Archive

Archive for the ‘Object Oriented Programming’ Category

Demeter is running

August 19, 2013 Leave a comment

I think that one of the widely ignored laws in in object oriented programming is the Law of Demeter (LoD).

Take the following real life scenario:

John needs $5. John goes to Jack, pulls out his wallet an opens it – and takes $5, than puts the wallet back in its palace.

Sounds bad – right? Now see it as a piece of code and think if you ever saw something like this in your source code:

public class Wallet
{
     private int amount;

     public Wallet(int amount)
     {
          this.amount = amount;
     }

     public int deposit(int sum)
     { 
         if (sum < 0) throw new IllegalArgumentException("sum must be non-negative");
         amount += sum;
         return amount;
     }
     public int withdraw(int sum)
     { 
         if (sum < 0) throw new IllegalArgumentException("sum must be non-negative");
         if (sum > amount) throw new InsufficiantFundsException("Insufficiant Funds!");
         amount -= sum;
         return amount;
     }
}

public class Person
{
     private string name;
     private Wallet wallet;

     public Person(String name, int moneyInWallet)
     {
          this.name = name;
          this.wallet = new Wallet(moneyInWallet);
     }

     public boolean requestLoanFrom(Person otherPerson, int amount)
     {
          int moneyFromOtherPerson = otherPerson.getWallet().withdraw(amount);
          this.wallet.deposit(moneyFromOtherPerson);          
          
          return true;
     }
}

public class Main
{
     public static void main(String [] args)
     {
          Person john = new Person("John", 10);
          Person jack = new Person("jack", 10);

          jack.requestLoanFrom(john,5);          
     }
}

The LoD relates to the fact that Jack knows John’s wallet – which it should not.

Now consider this implementation:

public class Person
{
     ...

     public boolean requestLoanFrom(Person otherPerson, int amount)
     {
          if (otherPerson.handleLoanRequest(amount))
          {
              this.wallet.deposit(amount);          
              return true;
          }
          else
          {return false;}                  
     }

     protected boolean handleLoanRequest(int amount)
     {
          // Do some validation ...
          wallet.withdraw(amount);     
          return true;
     }
}

Notice that each person is responsible for their own wallet – as it is in real life*.
*Note: I’m well aware this code is bad from the transaction POV – it is just to clarify the point.

To simplify things, the LoD states that this line of code is bad:

x = a.getSome().getThing();

It basically states that your code should be like:

public class A
{
   private Some some;

   public Thing getSomeThing()
   {
       this.some.getThing();
   }
}

public class Main
{
   public static void main(String ... args)
   {
      x = a.getSomeThing();
   }
}

I believe LoD is a useful guideline when developing Object Oriented software, but becoming too strict with it has a price.
In my experience – when you find it very hard to adhere to the LoD – you should review your design as you might be tight-coupling your system.

Advertisements
%d bloggers like this: