Monday, March 21, 2011

Making rich domain models in Ruby is nicer than Java

Being a Java developer starting to do some programing in Ruby i found many different nice things in the language and the way things are done.

One of the nicest things i found is the notion of module mixing, and although you can artificially do the same with Java and Spring (google for @DeclareParents) , it’s not as neat and clean as Ruby does it.

Module mixins basically allow us to add behaviour to our objects without inheritance. Is like if in Java we could use an Interface that has a default behaviour associated to it, so we don’t need to actually implement the methods of the interface.

The objects that has the module mixed in, can receive method calls on the module like if the methods belong to the object itself. This allows to a nice approach to domain rich programming, while at the same time maintaining a great separation of concerns and avoiding filling the classes and objects with lots of not very related functionality.

To explain the last paragraph better, let’s take a simple example. a Person class.

In our example a person can have emotions (happy, sad, etc), can do actions (play, sleep), have measure attributes and queries(height,weight). It can also be used in database operations (If we want like an ActiveRecord approach) (save, update, etc).

In a Model centric approach (Instead of using services, DAOs, etc) we would like to have Person objects that allow us to do thing like:

if(person.sad?)

person.playWith(toy)

if(person.higher_than?(person2))

person.store

We can consider each of these methods addressing different concerns, but all valid thing for a Person to know about. if we were to program this with Java, we would end up with a Person class with all these methods like:

publicclass Person{

publicboolean isSsad(){...}

publicvoid playWith(Toy toy){...}

publicint store(){...}

publicboolean isHigherThan(Person person2){...}

}

We could argue that a better approach would be to have “behavioural” modules and plug them individually to our class. For example in Ruby we could have something like:

class Person

include Sentiments

include Actions

include Persistence

include Measures

end

We can have then each module dealing with its own concern, and making all this knowledge and capacities available to the Person objects as if they were defined on the Person class.

So for example our “Measures” module could have something like:

module Measures

attr_accesor :height

def higher_than?(entity)

returnself.height> entity.height

end

end

Then we can do something like:

a= Person.new

a.height = 150

b=Person.new

b.height=200

b.higher_than? a

This same approach can be used for the other modules like Persistent or Sentiments.

The problem with interfaces is that they don't have any implementation, So if for example you want your class to be able to be persisted, Xml serializable, etc, and you separate this into different interfaces (like Persistable, XmlSerializable), you still have to implement this methods in your class, mixing your domain business logic with serialization and persistence logic.In Ruby, you can just implement your business logic in your object and let the implementation of the persistence and serialization to xml in different modules that you just need to include.

As I explain in the beggining of the post, you can achieve something similar in Java with Spring Introductions or Mixins