There is a little known but widely observed anti-pattern in software development that has been named “The Inner Platform Effect”. This anti-pattern is summarised as:
"The Inner-Platform Effect is a result of designing a system to be so customizable that it ends up becoming a poor replica of the platform it was designed with. The "customization" of this dynamic inner-platform becomes so complicated that only a programmer (and not the end user) is able to modify it.”
In other words: the more configurable you make a system, the more complex it becomes to configure. Taken to an extreme, whereby the system exposes more and more functionality via its configuration, it becomes a poor shadow of the system and tools used to implement it. A poor shadow, that is more complicated, yet less powerful.
Said in yet another way, you have to tell a computer what to do, you can either do this in a language such as c#, java or ruby that have amazing tools, are well documented, are supported by a large vendors and have large user bases for which it is (relatively) easy to find staff, or you can implement your own “language" or "platform", be that via rules, complex configuration or a DSL, that allows the system to be configured to provide similar functionality to that which you get with the system or language in which you implemented it.
On one end of the spectrum, you have a system which is not configurable in the slightest but which requires no skill or effort to setup but does not allow you to react quickly to changing business requirements. On the other end, you have a system which is infinitely configurable but which is extremely complex to configure, requires specialist skills and knowledge which aren’t known outside of your organisation but which enables you to support a wide range of scenarios not initially envisaged when the system was built, in theory.
Other commonly observed relationships include:
- Development time and development complexity required to implement a system in a user, not developer, configurable manner is often orders of magnitude greater than it is to implement in a proscribed but limited form.
- The more configurable you make a system, the slower the performance becomes. This relationship is not absolute but it often takes directed effort to negate.
- The more flexible a system is the less robust it becomes - you have non developers changing programme behaviour, without tests and in an increasingly large number of variants.
It is important to realise that we are not dealing in terms of absolutes here and that there is some form of non-linear curve between the extremes of each relationship distribution. I’ve not been able to find any empirical research into the exact correlation of these properties but they do serve as enlightening rules of thumb.
From the above rules, it’s possible to compile the following list of trade-offs:
- Flexibility/Power vs Complexity
- Flexibility vs Performance
- Flexibility/Power vs Development Time
- Flexibility vs Robustness
Evaluating any project in terms of the above observations is not a straight forward task. You may see issues with performance. You may see issues with poor documentation leading to lack of clarity. You may see complex configuration baffle end users (some of which are developers). You may see features become complex and time consuming to implement.
The following questions can be utilised when balancing the needs of configuration vs complexity vs performance vs development time vs robustness:
- Is this feature likely to change? If it changes slowly between deployments, would it be better developed as a core aspect of the system rather than via a configuration tool?
- Is flexibility through clean code, adherence to principals such as Open Closed and designing for change a more managable and maintainable approach?
- Is the configuration tool suitably easier to master, given the constraints of skill set, target user group and documentation, to make it worthwhile to develop?
- For example, are your configuration features easier to learn than your DBMS?
- Is the need for features enabled by the configuration better validated in a hardcoded manner first: specialise before generalising?
- Does the configuration tool expose enough power, as an abstraction, to mean the abstraction isn’t leaky?
- Is the subset of the outer system exposed by the inner system sufficient?
- Would a feature be cheaper to implement, overtime, via a configuration or via a concrete implementation?
Constraining the flexibility to the areas of the application that are likely to change whilst developing more static parts of the system in a more concrete fashion is often a technique which can tame some of the runaway pain of a project heading towards a fully-fledged inner platform. This is, of course, often easier said than done, as knowing what is likely to change up front isn't always possible.
There is value in all of flexibility, simplicity, performance and rapid development time. It is very difficult to have them all. Striking the sweet-spot between the inherent trade-offs is key. Constantly re-evaluating the balance and asking the questions is essential. This, in a nusthell, is the heart of the challenge!