Wednesday, May 13, 2009

Can a boy scout be too eager?

The software craftsman movement tells us that as professionals we should strive to do our best. Among other things we should strive to write the cleanest code we can. One of the ways do that is to adopt the so-called Boy Scout Rule. When adapted to software development the Boy Scout Rule goes as follows:

Always leave the code cleaner than you found it

So what does that mean? Well, if I was to simply follow the rule exactly as stated I would always do my best to clean up all the code I came by as much as I could. That leaves me with (at least :-) two questions: Should I really clean up all the code I come across (no), and should I always clean the code as much as I possibly can (no, again). The following paragraphs gives you my thoughts on each question:

What should I clean?
Cleaning everything I come across obviously is not going to get me far: If I use open source library X in a project should I start by cleaning up all the code in X as much as I can? -I think not. Although X might very well be a good and sound project it will inevitably contain a considerable amount of not quite clean or downright dirty code. -Every code base of any significant size does.
So always cleaning up code before using it, would leave me stuck cleaning other peoples working code, while I could have started on my actual project. Not good.
Right, so if I am not going to clean up all the code I meet on my path, then where should I draw the line? I draw the line at code I change: If I change a line of code in a method, I clean up that method, and possibly the class containing it. If I change a couple of methods in class I clean up that class. If I make changes to a couple of interrelated classes I clean up their interaction.

How clean should it become?
In his Clean Code book Uncle Bob goes through an example of cleaning up a class from JUnit (chapter 15). The end result is very nice, and definitely cleaner than the original. But the original was actually pretty good in the first place. Even Uncle Bob thinks so: He writes: "[...] you'll find it [the JUnit code] to be nicely partitioned, reasonably expressive, and even simple in structure". And I agree, the original code is more than decent.
Throughout the chapter Uncle Bob carries on to clean up that code, and ends up with something very different from the original. The chapter ends with the following conclusion: "And so we have satisfied the Boy Scout Rule". I don't agree. Or rather, I think he has over-satisfied the Boy Scout Rule: The code is changed so much that it could be hard to recognize for the original author, which I think is a problem.
The original authors are (in my experience) more than likely to return to the code later. If they can recognize the code, they will probably be able do whatever fix they are there to do pretty quickly. If they cannot recognize the code their work will be a lot slower - even if the new code is cleaner. I think this consideration often outweighs the need to clean up code as much as possible.
Rather I think the quest for clean code should be an incremental endeavour where the code is left a little cleaner each time it's changed, but never changed radically in one go. Over time this incremental cleaning might very well change the code to the point of being unrecognizable to the original authors, but only if they have not followed or taken part in the incremental clean up. In that case they have effectively stopped particpating in the maintainance of the code, so slowing them down is not such a big deal.

Conclusion
We should, in general, strive for writing the cleanest code we can. The Boy Scout Rule helps us do exactly that, but don't be too eager: Don't clean up code you are not already changing for other reasons. And don't clean up code to the point of being unrecognizable. 

Monday, May 4, 2009

DCI in C#

The DCI, or the Data Context and Interaction is an approach to implementing domain logic and use cases in terms of the roles domain objects play at runtime. It is being developed and promoted by Trygve Reenskaug and James O. Coplien, who have written a very good introductory article about DCI at Artima.com. Here I'll stick to a very brief explanation and then jump into implementation of DCI in C#.

DCI at a Glance

