May 2008

Test Naming

I was just naming some test cases.

I had a test called :

testShouldReturnInvalidSubmissionIfACompulsoryQuestionIsNotAnswered

I didnt like the way it had Return in it. THis is not very behavioural, it sounds like some implementation detail.

We have been using the pattern testShould a lot which i like, but here i thought, maybe i can call it:

testSubmissionShouldBeInvalidIfACompulsoryQuestionIsNotAnswered

Which breaks the pattern but looks ok. So i started renaming all the methods in the test. Halfway through i thought “what extra information is the ‘Submission’ word adding to my names ? And realised that actually my test was testing a class which was a submission validator and was returning a submission! do i really need to mention it all the time ? No!

so now its :

testShouldBeInvalidIfACompulsoryQuestionIsNotAnswered

all the tests are now named nicely and more concisely.

  • Share/Bookmark

testing

Comments (0)

Permalink

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/Bookmark

design
modelling

Comments (0)

Permalink

spring configuration files

We heard some interesting comments about spring yesterday. Some people were not into the configuration in xml which is something i have heard before and agree with. Reading the pro spring book I noticed that they recommened never using auto wiring because of the fact that for example you may be tempted to configure by type and then need two instances of the same type with different configs.

So the argument goes something like… I have one class which is configured with different services and this is what spring allows me to do. The class i have designed doesn’t need to know about which supporting services it is injected with as long as they support a common interface.

This is a bit like a strategy pattern.

The flip side is that is what I’m really doing moving some of my domain representation into the configuration ?

The example we were discussing was a setup where there were several spring configuration files which all included a common file which was a bit like an interface. It defined a set of beans which were needed and the specific instances of these were defined in the local files.

Is this trying to represent inheritance and overloading in xml ?

Should this be represented in the domain model ?

  • Share/Bookmark

code
design

Comments (0)

Permalink

The point of going in small, safe steps.

I have been thinking about Kent Beck’s talk and ideas about moving in small safe steps. Today I had a grerat example.

I want to add a feature to the codebase which will require changes throughout the stack and several of them, possibly half a days work.

I dont necessarly have the time set aside for this in true agile fashion something more important may come up.

What i dont want to do is take everything apart and have it in a mess on my machine and leave it until the whole thing is finished before checking in. because, IT WILL NEVER HAPPEN!

SO. What I needed to do was break the process down into small, manegable chunks of refactoring that maybe take an hour or so each and which can be completely safely checked in without affecting the codebase.

The joy of this approach is that even if i only do the first step, and then disappear from the project, I will have made the codebase progressively slightly easier to implement the required feature upon. Maybe everyone forgets they ever wanted this feature but if someone comes back to it, even if i have left no documentation, they will look at the steps necessary to implement the new feature and there will be one less on thier list than on mine so my work was valuable.

Points are that dont need documentation.

DOnt waste time.

Dont leave loads of changes on the PC waiting to check in

Tasks easier to exlpain to others for them to take over.

If everyone had the same approach would be easy to move between pairs and others (familiar territory)

  • Share/Bookmark

design

Comments (0)

Permalink

The power of the white board

One of the principals of Agile is making things visible at all times.

I have always been a proponent of getting the team to share a common understanding of the model, in an abstract way aswell as in the code. This can be particularly useful when you have multi-disciplinary teams (another agile precept), because having some representation of the software other than the code can help communication between different groups.

Another artifact of the design of a system is often screenshots or wireframes in internet applications.

We have recently taken to having a whiteboard which always has the current iterations’ main domain model drawn on it. It becomes a great place for having swift tech huddles and then writing down questions that arise. It becomes like a public representation of the model.

I realised today that it may also function as an alert mechanism – as people move to the board to make changes, other members of the team can see that somethign is being altered, the design process ITSELF is becomeing visible to the team and its easy to participate and keep informed.

A second thing we did is have the screenshots of what we are building live on the desk of the person responsible for coding the fornt end. Aswell as being the main consumer of the information I belive that this will mean that everyone goes to her to ask to see the desings which i hope will encourage spontaneous design decisions, again, making the design process visible.

Finally both of these activities are examples of DEVOLUTION of authority. Rather than the Tech / Team lead being the focus of this information and constantly responding to questions, they should become the guardian of the process which devolves the power. If everything is always visible theres no need to keep track of everything because its happening all around you all the time.

Main points:

Make the design ARTIFACTS highly visible
Make the design PROCESS visible
Encourage SPONTANEOUS design interactions
Encourage DEVOLUTION of the process from a central authority to the team

  • Share/Bookmark

design

Comments (0)

Permalink