How to identify and fix an anaemic domain model

In most CRUD applications, classes consist of many accessor methods and few behaviour methods. It is often difficult for developers to recognise this as a symptom of an anaemic model.

Anaemic classes are characterised by having only methods for reading and for writing attributes. In addition to negating the benefits of object-oriented programming, such methods are cumbersome boilerplate code.

TDD helps us to identify anaemic domain models. According to TDD rules, usage code must be written before the implementation. By writing tests first, we anticipate how our classes will be used and can thus write only methods that are necessary. For example, consider an Account class with the following responsibilities.

  • represent a user account
  • hold information about a user (ie. username, password, email address, status)
  • used for authentication

One unit test for user authentication could be as follows.

assertTrue(account.getPassword().equals("testpassword"));

Here, we see that the responsibility for validating the password is actually fulfilled by the test. Recognising that this is not right, we decide to move it to the Account class.

Therefore, we change our unit test to the following.

assertTrue(account.hasPassword("testpassword"));

Now we see that the responsibility is rightly held by the Account class.

We create these simple tests to visualise how our classes will be used and how they must be refactored to not be anaemic. By repeating this process, we can gradually transform anaemic classes into classes with valuable behaviour.

In my experience, the following rules help to identify refactoring opportunities.

  • If calling code reads an attribute value from an object, tests it, then calls another method on the same same object, the behaviour must be moved to the object.
  • Getters and setters must not be implemented mindlessly; instead, they must be written only when they are appear in unit tests.
  • Daisy-chain calls to methods of the same object indicate that the object is anaemic and needs more behaviour methods.

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.