Reusing domain code
Last week I wrote about when to add an interface to a class. The article finishes with the claim that classes from the application's domain don't usually need an interface. The reason is that domain code isn't going to be swapped out with something else. This code is the result of careful modelling work that's done based on the business domain that you work with. And even if you'd work on, say, two financial software projects in a row, you'll find that the models you produce for each of them will be different in many subtle (if not radical) ways. Paradoxically you'll find that in practice a domain model can sometimes be reused after all. There are some great examples out there. In this article I explain different scenarios of where and how reuse could work.
In "Facts and Fallacies of Software Engineering" (2002), Robert Glass speaks about reuse-in-the-small:
Reuse-in-the-small (libraries of subroutines) began nearly 50 years ago and is a well-solved problem.
Reuse in software is quite possible, but only if the amount of shared code is relatively small. Examples of components with the right size in the PHP ecosystem would be:
- Flysystem (filesystem abstraction)
- ProxyManager (proxy generation)
- JMSSerializer (object serialization)
- Symfony Validator (validation)
And so on. The idea being: if the library is basically a utility function that "got a bit out of hand", but is flexible at the same time, supporting many different use cases, then we can speak of successful reuse. In particular because PHP package maintainers tend to set a very high standard for themselves: every quality indicator should be green, 100%, etc. And so it can happen that these packages have millions and millions of downloads.
By the way, I also count frameworks as successful reuse-in-the-small: most of them are a collection of utility-like libraries anyway, and they rarely get in the way in terms of flexibility, at least in my experience; you can build any web application on top of any of them.
Reuse-in-the-large and software diversity
If a reusable component is too large, many aspects of it will be irrelevant, or even counter-productive, for its users. This leads to objections like:
- When I'd use this component in my project, I'll be downloading way too much stuff that I'll never actually need.
- Considerable parts of this component don't work as I want them to, so maybe I should roll my own.
- This component is good today, since we're in the prototype phase, but probably in about a year, it will limit us.
In Glass's terms, we're talking about reuse-in-the-large, and he poses that:
Reuse-in-the-large (components) remains a mostly unsolved problem, even though everyone agrees it is important and desirable.
Software projects in general are very diverse. Every project comes with its own requirements, its own domain experts, its own team, and everything about it is special (although some product owners would be better off not thinking that their project was so very special). Still, one might say, there should be some common ground. Some domain knowledge will be potentially reusable, like a
Money class, or a
DateTime class, right?
If there are enough common problems across projects and even application domains, then component-based approaches will eventually prevail. If, as many suspect, the diversity of applications and domains means that no two problems are very similar to one another, then only those common housekeeping functions and tasks are likely to be generalized, and they constitute only a small percentage of a typical program’s code.
Over the past few years we've had some excellent articles making the rounds, which prove the point that "no two problems are the same". I'd like to mention Ross Tuck's "Precision Through Imprecision: Improving Time Objects" and Mathias Verraes's "Type Safety and Money". In these articles, we learn by example how design decisions are based on domain knowledge, that different situations require different decisions, and that designs resulting from those decisions can't be useful in every other situation. Trying to use things like a
Money object in situations where they just don't belong, is very much like the saying: "trying to fit a round peg in a square hole".
In particular, reusing domain code will make us feel like we have to ignore or
Truncated by Planet PHP, read more at the original (another 6243 bytes)