We need to talk about Refinement

stormy waters

I’ve been working with a scrum team for the last few months, and the team is storming (1) on ‘how we do refinement’.

Here’s what the scrum guide says about refinement:

Product Backlog refinement is the act of adding detail, estimates, and order to items in the Product Backlog. This is an ongoing process in which the Product Owner and the Development Team collaborate on the details of Product Backlog items. During Product Backlog refinement, items are reviewed and revised. The Scrum Team decides how and when refinement is done. Refinement usually consumes no more than 10% of the capacity of the Development Team. However, Product Backlog items can be updated at any time by the Product Owner or at the Product Owner’s discretion. (2)

Context

This scrum team works on a combination of production support issues and a backlog of product updates. The product is a mature, complex web application with UI flows, calculation engines, and multiple external system integrations. So, it’s a complex technical environment, nothing new there.

The main focus of this team is to work on a backlog of small to medium sized features. The team works on many features at a time, so there are generally pairs or threes in the team working on delivering these features, inside a single sprint.

However, this scrum team also has Service Level Agreements with a high profile external client, which means we need to respond quickly and frequently to unplanned tasks.  In addition, this sometimes means we use refinement sessions to plan new issues that are either urgent, or important… or both (the doomsday scenario!) (3)

In addition, the team also responds to requests from internal stakeholders, and these are requests for features or enhancements from other departments inside the organisation.

The development team is quite large: 7 Dev, 4 QA, PO, SM.

Across the organisation, there is a prevailing culture that refinement should happen during a meeting in the sprint, with the whole team attending.

However, our team have requested that we manage this time better, so that they can avoid unnecessary meetings where possible, and remain more focused on Sprint tasks. This seems like a totally reasonable request to me, so we have been trying to modify how we do refinement in recent sprints.

Bored-employees-at-a-business-meeting

What we’ve tried so far

I’ve been working with the team’s Product Owner, and we have tried to prepare an agenda for upcoming refinement sessions.

That is, we list out the next product backlog items that the PO would like to refine, and publish it to the team as early as possible before refinement.

Then, we book a session in a meeting room, and make a rough attempt to time-box the session. The main goal is to try not to include too much.

Our intention is to show this to the team in advance of refinement, to allow time to review and prepare, but also to allow team members to manage their time, and, for example, avoid refinement sessions that are irrelevant.

There are trade-offs here, naturally. I would love the team to be sitting together happily, and sharing knowledge about problem resolutions with each other, but their reality is different from that.

Boiling it down to questions

With all this in mind, I have a few questions I’d love to get some input on:

  1. As a scrum master or product owner, how do you ‘do refinement’ in the teams you work with? Is it a meeting with the whole team invited, or is it multiple breakout sessions? Should I challenge the team to attend together, despite their frequent complaints about refinement swallowing time?
  2. Also, from the context I’ve described, am I missing something that could be the real problem here? Are our problems with refinement a symptom rather than a problem? Even as I write this I am looking at things like the size of the team, the combination of planned and unplanned work…

What do you think?

 

References / Links

(1) Tuckman’s Stages of Group Formation

(2) The Scrum Guide

(3) Eisenhower’s time management matrix

There and Back Again

There and Back Again

A near four year publishing hiatus probably deserves some explanation. (Also, what the hell? Where did those four years go!?)

As some justification for some of the time off, here is a link to something I wrote while I was on my two year career break from Software Development, working in China. It’s a blog post featured in the Irish Times website. (While I was there, I wrote a few other bits and pieces as well).

So, I went to China to teach, spent two years there, and now I’m back here again. Back in the land of Software Development, squarely in the ranks of Agile projects with all of their struggles.

Right now though, as I type, here is not Ireland. Right now, I’m in Orlando, Florida at the Agile Dev East conference. I’ve been here for the last four days, and it has been really great.

agiledeveast

Since my return to a software development role, I’ve been working on some really challenging projects, in an ambitious and volatile organisational context. Perhaps that’s why it was so inspiring this week to be reminded by a large room full of smart and empathetic folks that those challenges are not unique. Scrum Master, developer, tester, Product Owner, manager… you are not alone!

It has been humbling and motivating to listen to speakers who have been on similarly challenging projects in similar organisations to mine, and come out the other side better for the experience.

