Sculptor


An important building block when creating a high quality domain model is to create small type objects. In this article we will create a Length type for the diameter of the Planet of the helloworld application.

Length is a typical Quantity with a value and unit, e.g. meter, kilometer.

In the design model it looks like this:

BasicType Length {
    BigDecimal value min="0"
    -@LengthUnit unit
}

enum LengthUnit {
    cm, m, km
}

Entity Planet {
    gap
    scaffold
    String name key
    Long population min="0"
    -@Length diameter nullable
    -Set moons opposite planet

    Repository PlanetRepository {
        findByKey;
    }
}

We also need to convert between different units. The behaviour expressed as a JUnit test:

public class LengthTest {

    @Test
    public void shouldConvertFromMeterToKilometer() {
        Length length = new Length(new BigDecimal("31000"), m);
        Length lengthInKilometer = length.to(km);
        assertEquals(new Length(new BigDecimal("31"), km),
        lengthInKilometer);
    }

    @Test
    public void shouldConvertFromKilometerToMeter() {
        Length length = new Length(new BigDecimal("44"), km);
        Length lengthInMeter = length.to(m);
        assertEquals(new Length(new BigDecimal("44000"), m),
        lengthInMeter);
    }

    @Test
    public void shouldNotConvertSameUnit() {
        Length length = new Length(new BigDecimal("17"), km);
        Length length2 = length.to(km);
        assertSame(length, length2);
    }
}

BasicType objects may contain business logic in the same way as other domain objects. The following screencast illustrates how to implement the conversion.

BasicType is a stored in the same table as the Domain Object referencing it. It corresponds to JPA @Embeddable.

There are a lot of cases when it is a good idea to introduce types.

  • Identifers, natural business keys. It is more readable to pass around an identifier type instead of a plain String or Integer
  • Money
  • Range
  • Quantity

I can recommend reading When to Make a Type, Martin Fowler.



Fork me on GitHub