Economy is the management of limited resources. In software development the limited resources (*) are:
- memory of the developer: names of types, methods signatures, tricks to know
- time available to learn or discover new things
Therefore, every design decision should attempt to reach an optimal balance between both memory and time being consumed in the developer head.
Memory effort for the developers is positively reduced with:
- less abstract types to know (make interfaces more generic, use more polymorphism, favor generic approaches)
- less methods in interfaces (minimal interfaces)
- logical system of conventions: classes/methods naming (idioms)
- frequent use of the same set of concepts (patterns)
- sharing of one same ubiquitous language between business talking and technical models (sharing of words as resources)
Time to learn:
- more expressive names, dedicated for the case at hand (less generic)
- humane interfaces (easier to find how to use them)
- value objects, that bring explicit names even for simple primitive-like things
- favor specialized classes and interfaces (that reflect the concrete elements of the domain) rather than generic interfaces
- use practices, idioms and patterns already well known within the team
As usual, the optimum has to balance opposite forces, and will be somewhere between the two extreme approaches: smaller, full generic but totally unexpressive, or fully specialized, hence with some duplication of ideas but more expressive.
By making more concepts of an application sub-types of few interfaces, we obviously reduce the memory effort to deal with the code base: once created, instance of various types can be used under the same interface. Design patterns often also propose their participants to adhere to some existing interface (think about the Composite, Decorator, Proxy, Object Adapter) also encourage this trend.
On the other end there are design patterns that definitly make a design more costly for both limited resources, typically by introducing extra interfaces with no gain of expressivity. To discuss this case we need to introduce an extra quality criteria on top of our limited resources: the need for extensibility or flexibility. In this discussion design decision need to consider three antagonist forces: the memory effort in the developer head, the time needed by the developer to learn the code base, and the need for flexibility.
Every developer that feels concerned about maintenability or teamwork should be aware about this trade off in order to address it explicitly rather than just by gut feeling. For instance, the more unexperienced the coworkers, the less generic a design should be if they have to support it without help, but opportunities to rationalize the design will be wasted, hence some loss of agility. On the other hand one can decide to go more generic anyway while doing something to improve the expressivity of the code, e-g by introducing empty, useless but expressive sub interfaces just for the sake of expressivity (Taxonomy), or doing some effort on the documentation and training.
This approach of explicitly dealing with the memory and time being consumed in the developer head may suggest new metrics about design quality. I do not have the pretention to propose good metrics here but here are some ideas:
- number of different interfaces (or number of fully qualified method signatures) over size of the code base (maybe with smaller weighting on constructors) as a way to estimate how much memory is needed to be on top of the code base
- proportion of domain-specific names (e-g “Tax”, “Shipping”) within the code base as a way to estimate how specialized the code is
- proportion of abstract words from a corpus (such as “data” or “processor”) within the code base as a way to estimate how generic the code is
- amount of abbreviation and Flesher reading test applied for type and methods naming as a way to estimate how fast it is to discover the code base
- number of explicitely mentioned idioms and patterns (either by javadoc documentation or obvious naming conventions) over size of the code base
(*) We assume here that runtime efficiency is not a constraint since this discussion focuses on software development methodology and human to machine aspects.