The Paradox of Simplicity
In agile development, it is common to hear people say “do the simplest thing that could possible work.” This is a corollary to YAGNI or “you ain’t gonna’ need it.” I don’t hear many of my fellow developers outside of the agile movement arguing with those sentiments. It seems we can all agree that we should not exert effort beyond solving the specific problem at hand.
There is, however, contention about what the implementation of such pragmatic simplicity looks like. As a .NET practitioner of agile development, it is common for me to write tests before implementation code. I often write interfaces which have only one implementation. I may use an inversion of control container, an object-relational mapper and other infrastructure utilities which appear to add unnecessary complexity to developers with a different outlook.
One of the most glaring anti-patterns for simplicity in my view is the SQL data source. It seems very simple and pragmatic to some because it allows the developer to quickly create a forms over data application which will deliver value to the client. While I agree that there is tremendous immediate benefit in using the SQL data source for the initial delivery of value, there is also a tremendous cost down stream.
In my view, the SQL data source represents all that is flawed in RAD (rapid application development) tooling. It allows the developer to quickly get data into and out of a database into and from the user interface. It also tightly couples the data access implementation to the user interface making future changes very difficult to implement. Fundamentally, tools such as the SQL data source represent the software equivalent of a Rube Goldberg machine where each bit of functionality relies intimately on the implementation details of it’s neighboring components.
The core problem in software from my experience is not the delivery of the initial version of any functionality. The core problem is that that I and the customer never know when or where the code will need to change, but we know for certain that it will change. Enabling change therefore becomes a top priority along with delivering value.
If I deliver value up front while discouraging later changes to the code, then I have not actually delivered value. I have in essence paid with a credit card. The cost of changing the code must be paid later with interest. This phenomena is commonly referred to as “technical debt.”
In my agilist mindset, I view the avoidance of technical debt as an essential element of simplicity. High coupling and low cohesion are too high a price to pay for immediate gratification. Furthermore, I have found that once I become experienced with the tools and practices of agile development, there is little cost, if any, to building changeability into my implementation from the start.