Extended Definition Of Done
When software projects grow it is considered helpful if the software follows an established structure so that every developer finds their way easily. If the used structures and patterns change per developer or even every couple of months or years it will get really hard to maintain the software. There are multiple reasons for this:
- Collective Code Ownership
- Every developer in a team should have the feeling that the code is “their” code. Otherwise they will defer responsibility for features or bug fixes to somebody else. This is not helpful especially when somebody leaves the company or even just is sick or on vacation.
- Common principles ease understanding
- If the code follows common structures it is a lot easier to get to the business / domain logic and find issues there. Otherwise you first need to understand the structures of the code before you can even start thinking about the business / domain logic.
- Focus on what matters
- In the end our code is there to solve certain business / domain problems and not be creative about the patterns used. If you, as a developer, know immediately which patterns you are supposed to use you can focus much more easily on the business / domain concepts. Otherwise many developers will often try to come up with fancy abstraction layers distracting from the actual business / domain logic.
This may sound boring for developers but in our experience with many different teams developers welcome the possibility to focus on the business / domain part. They welcome not having to discuss the “correct” patterns again and again.
To get the acceptance for this it is crucial to do a workshop together with the whole development team and agree on the patterns to use with everybody involved with the code. We moderate workshops like this regularly and always find a sensible set of patterns to agree on. Guided by our expertise the already existing patterns and the patterns the developers themself think are the right ones to use will be discovered and agreed on.
In such workshops we mutually agree on set of definitions and define them as a guide for code reviews which are then part of the “Definition Of Done” for the team. This also means that the team gets clear guidelines for Code Reviews and the reviewer knows what to look for. With several teams we even assist during Code Reviews for some time by reviewing the pull requests ourselves according to the guidelines we agreed on. This helps to get a deeper understanding of the structure and patterns and resolves remaining issues.
A common Definition Of Done we agree on could look like the following points. Remember that this might vary a lot depending on the domain, the team and the already existing patterns:
- Always exceptions for error handling
- Never return
falsein case of an error
- Use data objects
- Never use arrays as data structures
- Data objects must not aggregate “active” dependencies (gateways, services)
- Only logic modelling eternal truth
- Max 4 dependencies, which are all injected using Constructor Injection
- No dependencies on externals — each external class should be wrapped behind a facade
- Must be “fully” tested
- Use Gateways / Repositories to load and save data
- Return and / or receive data objects
- Services depend on Gateways (interfaces)
- No logic in Controller, besides
- Catch domain exceptions
- Simple authorization (“is logged in”)
- Convert incoming data into object and outgoing data from object
There are usually more rules then this simple set which are then more specific to the given domain. But most of these rules are simple and fast to review (not simple enough to write automatic checks, though) and following such a defined set of rules already greatly simplifies and unifies the code.
While working with many different teams we understood that common rules for code structure and patterns on top of what PSR-2 defines are helpful for developers and speed up the development. Strong rules simplify code reviews and strengthen the sense of Collective Code Ownership. We suggest to build up a rule set for common problems in your domain and use them in your daily work. Get the whole team together and agree on a rule set with everyone.