After Technical Debt, technical Options

In finance, options are powerful tools for traders, and many design practices including design patterns can be seen as options. Options can -perhaps- yield a great benefit for a certain and immediate cost. If this cost is cheap enough it can be quite attractive.

An option to buy a stock is a right to buy the stock at a predefined price (let’s say EUR25) before a given date in the future. Until this date, you can freely exercise the option (i.e. buy the stock at EUR25), or not (do nothing). Of course if it happens that the stock price is greater than EUR25 (let’s say the stock is now EUR35), if you exercise the option you earn money (EUR10), and for that reason the option is worth something (EUR10 here, or even more if we expect the price to go even higher in the future).

In finance, the price of the option is directly linked to the expected benefit it can bring, even though this benefit is not certain. To be more precise, the more the stock price moves up and down, the bigger the option value: this instability of the price is called volatility, and you can think of it like a standard deviation in statistics. Options traders actually trade volatility: the higher the volatility (i.e. the less stable the prices), the more valuable the option.

Many design practices can be seen as options, and some are indeed cheap, almost free options. A free option is something that a reasonable investor cannot refuse to get, since it costs nothing while it can perhaps yields a benefit: this is actually an uncertain version of a “free lunch”. A design practice that would cost nothing is hard to resist, since it yields potential return in exchange for nothing.

In the spirit of the Technical Debt, we will focus on the cost of maintaining the code over time. Any change to the code must be weighted in accordance to the burden it will bring compared to its benefit.

Plenty of options here
Plenty of options here

Technical options in the code

In practice, everything that improves the flexibility of the software is de facto like an option: it creates additional opportunities that we can use or not in the future. Typically, it can enable the designer to change his mind at a later stage at no cost, or to defer a design decision.

The design principle to code against abstractions rather than implementation comes immediately to mind: coding against interfaces is probably the number one technical option. Therefore the question is: given this piece of concrete code, should I introduce an interface and reference the code through the interface, or should I leave it like that? Just like in finance, the answer is: it depends on the upfront cost of the option (adding the extra interface) compared to the anticipated stability of the feature the code is doing (is it likely to change in the future?).

In this case, the upfront cost depends on the tools (with modern IDEs with wizards and refactoring capabilities it is easier to add or even extract an interface automatically), and perhaps on what you like to do or not (if you hate having too many classes then adding an interface will cost you more, subjectively). Some commercial source control systems that are not convenient with widespread refactoring also make the cost of future changes much higher, and as such they encourage building flexibility upfront.

Going further, many design patterns can be considered as options to improve flexibility for a minimal cost. Out of the GoF patterns, the patterns Abstract Factory, Strategy, State, Visitor, Iterator, Bridge and Builder directly plan for easy change of behaviour or extension in the future (typically through additional interfaces as well), and thus are simple yet efficient ways to buy technical options.

Various elements combine together for bigger value added
Various elements combine together for bigger value added

Technical options Vs. YAGNI

Knowing the future is hard, and YAGNI is there to remind us that. If there are practices that cost a little to introduce and that can bring benefits later, and if we are so poor at anticipating change, why not just introduce them later? This is right, in most cases YAGNI applies, unless we can anticipate a need. The funny thing is that while the introduction of interfaces (directly or through the patterns mentioned before) creates opportunities to vary the implementations, it also creates opportunities for other opportunities. The new interface enables the addition of non-intrusive structural patterns that revolve around an existing interface, such as Decorator, Composite, Proxy, Adapter, Null Object, and every combination of them as suggested by the Interpreter pattern. (This introduction of such patterns, by the way, is precisely what most IoC containers, application servers and AOP frameworks do to add functionalities). How these patterns combine together under the common “umbrella” interface is kind of fascinating to me, and it always reminds me about the Network Effect: the more we use an interface, with implementations or opportunistic patterns, the more useful it becomes. I believe that a net of patterns like that can become so useful that it becomes irresistible. You will gonna need it.

Of course there is nothing really new in all that, nothing more than a new metaphor to help explain to managers. Even if they do not know what an option is, I am sure they can understand the concept very quickly.

I have been pushing this approach that I called “Think options, not solutions” in my former team to emphasize that we can build the system even if some of its business behaviours are not completely known yet, as long as we can define their contours and start with an arbitrary solution. The goal is that we are confident we can change it later with no pain. This was justified from a business point of view because we did not know what the market was expecting, for the product (an interest rate swaps multilateral trading facility) was too novel. In that environment, change was definitely not something we feared, rather the opposite: it was stimulating.

Just like traders speculate on volatility using options, developers can speculate on the stability of the business features using (or not) design practices that increase flexibility. The little extra effort to introduce these practices must be weighted by the expectation that it will be useful. And just for the fun, anyone interested in computing the value of a technical option using the Black-Scholes pricing model?

cyrille

Software development, Domain-Driven Design, patterns and agile principles enthusiast