It has been inspiring to listen to, meet and chat with software development professionals in the wider world of agile who are delivering quality products, and evolving the way agile and scrum can help teams at the same time.

Most of all though, it’s been great to get the sense of the community around agile, and how those folks are developing and pushing the frameworks and tools forward, shaping them into more relevant and useful forms for the future.

As you can probably tell by now, I enjoyed the conference, so I guess the main point of this post is to announce that I’m going to blog here again very soon. I have two or three posts bouncing around in my head that I’d like to share over the next few weeks, and hopefully they represent the most useful things that I picked up at Agile Dev East. Some ideas just need to be shared, for the win. Hopefully you’ll find them useful too.

The Stress Trap

This is an interesting review of a book by Dana Becker: “One Nation Under Stress”. The review was written by Alexander Nazarayan on NewRepublic.com.

http://www.newrepublic.com/article/112589/one-nation-under-stress-dana-becker-reviewed#

The article also references this New York Times op-ed about the potential trap of holding onto stress as a kind of modern status symbol:

I initially disagreed with the latter article, but it has been on my mind since! Maybe this guy has a point…

Drive and Scrum

ImageDan Pink’s ‘Drive‘ is an insightful demolition of common assumptions related to motivation theory, and will be of interest to you if you have ever asked the question “what do I really want to do with my career?”.

Indeed, if you are a manager yourself, or if you’ve ever been interested in management, you’ll also find this book relevant and insightful.

I studied business back in the day, and always enjoyed the sprinkling of psychology in certain subjects, particularly in Behavioural Science, so the theory of motivation is an interesting topic for me. In addition, as I’ve recently taken on a Scrum master role, I found it very relevant to the scrum practices I’m working with on a day-to-day basis.

Premise

Pink’s premise is that, when it comes to motivation in particular, there’s a gap between the practices of managers and the findings of recent scientific research. For instance, while managers persist in attempting to get people working with the promise of rewards once a task is completed, science is proving that this practice actually hinders chances of success, especially when we look at any time-frame longer than the short term. In particular, when a task involves cognitive effort or creativity, the direct connection to a reward actually hampers creativity, and removes enjoyment from the task: science has proven this (1). Pink argues that business seems to be ignoring it.

As an alternative to ‘if-then’ rewards, Pink suggests that managers of teams that perform creative work should first remove the issue of financial rewards from the discussion table, and then work at creating three things in their team’s working environment. Those three things are autonomy, mastery and purpose. My own belief is that the scrum practices (2) have embedded these three elements, and that there is not so wide a gap between what science knows and what scrum does.

scrum

Autonomy is a big part of Scrum practices. Scrum acknowledge that the team are the experts, and strives to give a team of experts the autonomy to decide how the product will be built. In addition, the concept of self-organising teams is fundamental to scrum, and in this context, the scrum master is more like a facilitator than a traditional chief or ‘boss’.

I have recently moved into a scrum master role, and it can be a difficult role to explain to those unfamiliar with the world of Scrum. Being made a scrum master initially seems like a promotion to Team Leader, but that is not an accurate description of the role. Rather, “a Scrum Master is a servant leader helping the team be accountable to themselves for the commitments they make” (3) The team make commitments before a sprint, and the role of the scrum master is to remove impediments to the achievement of those commitments during the sprint. Effectively, the scrum master’s prime directive is to protect the autonomy of the team.

The path to mastery in any domain requires huge effort, it is paved with many mistakes, and it takes an unpredictable amount of time. Some say it takes 10,000 hours (4). On the other hand, others say that the path to mastery requires humility, as you can never actually fully achieve mastery: there is always more to learn. (5)

path

Although the role is called scrum master, the person in the role is not assumed to have fully mastered the practices and values of scrum. Instead, it is perhaps more appropriate to think of the scrum master as a coach, or as an evangelist, someone who retains a process view of the work done by the team, and ensures the scrum practices are applied in order to help the team perform to the highest level possible.

