Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thinking About Using Command Design Pattern

I have some code which updates a list of people to email. This list is updated often, with people being added and removed before the actual "send email" portion of the code is called. Currently my code to take care of this is something like this:

if (instructorEmailType == InstructorEmailType.AddToCourse)
{
    // If instructor not already in the list, then put them in.
    if (!this.InstructorsToEmail.ContainsKey(courseInstructor))
    {
        this.InstructorsToEmail.Add(courseInstructor, InstructorEmailType.AddToCourse);
    }
    else
    {
        // If instructor already in the list, and marked for removal, then get rid
        // of that entry from the list.
        if (this.InstructorsToEmail[courseInstructor] == InstructorEmailType.RemoveFromCourse)
        {
            this.InstructorsToEmail.Remove(courseInstructor);
        }
    }
}
else
{
    if (this.InstructorsToEmail.ContainsKey(courseInstructor))
    {
        this.InstructorsToEmail.Remove(courseInstructor);
    }
    else
    {
        this.InstructorsToEmail.Add(courseInstructor, InstructorEmailType.RemoveFromCourse);
    }
}

It's complicated and I don't like it. I've been thinking about implementing the Command design pattern instead. My idea what to create two commands:

  • SendAllocatedInstructorEmailCommand
  • SendDeallocatedInstructorEmailCommand

When an instructor is allocated to a course, then I would new-up a SendAllocatedInstructorEmailCommand and add it to CommandInvoker.SetCommand for later use. Likewise, I would create a SendDeallocatedInstructorEmailCommand object for those instructors who are taken off a course.

That is the problem.

If I've created a SendAllocatedInstructorEmailCommand object for Instructor A and later down the line Instructor A is deallocated from the course (before any data on the page has been saved, or emails sent), then I need to delete the SendAllocatedInstructorEmailCommand that I built earlier.

What is a clean way of searching for commands that already reference Instructor A, so that I can delete them? I can't use an Undo method on my commands since the emails will have been sent already via the SendAllocatedInstructorEmailCommand.

I was thinking of adding some kind of Query method to my CommandInvoker object, but I'm not sure if that is a poor plan.

Should I be using the Command design pattern at all? It does come across as a really nice way to queue these emails.

Cheers. Jas.

like image 420
Jason Evans Avatar asked Nov 14 '22 06:11

Jason Evans


1 Answers

I'd say you should keep your commands, just decouple them from sending any emails.

Your commands should be like IncludeInstructorEmail and ExcludeInstructorEmail, they should both implement one interface, like this

public interface ICommandOverEmailsList
{
    void ApplyToList(List<string> emailsList);
}

then the code in the main part would be like this:

List<string> emailsList = new List<string>();
foreach(var command in instructorEmailsCommandsQueue)
{
   command.ApplyToList(emailsList);
}
SendEmails(emailsList);

Of course, this assumes that the sequence of commands like "Exclude X, Include X" will leave the address X in the list. This seems to be different from your original code logic, but is it really required?

like image 112
Max Galkin Avatar answered Dec 06 '22 09:12

Max Galkin