brad-neighbors edited this page Apr 4, 2012 · 6 revisions

Buildable wiki home.

What

  • A set of build-time Java annotations to support automatic creation of POJO Builder classes with fluent-api's.
  • A Java annotation processor that acts upon source files annotated with the supplied annotations to create POJO builder source files.

Why

Being a fan of Domain Driven Design, TDD and the book "Growing Object Oriented Software, Guided by Tests", I've worked on countless Java projects that exploited this little Builder-with-fluent-api pattern to great effect in unit tests.

If you're an OO practitioner, you'll likely subscribe to the notion that objects should only be able to be instantiated in a valid state (as opposed to creating w/ empty constructors and then "setting" them into validity). If you create rich domain objects that follow that notion, they are often difficult to easily set up with useful state as needed in a unit test.

Often, unit tests only care about certain state in a domain object- they may not care about some of the internal data in an object. Wouldn't it be nice to have an expressive, syntactically rich API that would allow easy instantiation of these objects, perhaps even with default state?

What's easier?

@Test public void usersUnder21AreUnderAge() {
   User underageUser = new User("Jane Doe", Sex.FEMALE, new Age(20), new ZipCode("94114"), State.CA, Country.US, new PhoneNumber("914-336-7000"), "other", "data", "this", "should", "probably", "be", "refactored");
   assertTrue("Users under 21 are underage", underageUser.isUnderage());
}

or

import static UserBuilder.aUser;

@Test public void usersUnder21AreUnderAge() {
    assertTrue("Users under 21 are underage", aUser().age(20).build().isUnderage());
}

It may seem subtle, but in some cases, where you may want to test rich interactions or message passing between objects with complex setup/instantiation logic, this can quickly get out of hand. The second example, using the pattern, makes things a lot easier- all you really care about is their age.

Now, this pattern does break encapsulation, in a big way, so one could effectively argue that these builders should only be available to testing classpaths, not to production code.

Example

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.