Mastery implies that you have chosen a profession that lets you do what you do best, and that you are striving to better yourself and improve your abilities. Anyone who has worked in software will know that some of the language used to describe levels of expertise is at times incongruous, synonymous instead with the world of martial arts perhaps. (Ever worked with a ‘guru’?) In my own experience, developers are all at different points on their own journey towards mastery of their domain, and the best people to work with are those who are hungry to learn and continuously striving to improve their abilities.

On the path towards mastery, short-term goals are useful, but are ultimately insufficient to guarantee commitment to the long road ahead. Especially when starting out, a commitment to a purpose is also required in order to ensure perseverance. Scrum embraces the need for purpose with the notion of vision. The practices of scrum assume that the product owner has a long term vision of the product, and keeps the scrum team informed of this longer term vision. (8) Part of the role of the scrum master is to ensure that the commitments of the team are always aligned with the priorities implied by that vision. To achieve this, regular contact with the  product owner is essential during sprints, and also in the regular sprint review meetings.

farside Edgar finds his purpose

Summary

Dan Pink’s book Drive is a great read, and presents a compelling argument that there is a gap between what science knows and what business does in relation to motivation. Pink argues that businesses are incorrect to persist with ‘if-then’ rewards (for example, if you achieve this sales target, then you will get a bonus of 5%) to drive people to achieve goals, as this type of goal encourages a short-term view, and hampers creativity.

For creative work such as software development, Pink’s suggests that an alternative to traditional ‘if-then’ rewards is required. He suggests to first resolve any outstanding financial matters related to rewards, so as to remove them from the discussion table, and then to create an environment that promotes autonomy, mastery and purpose. He proposes these three values as key to motivation in a creative working environment.

In my recent experience as a scrum master, I believe the scrum framework genuinely embeds these values into the culture of  software development teams. Since reading his book, and with this recent experience in mind, I can only conclude that when it comes to motivation, there’s not so big a gap between what science knows and what scrum does.

References:

1. Research that rewards hamper creativity

http://en.wikipedia.org/wiki/Candle_problem

2. Scrum.org’s Definition of Scrum:

http://www.scrum.org/Resources/What-is-Scrum

3. Bob Hartman, “What Does the Scrum Master do anyway?”

http://www.agileforall.com/2009/09/23/new-to-agile-what-does-the-scrummaster-do-anyway/

4. Malcolm Gladwell’s controversial 10,000 hour rule:

http://www.gladwell.com/outliers/outliers_excerpt1.html

5. George Bradt’s spin on Mastery from Forbes.com:

http://www.forbes.com/sites/georgebradt/2012/11/08/beyond-10000-hours-the-constant-pursuit-of-mastery/

6. Mike Cohn’s definition of the Scrum Master role:

http://www.mountaingoatsoftware.com/scrum/scrummaster

7. Mike Cohn, six attributes of a good scrum master:

http://www.mountaingoatsoftware.com/articles/leader-of-the-band

8. Roman Pichler, “The Product Vision”, Scrum Alliance:

http://www.scrumalliance.org/articles/115-the-product-vision

9. Drive, by Dan Pink, available on the Book Depository

http://www.bookdepository.co.uk/Drive-Daniel-Pink/9781847677693

Quiet: The Power of Introverts

It may surprise you to hear that up to 30% of the world identifies as introverted. Susan Cain’s ‘Quiet’ is a thoughtful paean to introverts and an insightful examination of this less vocal personality type. (You’ve got to watch the quiet ones!)

Initially, Cain discusses how popular culture has evolved to a point where the extroverted, gregarious personality type has become a prized ideal, even a cultural more in Western cultures. The author also discusses the difficulties with which introverts manage to get by in this extrovert-oriented environment. In addition, she has some advice to offer the introverted types out there.

 

The Extrovert Ideal
For software developers, the idea that gregarious personalities are more likely to succeed will not come as a shock. In software development, technical work alone is not enough to guarantee success: publicity and public relations skills are also required to make sure your awesome work is visible to others, and crucially, that its benefits are understood. These kind of skills do not always come naturally to developers however.

“The extrovert ideal – the omnipresent belief that the ideal self is gregarious, alpha, and comfortable in the spotlight”

One of the early ideas presented in Cain’s book is that western cultures have evolved to prize the good talker, the fast thinker, the hail-fellow-well-met who gives a good public account of himself. However, it is interesting to note that in other cultures, this is not always true, and that even in Western cultures, this has not always been the case either.

