DESIGN PATTERNS SAGA #2: REAL PROJECT SITUATIONS WITH BUILDER

The Problem: Not using the right pattern for the right situation and creating difficult to find bugs.

In day-to-day work I continually see complex objects being constructed without any patterns at all. What happens? Well, we see giant Services with 10, 20, 30 or more lines with setters from the objects being populated. Do you think we can continue coding like this? Of course not!

This structure looks like procedural programming. We must learn the best programming techniques so that we can deliver quality software and avoid bugs. If we use the Builder pattern effectively, we can make awesome, flexible and powerful code.

Builder

The diagram:

Builder.PNG

Get the source code:

https://github.com/rafadelnero/nobugsproject.git >> design-patterns-saga

1 – Calculation Class: This a simple class with values of a calculation. It has attributes, getters and setters and some important details in this class:

  • The setters are private to avoid direct access
  • The getter of the list is unmodifiable to avoid new elements adding
  • The constructor is private for avoiding instantiation

We are using a really important concept here, ENCAPSULATION! But, how can I change those fields if they are private? You will see in the next topic.

 public class Calculation {

	private long idCalculation;

	private long idPeriodicity;

	private List<Price> prices;

	private Date dtCalculation;

	private Calculation() {
		prices = new ArrayList<>();
	}

	// Builder class omitted, it will be explained in the next topic

	private final void setIdCalculation(long idCalculation) {
		this.idCalculation = idCalculation;
	}

	private final void setIdPeriodicity(long idPeriodicity) {
		this.idPeriodicity = idPeriodicity;
	}

	private final void setDtCalculation(Date dtCalculation) {
		this.dtCalculation = dtCalculation;
	}

	public final long getIdCalculation() {
		return idCalculation;
	}

	public final long getIdPeriodicity() {
		return idPeriodicity;
	}

	public final Date getDtCalculation() {
		return dtCalculation;
	}

	public final Collection<Price> getPrices() {
		return Collections.unmodifiableCollection(prices);
	}

}

2 – Static Inner Builder Class: Here is where the magic happens! We are going to build the Calculation object and with the Builder we can have access to modify the fields.

In the constructor:

  • public Builder(long idCalculation, long idPeriodicity): we are initiating the Builder class with the required fields, that is why they are being passed in the constructor.
  • In the method Builder withDate(Date dtCalculation): we are putting information in dtCalculation. Most importantly we are returning “this”, the Builder. It makes  invoking another method directly possible.
  • The method public Builder withPrice(long idCurrency, BigDecimal priceValue) builds the Price object. See that this method delegates the responsibility for the Builder of the Price class.
public static class Builder {

		private Calculation calculation = new Calculation();

		public Builder(long idCalculation, long idPeriodicity) {
			calculation.setIdCalculation(idCalculation);
			calculation.setIdPeriodicity(idPeriodicity);
		}

		public Builder withDate(Date dtCalculation) {
			calculation.setDtCalculation(dtCalculation);

			return this;
		}

		public Builder withPrice(long idCurrency, BigDecimal priceValue) {
			Price price = new Price.Builder(new Random().nextLong()).withPrice(idCurrency, priceValue).build();
			calculation.prices.add(price);

			return this;
		}

		public Calculation build() {
			return calculation;
		}

	}

3 – Price Class: This is pretty much the same as the Calculation class – no new concept here!

public class Price {

	private long idPrice;

	private long idCurrency;

	private BigDecimal priceValue;

	private Price() {
		super();
	}

	public static class Builder {

		private Price price = new Price();

		public Builder(long idPrice) {
			price.setIdPrice(idPrice);
		}

		public Builder withPrice(long idCurrency, BigDecimal value) {
			price.setIdCurrency(idCurrency);
			price.setPriceValue(value);

			return this;
		}

		public Price build() {
			return this.price;
		}

	}

	// Getters and Setters omitted 

}

4 – Unitary Test: The final process. Let’s finally build our objects!

Summary of actions:

1 – We encapsulate the attributes of the POJO
2 – We make the constructor of the POJO private
3 – We create a static Builder class inside the POJO class
4 – We declare the POJO class inside the Builder
5 – We create methods in the Builder that return the Builder
6 – Finally, we build the object

You can execute your tests with these Unitary Tests:

public class BuilderTest {

	private static final long ID_CALCULATION = 1L;

	private static final long ID_PERIODICITY = 1L;

	private static final long ID_CURRENCY = 1L;

	private static final Date DT_CALCULATION = new Date();

	private static final BigDecimal PRICE_VALUE_1 = BigDecimal.ONE;
	private static final BigDecimal PRICE_VALUE_2 = BigDecimal.TEN;

	@Test
	public void validateCalculationInformationTest() {
		Calculation calculation = new Calculation.Builder(ID_CALCULATION, ID_PERIODICITY).withDate(DT_CALCULATION)
				.withPrice(ID_CURRENCY, PRICE_VALUE_1).withPrice(ID_CURRENCY, PRICE_VALUE_2).build();

		Assert.assertEquals(ID_CALCULATION, calculation.getIdCalculation());
		Assert.assertEquals(ID_PERIODICITY, calculation.getIdPeriodicity());
		Assert.assertEquals(DT_CALCULATION, calculation.getDtCalculation());

		Iterator<Price> iterator = calculation.getPrices().iterator();
		Price firstPrice = iterator.next();
		Price secondPrice = iterator.next();

		Assert.assertEquals(ID_CURRENCY, firstPrice.getIdCurrency());
		Assert.assertEquals(PRICE_VALUE_1, firstPrice.getPriceValue());

		Assert.assertEquals(ID_CURRENCY, secondPrice.getIdCurrency());
		Assert.assertEquals(PRICE_VALUE_2, secondPrice.getPriceValue());
	}

	@Test(expected = UnsupportedOperationException.class)
	public void validatePricesIsImmutableTest() {
		Calculation calculation = new Calculation.Builder(ID_CALCULATION, ID_PERIODICITY).build();

		calculation.getPrices().add(new Price.Builder(new Random().nextLong()).withPrice(ID_CURRENCY, PRICE_VALUE_1).build());
	}

}

To practice this Pattern, create another POJO and check if the fields correspond to each other in your Unitary Test.

Keep up the great work. Stay tuned for more articles next week!

DESIGN PATTERNS SAGA #2: REAL PROJECT SITUATIONS WITH BUILDER

2 thoughts on “DESIGN PATTERNS SAGA #2: REAL PROJECT SITUATIONS WITH BUILDER

  1. rcmoutinho says:

    Simple and great explanation! It’s nice to see that you used static inner class on Builders, because they don’t need the instance values from the father. They are inner classes to favor encapsulation and better code organization.

    Amazing, Rafael!!
    Thanks for sharing this great knowlegde

    1. Thank you Rodrigo! Exactly! Static inner classes make the Builder easier to find also to maintain! Encapsulation is key to make powerful code! Stay tuned for more articles next week! See you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s