Implicit concepts are concepts that exist but , for some reason, the domain experts don’t talk about them explicitly. It takes some time until the developers actually realize the existence of those implicit concepts, by means of hints while discussing the model or at later stages, when several other concepts are already set in place.
Digging out concepts
When a new concept is found, we need to refactor in order to reflect that concept in the code, naturally ending up with a cleaner design.
Listen to the language
Listen to the language the domain experts use. Are there terms that succinctly state something complicated? Are they correcting your word choice (perhaps diplomatically)? Do the puzzled looks on their faces go away when you use a particular phrase? These are hints of a concept that might benefit the model.
pg. 206
Scrutinize awkwardness
Developers can not always find implicit concepts just by talking to the domain experts.
We need to dig concepts from the code itself. Whenever we find code which is confusing, difficult to extend, does not fit into any explicit concept, and has awkward responsibilities, we need to actively engage the domain experts in order to clarify our domain knowledge and further improve the domain design.
Contemplate contradictions
Different domain experts can have different views on a particular part of the domain, according to their knowledge and experience.
Most of the times, the contradictions are merely terminology differences and misunderstandings, however sometimes there is an actual clash of ideas.
Either way, when we find a contradiction, we need to clarify it with the domain experts.
Read the book
When dealing with a specific domain, for example “accounting”, it is often useful to educate ourselves on it, specially if no domain experts are available.
Try, try again
All the knowledge crunching is interactive, it doesn’t happen in one go. It involves a lot of experimentation, a lot of trial and error. It takes time, but it deepens the model, it makes the model reflect what is indeed needed and, in the long run, it ends up being faster.
How to model less obvious kinds of constrains
Explicit constrains
An example of a constrain is the volume of liquid a bucket can have.
This is a simple rule and can easily be implemented using a few conditionals. However, we can easily imagine similar rules being obfuscated within other code, or much more complex rules, and the same rule being repeated in several places.
Making such a rule explicit its as simple as encapsulating it in a reusable method, with a clear and descriptive name. This will make that obfuscated concept, an explicit concept:
A named thing we can discuss
pg. 221
This also isolates the rule, allowing it to grow, if needed, without affecting the remaining code.
Nevertheless, there are cases where encapsulating a rule in a method is not enough, namely when:
Evaluating a constraint requires data that does not otherwise fit the object definition;
Related rules appear in related objects, forcing duplication or inheritance between objects that are not otherwise family;
A lot of design and requirements conversation revolves around the constraints, but in the implementation, they are hidden away in procedural code.
pg. 221
In such cases, we should refactor the constraint by extracting it into an explicit object, or as a set of objects and relationships.
For this, the SPECIFICATION Design Pattern comes up: A class who’s only purpose is to evaluate if a specific condition/predicate/business rule is met
Eric Evans identifies 3 situations where we should use a Specification pattern:
- Validation: Validate if an object fulfills some need or is ready for some purpose;
- Selection: To select an object from an hydrated collection by cycling through all elements and filtering them or by using a query language like SQL, although in this case we should put the actual SQL outside of the Specification class, in a Repository.
- Generation: Specify what object to create to fit some need. This means we can pass a Specification into a Factory and have it decide what object to instantiate, and how.