The professional environment does not provide the only favourable habitat for the gregarious individual. In education too, the increasing prevalence of group work also favors the extroverted person. Successful participation in group work is seen as a good indicator of likely success in the ‘real world’.

However, even if those who do well in pressurized group discussions may be more able to dominate a conversation to promote their ideas, the notion that this skill is a clear indicator of a successful person is not necessarily true for all professions. Moreover, for the introverted person, the group discussion can be a more difficult context within which to make a meaningful contribution. If success if measured by performance in this context, then, Cain argues, introverts are at a natural disadvantage.

“It’s not that I’m so smart, it’s just that I stay with problems longer.”

Albert Einstein

In fact, many successful introverts often prefer working alone. Steve Wozniak, co-founder of Apple, learned his trade by working on engineering projects by himself, giving himself the time to focus on the areas he didn’t understand, and making his own creative leaps towards solving problems. His advice to engineers is unequivocal:

“If you’re that rare engineer who’s an inventor and also an artist, I’m going to give you some advice that might be hard to take. The advice is: work alone.”

Steve Wozniak

The only problem with this advice is, many careers depend on the ability to be a team player. By declaring an interest in working alone, are introverts hurting their chances to get ahead?

 

Faking it: Free Trait Theory

There is an open debate in psychology theories regarding the nature of personality: the ‘person-situation’ debate centers around one important question. Is our personality based on fixed traits, or is it something more transient, adapting to suit the various situations we find ourselves faced with? This debate poses some interesting questions for most of us. For example, do we behave the same way in the office as we do at home? And for introverts, is it ok to pretend to be an extrovert?

“To thine own self be true”

William Shakespeare: Hamlet, Act I, Scene III

‘Quiet’ presents a theory as to why introverts can in fact prevail in an extrovert-oriented context. Free Trait Theory argues that, although introverts are naturally predisposed to avoid the spotlight, they can in fact force themselves to act extroverted, if doing so allows them to achieve a higher goal, something Cain identifies as a ‘core personal project’. If acting in service of this goal, Cain argues, introverts can push through the pain barrier, and find themselves acting in very extroverted ways. (This might even explain how Woz, a card-carrying introvert, managed to find himself on ‘Dancing With The Stars’…!)

It can also go some ways toward explaining the introvert who becomes a successful public speaker in the interest of advancing her career, or the tortured singer who forces himself on stage one more time. Introversion is a strong indicator of personality and behaviour, but it can be overcome if the required behaviour is in support of a loftier purpose.

 
Finally, Some Practical Advice For Introverts

Select a ‘core personal project’. Think back to what you loved to do when you were a child and pay attention to the work you gravitate to. Acting in the service of this personal project will make it easier for introverted types to ‘fake it’ when required.

Find ‘restorative niches’. These are spaces where you can relax and recharge your batteries. These can be anything from a quiet spot to spend a few minutes at lunchtime, activities that you enjoy, or simply situations where you feel more comfortable. In a work situation, an introvert can thrive in an extrovert-friendly environment if there are sufficient restorative niches available.
 
So, for all the extroverts, introverts and ambiverts out there (yes, that word does exist!), ‘Quiet’ is an excellent read, well researched, and with plenty of insights to offer.

 
Some References

Fluent Java APIs II: The MockBuilder Pattern

Context

  • In a TDD environment, the same coding standards should be enforced on Unit Test code as on application code. Often, however this isn’t the case! Remember: unit tests can contain technical debt too!
  • Mocking service calls with EasyMock involves repetitive code.
  • This repetitive code can be simplified, and rendered more fluent with the Builder pattern.

Benefits of a MockBuilder

  1.   Sharpened focus: unit tests becomes more focussed on the code under test , rather than code written to support or prepare the test.
  2. Cheaper to write more and more tests.

First Iteration: mocking a service call to the ClientService with EasyMock

Consider an example of a unit test where there is a call to the ClientService that we want to replace with a call to a Mock:

