Software Development

DRY != OAOO. Say it!

DRY != OOAO

DRY (Don’t repeat yourself) and  OOAO (Once and Only Once) are principles in Software Development used to advocate writing the smallest amount of code possible. Avoiding redundancy helps making code more understandable. A bug is fixed once. If you follow these principles, copy & paste is no longer needed.

Often, I have seen DRY and OAOO used synonymously. The similarity is obvious, but there is significant difference in detail.

The pitfalls of repetition

What does it mean for you as a developer not to repeat yourself? Interesting enough, the principle says “do not repeat yourself“, where it could say “do not repeat your code. Likewise, OOAO refers to saying everything once, not to writing code only once. I welcome this as an indication towards a focus on what I call semantic repetition instead of syntactical repetition. Sometimes two pieces of code are syntactically identical (or similar), yet semantically different. They happen to have the same or similar syntax accounting for distinct semantics.

Sample code

Have a look at this simple sample C# 4.5 code:

Code including repetition

    public class User
    {
        public String Name { get; set; }
        public String Email { get; set; }

        public static void Create(string name, string email)
        {
            User user = new User { Name = name, Email = email };
            MailMessage mail = new MailMessage("from@sender.com", email, "User Details created", String.Format("Your name has been set to {0}"));
            SmtpClient client = new SmtpClient("mailserver");
            client.Send(mail);
        }

        public void Update(string name, string email)
        {
            Name = name;
            Email = email;
            MailMessage mail = new MailMessage("from@sender.com", Email, "User Details updated", String.Format("Your name has been changed to {0}"));
            SmtpClient client = new SmtpClient("mailserver");
            client.Send(mail);
        }
    }

There are slight differences in the cases of update and create:

  • Where the email address is taken from (parameter or property)
  • Subject and notification text

Refactored code without repetition

        public static void Create(string name, string email)
        {
            User user = new User { Name = name, Email = email };
            Notify(email, "User Details created", String.Format("Your name has been set to {0}"));
        }

        public void Update(string name, string email)
        {
            Name = name;
            Email = email;
            Notify(Email, "User Details updated", String.Format("Your name has been changed to {0}"));
        }

        private static void Notify(string email, string subject, string body)
        {
            MailMessage mail = new MailMessage("from@sender.com", email, subject, body);
            SmtpClient client = new SmtpClient("mailserver");
            client.Send(mail);
        }

Let us think about what we have refactored for a second. We have extracted the three lines of boilerplate code which .NET wants from us to send an email. In other words: Had it been one line of code, would we still have extracted the code into its own method?

The importance of the O

If you say something twice or even more often, you will violate DRY. However, the difference to OAOO comes into play when we look closely at the first O in OAOO: Say everything once.

You have to at least say it, before you take care of not repeating it. That is the difference between DRY and OAOO: You cannot repeat something you have not even said.

This is one important message which Eric Evans is giving in Domain Driven Design. Say what you have to say, do not omit or imply logic which the domain requires.

Say it

Considering our example, the notification behavior in both cases might evolve differently in the future. We might want to add an attachment in one case. How about sending an SMS instead when the email address has changed?

So, have we said it all?

How about saying ConfirmDetailChanges() and WelcomeUserToSystem().

Now we have explicitly stated the two Domain Events. There is no second guessing about whether these two cases have a distinct significance in our Domain Model.

Real world code

Of course, nowadays nobody will invoke the notification in the object itself, let alone specifying the communication details in the same place. Probably, you will have a loosely coupled structure where an event will be fired and a different module will respond to the event by notifying the user. Also, since we mentioned Domain Driven Design, Update and Create is exactly not how you want to name your methods. Further, you might still decide to avoid repeating boilerplate code for sending emails. However, you would do this in the technical domain in some notification service, not in the business domain.

Summary

We already know that repetition is ineffective. What this article shows is that verifying whether you actually repeat yourself is very helpful. That will help you to avoid pseudo-generic code, which cannot serve the specific use cases at some point of requirement evolution. Domain Driven Design in the above example makes it easy to spot the difference between semantic and syntactic repetition, but the distinction is applicable also outside the context of the Domain Driven Design approach. Before you spend time trying to remove duplicate boilerplate code, make sure you say what needs to be said and try to avoid semantic repetition. Your domain logic exists only once, so do not write it twice.

1 reply »

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s