Software design as a matter of economy

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.

Read More

Sharing a common architecture or vision within a team

What do you think about when you hear the word “architecture” about software? Fowler defines it: whoNeedsArchitect “In most successful software projects, the expert developers working on that project have a shared understanding of the design system design. This shared understanding is called ‘architecture.'”.

However for most people the word “architecture” comes full of middleware connotations, hence I consider this word now inappropriate. Let us consider here the concept of a shared “vision” of the design.

First it has to be a shared vision of the domain, for instance the interest rate swaps trading business. Words must have only one meaning, known by everyone, from IT, marketing or support. A shared glossary is key for that.

Then the IT team must share a consistent set of practices: consistent between developers, and consistent between practices themselves. This also means that the set of practices de-facto excludes other practice that conflict with it, and this has to be clearly acknowledged.

Even though any set of practices can be considered arbitrary, everybody in a team must adhere to it, preferably wholeheartedly. Of course the more accepted and documented the practices, the easier it is for everybody to adhere to them.

For example, a team can have a set of practices that includes Agile programming (be prepared for change, no big design upfront), automated testing (unit tests, stress tests), domain-driven analysis as devised by Eric Evans, the use of proven solutions when they exist (hence design and analysis patterns from GoF, POSA, Fowler, Doug Lea…), a bit of functional-programming style (favour immutability and side-effect-free functions, pipe and filters…), and Eclipse default coding conventions.

Some practices that also belong to the shared set of practices might not be directly documented, though they derived from articles, papers, blogs and some personal opinions. Examples of such custom practices that I like a lot include “Align the code with the business” and “think options not solutions”.

“Align the code with the business”, focuses at the smallest level, i.e. at the class and method level. Just every bit of the application must make sense with the domain considered. A class must reflect some relevant concept, concrete or more abstract, of the domain, not of the requirement. The rationale is that while requirements change all the time, the domain concepts are very stable; they are not true or false, they just exist!

“Think options not solutions” refers to the very basics of Agile and XP: “be prepared for change”. It also acknowledges the fact that most of the code in a well done software project provides standalone, encapsulated and reusable building blocks that are then assembled together using a smaller amount of glue code, that can even be reduced by using a dependency-injection framework such as Spring. Typically, a concept from the domain, such as an interpolation algorithm in the finance domain, translates into an Interpolation interface along with several alternate implementations. Most of the time, only one implementation out of the ten possible is really used at a time. However the option to use the other nine alternatives is there. This also means that we can assemble a release of the software using some subset of its building blocks, and assemble another release using another subset, at the same time. One codebase, several possible applications: this is the goal.

In addition to every explicit practices, the existing code base implicitly shows practices that can either be reused just for the sake of consistency, or replaced as widely as possible when they conflict. Prior art, when of good-enough quality, can form a skeleton for a shared vision of how to create software. Again this is arbitrary, but consistent, and consistent design is valuable in itself, and often more than the design decisions themselves.

Of course there is a point where more shared practices become counter-productive, for instance when there are too many of them (more efforts to learn by newcomers, feeling of loosing freedom, lack of flexibility). However when they are standard enough, or becoming standard enough, developer should consider that acquiring these practices a long term, beneficial, investment.

Initially published on Jroller on Monday January 21, 2008

Read More