@Test
public void testLoadPresetFormWithClient() throws RemoteException {

    NewBusinessApplication nba = NewBusinessApplicationBuilder.create()
    .withPresetOwner()
    .build();

    nba.getOwner().setRegisteredAddress(null);
    nba.getOwner().setClientNumber("12345678");

    Client stubbedClient = new Client();
    stubbedClient.setAddress(new Address());
    stubbedClient.getAddress().setLine1("Client Address 1");
    stubbedClient.getAddress().setLine2("Client Address 2");
    stubbedClient.getAddress().setLine3("Client Address 3");
    stubbedClient.getAddress().setLine4("Client Address 4");
    stubbedClient.getAddress().setLine5("Client Address 5");

    ClientService mockClientService = EasyMock.createMock(ClientService.class);
    EasyMock.expect(mockClientService.findByClientNumber((String)EasyMock.anyObject())).andReturn(stubbedClient).anyTimes();
    EasyMock.replay(mockClientService);
    EasyMock.verify(mockClientService);

    ClientServiceDelegate.getInstance().setClientService(mockClientService);

    EmployerCorrespondenceDetailsForm form = service.loadPresetForm(nba);

    assertFormAndClientRegisteredAddressEquals(form,mockClientService.findByClientNumber("12345678"));

    assertFormAndApplicationBusinessAddressEquals(form,nba);
}

The vast majority of the code in this unit test is support code, written to mock the client service call, and ensure a stubbed client is used for the purposes of the test.

In fact , only the last three lines of this test method are actual test code, executing the method under test, and evaluating the results

Second Iteration: Create ClientServiceMockBuilder

All the semi-boilerplate EasyMock code related to mocking the client service is now moved to it’s own object, where the builder pattern is implemented:

public class ClientServiceMockBuilder {

    private ClientService mockClientService;

    public static ClientServiceMockBuilder create() {
        return new ClientServiceMockBuilder();
    }

    public ClientService build() {
        EasyMock.replay(mockClientService);
        EasyMock.verify(mockClientService);
        return mockClientService;
    }

    private ClientServiceMockBuilder() {
        mockClientService = EasyMock.createMock(ClientService.class);
    }

    public ClientServiceMockBuilder withFindByClientNumberStubbedClient(){
        try{
            EasyMock.expect(mockClientService.findByClientNumber((String)EasyMock.anyObject())).andReturn(createStubbedClient()).anyTimes();
        }   catch(RemoteException e){
            throw new RuntimeException(e);
        }
        return this;
    }

    private Client createStubbedClient(){
        Client client = new Client();
        client.setAddress(new Address());
        client.getAddress().setLine1("Client Address 1");
        client.getAddress().setLine2("Client Address 2");
        client.getAddress().setLine3("Client Address 3");
        client.getAddress().setLine4("Client Address 4");
        client.getAddress().setLine5("Client Address 5");
        return client;
    }

}

Revisiting the Unit Test, it is now a lot cleaner, and more readable. More to the point though, we are pointing the way to any unit test that needs to mock a call to the Client Service:

@Test
public void testLoadPresetForm_WithClient() throws RemoteException {

    NewBusinessApplication nba = NewBusinessApplicationBuilder.create()
     .withPresetOwner()
     .build();

    nba.getOwner().setRegisteredAddress(null);
    nba.getOwner().setClientNumber("12345678");

    ClientService mockClientService = ClientServiceMockBuilder.create()
     .withFindByClientNumberStubbedClient()
     .build();

    ClientServiceDelegate.getInstance().setClientService(mockClientService);

    EmployerCorrespondenceDetailsForm form = service.loadPresetForm(nba);

    assertFormAndClientRegisteredAddressEquals(form,mockClientService.findByClientNumber("12345678"));

    assertFormAndApplicationBusinessAddressEquals(form,nba);
}

Third Iteration: Abstract out common MockBuilder behaviour

If your unit test code involves the use of many different mocked objects, you’ll be building a lot of MockBuilder objects to correspond with these. You’ll also quickly notice repetition of certain code, which can be abstracted to an abstract parent class called MockBuilder, as below:

public abstract class MockBuilder<T extends Object> {

    protected T mockedObject;

    public T build() {
        EasyMock.replay(mockedObject);
        EasyMock.verify(mockedObject);
        return mockedObject;
    }

}

The updated ClientServiceMockBuilder now looks like this:

public class ClientServiceMockBuilder extends MockBuilder<ClientService> {

