Classes and objects

From cdd
Jump to: navigation, search

In traditional object oriented languages the state and behaviour are merged to form classes that can be instantiated to objects, like this:

public class Person {
    private int age;
    private String name;
 
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
 
    public boolean isTeenager() {
        return age >= 13 && age <= 19;
    }
 
    @Override
    public int hashCode() {
        int result = ssn;
        result = 31 * result + (name != null ? name.hashCode() : 0);
 
        return result;
    }
 
    @Override
    public boolean equals(Object that) {
        if (this == that) return true;
        if (that == null || getClass() != that.getClass()) return false;
 
        PersonState state = (PersonState)that;
 
        if (ssn != state.ssn) return false;
        if (name != null ? !name.equals(state.name) : state.name != null) return false;
 
        return true;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
 
Person person = new Person(56, "Ingemar Stenmark");
System.out.println(person);
System.out.println("Is teenager: " + person.isTeenager());

...if executed, we get:

Person{age=56, name='Ingemar Stenmark'}
Is teenager: false


The state is here represented by the attributes age and name, and the behaviour is represented by the method isTeenager, which can be illustrated by this diagram:


Traditional-object.png


The merging of state and behavior makes it harder to reuse code and to work in different contexts. Object oriented languages with support for traits are able to compose classes in a powerful way, but once instantiated the objects become static.

Flexible objects

CDD wants to bring the same level of flexibility to objects as we get for classes. The separation of creator, state and behaviour enables powerful ways to build, validate and compose objects. Let's see how the previous example would look like in CDD (generated code has been removed):

public class PersonState implements ImmutableState {
    public final int age;
    public final String name;
}
 
public class PersonCreator implements PersonCreatorMaker {
    private final PersonMutableState state;
 
    public Person asPerson() {
        return new Person(state.asImmutable());
    }
}
 
public class Person extends PersonBehaviour {
    public Person(PersonState state) {
        super(state);
    }
 
    public boolean isTeenager() {
        return state.age >= 13 && state.age <= 19;
    }
}
 
Person person = createPerson.age(56).name("Ingemar Stenmark").asPerson();
System.out.println(person);
System.out.println("Is teenager: " + person.isTeenager());


...when executed, we get:

Person{age=56, name='Ingemar Stenmark'}
Is teenager: false


The cool thing with CDD is that we can have many behaviour representations (one per context), not just Person but also for example PersonRowInFile and PersistablePerson:


CDD-object.png


CDD is not the only attempt to improve how to work with objects, you may also find it interesting to read about the DCI paradigm. If you want to compare the two you can have a look at the popular account example which looks like this in DCI using the Decorator pattern and traits or like this using the framework Qi4j and like this in CDD.


Here is an alternative way of illustrating objects in CDD where we can think of them as building blocks:

CDD-object-layering.png


< Back          Next >