I find that the DCI design is most easily understood in the context of Model View Controller. MVC, in its purest form, allows the end user to reach through the view, via the controller into the model and manipulate it directly. This is fine as longs the user is actually able to perform his tasks simply by massaging the domain objects. As soon as the application needs to support some sort of coordinated sequence of actions that the user is not allowed to control on his own,  something more is needed. Where is that control coded? Is it in the controller? Is it spread out between a number of domain classes? Is it in a business or service layer on top on the domain model? -DCI offers a different take:
DCI tells us to think in terms of three main concepts: The data captured in the domain model, the interactions between domain objects happening at runtime and the context in which the interactions happen. DCI also tells us to implement interaction in terms of roles: Domain objects take on different roles throughout the execution of an application. The interactions between domain objects happen in terms of these roles. The context of an interaction is the collection of runtime objects that will take part in the interaction, each referenced by role. The nice thing is that those coordinated sequences of actions are implemented directly in the role that will plays the lead part in the interaction. The context will provide the role with all the collaborators it needs. 
Right, enough explanation, the article mentioned above does a better job at explaning DCI anyway, so I'll just jump right into the C# code.

The C# Code

I'll walk through how the data, the context, and the role can be implemented in C#. To do this I'll use a simplistic banking example and implement a simplified money transfer use case in the role TranferMoneySource. The example is the same as the one used in the article linked above.
The domain model (i..e the D in DCI) consists of a savings account and an abstract account:

public abstract class Account
{
   public double Balance { get; protected set; }

   public void Withdraw(double amount)
   {
       Balance -= amount;
   }

   public void Deposit(double amount)
   {
       Balance += amount;
   }

   public void Log(string message)
   {
       Console.WriteLine(message);
   }
}

public class SavingsAccount 
    : Account, TransferMoneySource, TransferMoneySink
{
    public SavingsAccount()
    {
        Balance = 1000;
    }

    public override string ToString()
    {
        return "Balance " + Balance;
    }
}

The TransferMoneySource and TransferMoneySink are roles, and I'll get back to those. For now just notice that the roles must be interfaces, since the single inheritance of C# is used to extend the abstract Account.
The context (the C) in which the money tranfer use case is executed is the TransferMoneyContext:

public class TransferMoneyContext
{
    public TransferMoneySource Source { get; private set; }
    public TransferMoneySink Sink { get; private set; }
    public double Amount { get; private set; }

    public TransferMoneyContext(TransferMoneySource source,
        TransferMoneySink sink, double amount)
    {
        Source = source;
        Sink = sink;
        Amount = amount;
    }

    public void Execute()
    {
        Source.TransferTo(Sink, Amount);
    }
}

The context captures the objects necesarry to execute the money transfer use case in terms of the roles they play in that use case. I.e. the context captures the account that acts as source and the account that acts as sink. The context just holds on to these object until the Execute method is called. At that point the control is transferred to the role capable of running the use case - the source account.

Lastly the role implementation remains. The use case (the I) is captured in the role, and the role is attached to any number of domain objects.  As mentioned above the roles are interfaces, but they also need to implement the use case. This is achieved through extension methods attached to the role interfaces. This enables us to tie behaviour to interfaces, which is what we need in order to tie the use case implementation to the role, which in turn can be tied to any domain object. The roles are implemented like this:

 public interface TransferMoneySink
{
    void Deposit(double amount);
    void Log(string message);
}

public interface TransferMoneySource
{
    double Balance { get; }
    void Withdraw(double amount);
    void Log(string message);
}

public static class TransferMoneySourceTrait
{
    public static void TransferTo(
        this TransferMoneySource self,
        TransferMoneySink recipient, double amount)
    {
        // The implementation of the use case
        if (self.Balance <>
        {
            throw new ApplicationException(
                "insufficient funds");
        }

        self.Withdraw(amount);
        self.Log("Withdrawing " + amount);
        recipient.Deposit(amount);
        recipient.Log("Depositing " + amount);
  }
}

In essence the above usage of extension methods on interfaces emulates traits in C#.

DCI on .NET

While this offers one way of doing DCI on the .NET platform it is not the only way. There are also implementation in Python and Ruby. Attaching roles to objects is somewhat more straight forward in Ruby, where it is done by mixing a module specifying the a role into a domain object at runtime. With IronRuby maturing nicely, that could easily turn out to be the nicer DCI implementation for .NET.