Wednesday, May 28, 2014

Law of Demeter in Java - Principle of least Knowledge - Real life Example

Law of Demeter also known as principle of least knowledge is a coding principle, which says that a module should not know about the inner details of the objects it manipulates. If a code depends upon internal details of a particular object, there is good chance that it will break as soon as internal of that object changes. Since Encapsulation is all about hiding internal details of object and exposing only operations, it also assert Law of  Demeter. One mistake many Java programmer makes it exposing internal detail of object using getter methods and this is where principle of least knowledge alerts you. I first come to know about this principle, while reading one of the must read programming book,  Robert C. Martin's Clean code. Apart from many good thing the book teaches you, "principle of least knowledge" is one principle, which I still remember. Like many bad things, you will tempt to violate Law of Demeter, because of beautiful chaining of methods written in fluent style. On surface it looks pretty good, but as soon as you think about principle of least knowledge, you start seeing the real picture. In this article, we will see formal definition of Law of Demeter and explore code snippet which violates this principle.


Law of Demeter

According to Law of Demeter, a method M of object O should only call following types of methods :

  1. Methods of Object O itself
  2. Methods of Object passed as an argument
  3. Method of object, which is held in instance variable
  4. Any Object which is created locally in method M
More importantly method should not invoke methods on objects that are returned by any subsequent method calls specified above and as Clean Code says "talk to friends, not to strangers". Apart from knowing object oriented programming basic concepts e.g. Abstraction, Polymorphism, Inheritance and SOLID design principle, it's also worth knowing useful principle like this, which has found it's way via experience. In following example, we will see how a method can violate above rules to violate Law of Delimiter.

public class LawOfDelimterDemo {

    /**
     * This method shows two violations of "Law of Delimiter" or "Principle of least knowledge".
     */
    public void process(Order o) {

        // as per rule 1, this method invocation is fine, because o is a argument of process() method
        Message msg = o.getMessage();

        // this method call is a violation, as we are using msg, which we got from Order.
        // We should ask order to normalize message, e.g. "o.normalizeMessage();"
        msg.normalize();

        // this is also a violation, instead using temporary variable it uses method chain.
        o.getMessage().normalize();

        // this is OK, a constructor call, not a method call.
        Instrument symbol = new Instrument();

        // as per rule 4, this method call is OK, because instance of Instrument is created locally.
        symbol.populate(); 
    }
}

You can see that when we get internal of Order class and  call a method on that object, we violate Law of delimiter, because now this method knows about Message class. On the other hand calling method on Order object is fine because its passed to the method as parameter.  This image nicely explains what you need to do to follow Law of Demeter.



Let's see another example of code, which violates the Law of Demeter and how does it affect code quality.

public class XMLUtils {
   public Country getFirstBookCategoryFromXML(XMLMessage xml) { 
       return xml.getXML().getBooks().getBookArrary(0).getBookHeader().getBookCategory();
   }
}
This code is now dependent upon lot of classes e.g.
    XMLMessage
    XML
    Book
    BookHeader
    BookCategory

Which means this function knows about XMLMessage, XML, Book, BookHeader and BookCategory. It knows that XML has list of Book, which in-turn has BookHeader and which internally has BookCategory, that's a lot of information. If any of the intermediate class or accessor method in this chained method call changes, then this code will break. This code is highly coupled and brittle. It's much better to put the responsibility of finding internal data into the object, which owns it. If we look closely, we should only call getXML() method because its method from XMLMessage class, which is passed to method as argument.  Instead of putting all this code in XMLUtils, should be putting on BookUtils or something similar, which can still follow Law of Demeter and can return the required information.

That's all on this example of Law of Demeter or "Principle of least knowledge". It's better not to have a chain of methods, originating from unknown object, which may change. I also suggest to read Chapter 6 of Clean Code, a must read book for any software developers.

Want to read more on design principles and patterns? Check out these amazing articles

  • Real life example of Open Close design principle in Java. (read here)
  • How to use Decorator pattern in Java? (read here)
  • When to use Builder pattern in Java? (read here)
  • How double checked locking of Singleton works in Java? (see here)
  • Observer Pattern in Java with Example (see here)
  • Difference between Factory and Abstract Factory pattern in Java? (see here)
  • When to use Factory method pattern? (see here)
  • Difference between Strategy and State design Pattern? (check here)
  • Why Enum as Singleton is better pattern? (check here)
  • Difference between Singleton and Static class in Java? (check here)
  • How to create thread-safe Singleton in Java? (link)
  • 20 Software design and pattern Interview question for Java programmer? (link)
  • Dependency Injection and Inversion of Control in Java (link)
  • How to make a class Immutable in Java? (link)

4 comments :

Anonymous said...

Law of Demeter is all about "asking things it really needs, instead of asking some thing and then getting things it really need from that". Follow example will make this clear :


// voilate Law of Demeter
public Book(AuthorRepository repository, String isbn){
AuthorLocator locator = repository.getAuthorLocator();
this.author = locator.getAuthor(isbn);

}

// follows Law of Demeter
public Book(AuthorRepository repository, String isbn){
this.author = repository.getAuthor(isbn);

}

Pubby said...

I would like highlight here that otherwise popular ServiceLocator pattern actually violates "Law of Demeter". In code, where you use ServiceLocator to find dependency, what essentially you are doing is "Instead of asking for things you really want, you are asking a service locator and then retrieving things you really want". ServiceLocator is still better than Singleton, but you can see it violates "Law of Demeter", which is to reduce coupling between classes.

chand31290 said...

do u think that getting Column count from ResultSet violates law of delimiters?
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int colCnt = resultSetMetaData.getColumnCount();

Anonymous said...

I think main advantage of Law of Demeter comes from the fact that it promots testable code. Once you start voilating Law of Demeter, you invite dependencies to us which makes unit testing hard. For example, if you have to check a method which validates Zipcode, ideally you would like to pass him ZipCode, instead of passing Person, so that he call getAddress().getZipCode() because in that case, you need to create a Person, popular that with Address with ZipCode, lot of boiler plate code there. In later case, you just need to mock ZipCode class, a much easy way to test the method.

Post a Comment