Take it easy, we have builders

As I said before, it’s a valuable experience for me to keep in touch with different development teams.

Last week we were discussing the best method to validate domain model objects. My first response to that question is: model objects should never be invalid, in the first place.

Each domain object should be fully initialized in its constructor, either by initializing default values or receiving values ​​from the constructor.

Sometimes someone says that does not appreciate consructors with 20 parameters, then I question if the object is large because one or more objects are not yet discovered.

Not to make this post too long, suppose we agree that completely initialize the object with valid values ​​in the constructor and that no public method allows us to modify the state leaving it invalid. In this case, it is never necessary to validate our object because we know that it can never be invalid.

And here we come to the practice recommended to fellow developers last week: if it’s not trivial to validate a data and, once validated, to build the object, then use a Builder. Builder’s responsibilities are:

  • Make sure you have all the necessary data to construct the object
  • Provide a friendly interface for specifying the data
  • Construct the object

The following example “fluent API”:

public class InvoiceBuilder {
    private Customer _customer;
    private DateTime _date;

    public InvoiceBuilder WithCustomer(Customer customer) {
        _customer = customer;
        return this;
    }

    public InvoiceBuilder WithDate(DateTime date) {
        _date = date;
        return this;
    }

    public Invoice Build() {
        AssertDataCompleteAndValid();
        return new Invoice(_customer, _date);
    }

    private void AssertDataCompleteAndValid() {
        if (_customer == null)
            throw new ArgumentNullException("customer");

        if (_date < DateTime.Today)
            throw new ArgumentOutOfRangeException("date");
    }
}

And this code would be used this way:

var invoice = new InvoiceBuilder().
    WithCustomer(jose).
    WithDate(DateTime.Today).
    Build();

See you!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *