Eric Evans Visit

We just had the privilege of hosting Eric Evans for half an hour at our project!

quick summary of what i scrawled down.

1) The MODEL : it was very clear to me that the model is neither a diagram, documentation or (which was the most interesting to me) the code. Quite often in agile we hear about the code being king! the code is the design, etc. Actually the model is an abstraction of all of these. THe code is the current expression of that abstraction and is therefore the only solid thing you have available. UML and documentation (he mentioned writing up key abstractions in the model such as Page – these could be made highly visible on walls or so) are TRANSIENT and provide a particular view of the model at any one time which can be useful for communication but is not necessarly the LAW.

2) Services : Should be orchestration rather than containing a lot of logic. The logic should be presented by the domain entities. Anything complex lives there, services should represent clearly defined abstractions of doing a particular thing. They can also represent an easy interface to the complexity of the domain.

To aid with design decisions about what should live in the service or the entity it helps to have a clear MODEL worked out and understood by everyone. The model will tell you where to put stuff, or it will feel more natural, it will guide you.

3) Model context boundaries: This is something interesting in the DDD book – models only have relevance within specific context and so it is important to define that context and anything that crosses the boundary must be translated into the other context.

4) Crossing boundaries or interacting with other domain models. There are 2 strategies, Conformist or Anti-corruption layer Conformist means to take the same object model. Anti-corruption layer means to build an adapter between the two contexts.

5) We have 2 clients of our Domain objects, people who edit content and the people who design the front end pages using velocit and CSS. We asked the question as to wether there should be additional translation into the front end “model”. Perhaps there are 2 domain contexts’ here? The thought was that for our system it might be better to keep the core model as a set of concepts and just exntend those concepts to provide a more useful interactio with the presentation layer. One of the problems is classes getting really big, so maybe splitting them up into smaller, functionally cohesive units which are more suitable for different applications.

By the same token we should be extracting the CONCEPTS from the front end and building them into the model. This totally highlights the idea that the model is a conceptual abstraction of the software, not a particular artifcat such as the code or a diagram.

We have been more focused on the content building side and have done good work modelling the domain from that aspect, potentially we need to move that modelling into the front end.

6) MODELLING is different to Software DESIGN : this is not something he said but something i think might be implied by the modelling stuff.

If the MODEL is not the CODE, it cannot be the design of the software. Therefore, MODELLING as an activity is a more abstract than writing the code – the DESIGN of th ecode should fall out if the model is well defined and understood. The MODEL is more about principals and ENTITIES than low leve code design.

What a great afternoon!

Share

Services Vs Domain objects

So far I have the following.

There are three different types of service (From DDD by Eric Evans) :

1) Application Services (front end, transport, e.g. unpacking xml files, communicating to infrastructure)

2) Domain Services (Always defined in terms of Domain objects, in SAME LAYER as Entities, i.e. Domain Layer, Perform operations which don’t naturally fit into the domain object, which may use global facilities)

Domain services should have methods named using the UBIQUITOUS LANGUAGE

3) Infrastructure services (communication to other systems, e.g. email, SOAP requests)

Domain services are the tricky ones.

Personally so far I want to always try to put something on the Domain. If it looks really messy and is hard to test, maybe it needs to be in a service.

An alternative approach is to build the service first and then see if it makes sense to move it into the domain. The problem with this second approach is that you end up having to remove the service afterwards, but it might be easier to communicate to people who are used to always having a service, it becomes more obvious once you see the code that it should be moved into the Domain Object.

For example we have been building a domain object which accepts user input from a front end in the form of an email address and the answers to a set of questions, a bit like a survey. The names have been changed to protect the innocent and prevent any legal issues!

One of the main things you can do with a competition is of course, enter it. So, should there be a service which allows you to enter or should you just enter the Competition ?

The first cut involved a service called DomainObjectSubmissionService with a method submit() which took the responses the user had made in the form of a map of question ids to answers.

    public DomainObjectSubmission submit(String emailAddress, Map<Integer, List<String>> responsesToQuestions, DomainObject domainObject) {
        DomainObjectSubmission submission = responseValidator.validate(emailAddress, responsesToQuestions, domainObject);
        if(submission.isValid()){
           enter(domainObject, emailAddress, responsesToQuestions);
        }
        return submission;
    }

    private void enter(DomainObject domainObject, String emailAddress, Map<Integer, List<String>> responsesToQuestions) {
        DomainObjectEntry entry = new DomainObjectEntry();
        entry.setEmailAddress(emailAddress);

        for (DomainObjectQuestion question : domainObject.getQuestions()) {

            if (question instanceof CheckBoxQuestion && !responsesToQuestions.containsKey(question.getId())) {
                DomainObjectResponse response = new DomainObjectResponse();
                response.setResponseValue("unchecked");
                entry.putResponse(question, response);
            } else if (responsesToQuestions.containsKey(question.getId())) {
                DomainObjectResponse response = new DomainObjectResponse();
                String submittedResponseValue = toResponseValue(question, responsesToQuestions.get(question.getId()));
                response.setResponseValue(submittedResponseValue);
                entry.putResponse(question, response);
            }

        }

        entry.setDomainObject(domainObject);
        repository.save(entry);
    }

So here are two methods, submit and enter. This might be an example of application vs domain services… perhaps submit is an application service and enter is a domain service. enter is definitelly a domain service, it is TOTALLY using domain objects and manipulating them. The reason it should move to the domain is that it is doing the classic thing of calling lots to the same object, the entry. This is the indication that it should move, infact it is more specific, in that it is the same instance if there were two instances of the same class then it would be leaning towards a service as exemplified by the old Account Transfer example.

Alternatively, you could argue that constructing the entry is a FACTORY METHOD as it is building an object up. I would argue that the method still belongs on the Domain object but that it could use a factory method inside it to actually do the work. Although the thing about factories is that they are not so useful if only one thing ever uses them.

This is also something ive heard said about services. So, for example in this service we have only one client, the web controller. Should there really be a service ? It is already looking more liek and APPLICATION SERVICE, i.e. its not only dealing with domain objects, it is validating a submission and then calling the domain.

It seems that this logic could easily live in the controller.

Finally, what about this validation object ? Should this live inside the domain object aswell ?

We already made the decision to not represent the user response with a custom domain object, i.e. we just use a simple map. The validator however does do some extra validation which requires a database call to find out if the person has already submitted or not for that email.

Without adding repository access to the domain object (which may not be a bad idea) this kind of has to live in the service.

Is the service an APPLICATION service or a DOMAIN service ?

I think that if we set the email address on the competition and then set the responses and THEN validated the competition, it would be a domain service, because the validator would be also a domain level object.

So a rule of thumb:


If a method is making many calls to the same instance of a class, and is purely manipulating domain objects which either belong to or are associated with that instance, it should move onto the domain object

This is quite a simple rule and is basically ENCAPSULATION

Firstly, this method doesn’t have parameters which are domain objects… should there be a domain object which represents the Response from the user, rather than a Map ? Maybe. just using a Map may be simple but it does not declare any intent.

I intuitively wanted to move this into a method Competition.enter().

But is it the right thing to do ?

One thing to think about is that a domain service will usually coordinate between domain objects. A really good example is that of transferring money between two accounts – if you put this on account it would be a bit like it was breaking the encapuslation, it would become not obvious which account was which.

Secondly, if the parameters really aren’t a domain object, maybe they shouldnt be on a service but on the domain object.

Share