Sonntag, 4. November 2012

Java suffers from anemia

I recently read this StackOverflow question. The author asks how he can build rich domain models when all of Java's standards are built around the assumption of completely exposed state. I think that this is symptomatic for the direction that standard Java has been going for many years now: Back to procedural programming.

Let's take the new Bean Validation Framework as an example. It allows you to annotate your classes' fields with things like @NonNull or @Size(min = 5). Then you can ask a validation service if your bean is still okay. The service needs access to the internal state, so you need to have getters for everything you want to check. But the really bad part is the concept of objects entering an invalid state at all. In my happy little world, an object will throw an exception when I try to null a mandatory field. In the Bean Validation world, the object will just accept any input given to it. Only the validator can know if the object is in a valid state.

This is bad for several reasons:
  • Testability: If you want to check that business rules are honored, you always need a validator in your unit tests, because the domain object itself will not complain
  • Understandability: When an object just accepts any input, it gets harder to understand what can legally be done to it
  • Correctnes: If for some reason you forget to call the validator, invalid objects could enter your database or be transmitted to other applications
Sure, you could use exceptions in your domain model and build an additional view model with validation annotations and getters/setters. But that would mean duplicating all the validation rules. Wouldn't it be much nicer if Java allowed us to specify preconditions and invariants? These could be enforced through exceptions when methods are actually called, but could also be available through reflection in order to validate user input. I understand that this would require a completely new language feature, but it would allow us to build rich domain models without duplicating validation in UI code. 

But since that is unlikely to happen any time soon - if at all - we have to turn our attention to other possibilities  On of them are active annotations - the next big feature of the XTend language. Active annotations allow you to alter the Java code that is generated from XTend source code or even produce completely different resources. Basically they give you type safe compile time metaprogramming.

They are still in a very early stage, but as soon as they reach beta, I will try to build the above mentioned preconditions feature on top of them. On option would be annotating method parameters with preconditions and then generating "canXXX"-methods which return localizable error messages when the parameters do not satisfy the preconditions. Alternatively, one could generate view models that contain the aforementioned validation logic and only use exceptions in the domain model. Either way, business logic would only be specified in one place and enforced at all times - just as it should be.