    public static ClientServiceMockBuilder create() {
        return new ClientServiceMockBuilder();
    }

    private ClientServiceMockBuilder() {
        mockedObject = EasyMock.createMock(ClientService.class);
    }

    public ClientServiceMockBuilder withFindByClientNumberStubbedClient(){
        try{
            EasyMock.expect(mockedObject.findByClientNumber((String)EasyMock.anyObject())).andReturn(createStubbedClient()).anyTimes();
        }   catch(RemoteException e){
            throw new RuntimeException(e);
        }
        return this;
    }

    private Client createStubbedClient(){
        Client client = new Client();
        client.setAddress(new Address());
        client.getAddress().setLine1("Client Address 1");
        client.getAddress().setLine2("Client Address 2");
        client.getAddress().setLine3("Client Address 3");
        client.getAddress().setLine4("Client Address 4");
        client.getAddress().setLine5("Client Address 5");
        return client;
    }

}

And we can extend the MockBuilder again as required. For example, here’s another implementation, a Spring MVC BindingResultMockBuilder

public class BindingResultMockBuilder extends MockBuilder<BindingResult> {

    public BindingResultMockBuilder() {
        mockedObject = EasyMock.createMock(BindingResult.class);
    }

    public static BindingResultMockBuilder create() {
        return new BindingResultMockBuilder();
    }

    public BindingResultMockBuilder withErrors(boolean hasErrors) {
        EasyMock.expect(mockedObject.hasErrors()).andReturn(hasErrors).anyTimes();
        return this;
    }

    public BindingResultMockBuilder withAddAllErrors() {
        mockedObject.addAllErrors((Errors) EasyMock.anyObject());
        EasyMock.expectLastCall().anyTimes();
        return this;
    }

    public BindingResultMockBuilder withGetAllFieldErrors() {
        EasyMock.expect(mockedObject.getFieldErrors()).andReturn(new ArrayList<FieldError>()).anyTimes();
        return this;
    }

    public BindingResultMockBuilder withRejectValue() {
        mockedObject.rejectValue((String) EasyMock.anyObject(), (String) EasyMock.anyObject());
        EasyMock.expectLastCall().anyTimes();
        return this;
    }
}

Results

  1. The MockBuilder can be extended to create a new subclass for anything you need to mock.
  2. Large amounts of boilerplate code can be refactored into a simpler invocation of a Builder.
  3. Cleaner Unit Tests = Better Unit Tests.

Fluent Java APIs I: The Builder Pattern

On February 23rd, PaddyPower hosted their inaugural technology series event, anchored around an excellent presentation on Java coding practices given by John Ferguson Smart – a Java and TDD expert. Smart’s presentation focussed on specific Java best practices, with the noble goal of more readable, more maintainable and more testable code.

A number of techniques that Smart was pushing were in the area of Fluent APIs. I’ve been using a few of them since the talk. In this blog post – and maybe one or two more – I’ll describe some of them in detail. I’ll be using a sandbox Github project to code up these examples, so you can access the code via Github here (with Git or SVN).

Right, let’s start with an initial application of the Builder pattern.


The Builder Pattern

Consider the following Contract object, a reasonable facsimile of a contract object you might see in a Life Assurance system:


public class Contract {

 private String contractNumber;
 private Date commencementDate;

 private Product product;

 private ContractStatus contractStatus;

 private Client[] contractOwners;
 private Client[] livesAssured;

 private BillingMethod billingMethod;

 public Contract() {
 }

 public Contract(String contractNumber, Date commencementDate, Product product, ContractStatus contractStatus, Client[] owners, Client[] livesAssured, BillingMethod billingMethod) {

     this.contractNumber = contractNumber;
     this.commencementDate = commencementDate;
     this.product = product;
     this.contractStatus = contractStatus;
     this.contractOwners = owners;
     this.livesAssured = livesAssured;
     this.billingMethod = billingMethod;
 }
 ...
}

The traditional way to construct this object could be as with the below, long method:

public class NewContractController {

 public Contract createNewContract(NewContractForm form) {

     Contract contract = new Contract();
     contract.setContractNumber(form.getContractNumber());
     contract.setCommencementDate(form.getCommencementDate());
     contract.setContractOwners(new Client[]{form.getFirstOwner(), form.getSecondOwner()});
     contract.setLivesAssured(new Client[]{form.getFirstLifeAssured(), form.getSecondLifeAssured()});
     contract.setProduct(form.getProduct());
     BillingMethodTypes thisBillingMethodType = Enum.valueOf(BillingMethodTypes.class, form.getBillingMethod());
     BillingMethod billingMethod = new BillingMethod(thisBillingMethodType);
     contract.setBillingMethod(billingMethod);

     return contract;
 }
...
}

The above code is fit for purpose, but it certainly isn’t easy to read. Here’s how it looks after a first sweep of refactoring:

public Contract secondCreateNewContract(NewContractForm form) {

  Contract contract = new Contract();
  contract.setContractNumber(form.getContractNumber());
  contract.setCommencementDate(form.getCommencementDate());
  contract.setContractOwners(getOwners(form));
  contract.setLivesAssured(getLivesAssured(form));
  contract.setProduct(form.getProduct());

  BillingMethod billingMethod = BillingMethodBuilder.create()
     .withType(form.getBillingMethod()).build();
  contract.setBillingMethod(billingMethod);

  ContractStatus contractStatus = ContractStatusBuilder.create()
    .withType(form.getContractStatus()).build();
  contract.setContractStatus(contractStatus);

  return contract;
 }

This new version is an improvement. We’re getting the owners and lives assured in separate methods, and we’ve introduced a couple of builders,for billing method and contract status.

Let’s look at just one of those builders in more detail:


package com.sandbox.builder;

import com.sandbox.model.billing.BillingMethod;
import com.sandbox.model.billing.BillingMethodTypes;

public class BillingMethodBuilder {

 private BillingMethod billingMethod;

 public static BillingMethodBuilder create() {
     return new BillingMethodBuilder();
 }

 public BillingMethodBuilder withType(String billingMethodType) {
     BillingMethodTypes thisBillingMethodType = BillingMethodTypes.valueOf(billingMethodType);
     billingMethod.setBillingMethodType(thisBillingMethodType.getType());
     billingMethod.setBillingMethodDescription(thisBillingMethodType.getDescription());
     return this;
 }

 private BillingMethodBuilder() {
     this.billingMethod = new BillingMethod();
 }

 public BillingMethod build() {
     return billingMethod;
 }

}

As you can see, we use a static create method to call a private constructor, and the build method returns the object we are building. In between the create and the build, we have a method name starting with ‘with’. What this means is, when we use this builder, we write a more English-looking line of code: build x, with y. Also, you could probably already see how this builder could be extended, especially for a more complex object.

With this in mind, we can return to our contract creation method, refactor each of these builders to it’s own method, and go one step further: the ContractBuilder:

public Contract finalCreateNewContract(NewContractForm form) {

 Contract contract = ContractBuilder.create()
    .withContractNumber(form.getContractNumber())
    .withCommencementDate(form.getCommencementDate())
    .withStatus(getContractStatus(form))
    .withOwners(getOwners(form))
    .withLivesAssured(getLivesAssured(form))
    .withBillingMethod(getBillingMethod(form))
    .build();

 return contract;
}

Benefits of the Builder

This code reads more naturally than the first attempt using constructors, but it’s worth remembering, this builder also gives a more flexible API. Remember, the constructors of the Contract object only gave us two options: default-constructor-plus-setters, or the pass-all-members option. You could imagine any number of constructors in the Contract object, to cater for different combinations of members, depending on different requirements. Each new constructor makes the Contract API more difficult to interpret for the next guy who needs to use it. By contrast, the builder understands implicitly that you might only need a contract with some of its building blocks, and allows you to create some, none, or all of them.

By extension, if we accept that the builder is the way to access the Contract across our codebase, we can remove all non-default constructors from the Contract object, and remove a lot of complexity from the API.

I’ve been using the Builder pattern a lot in the last few weeks, particularly in unit tests, and so far I’m finding it genuinely makes code more readable.

Note: as mentioned above, the code for this demo is available on GitHub here:
https://github.com/PaddyC/FluentApiSandbox

The next post will look at an application that uses the builder to create Mock objects.