Sanity Maintenance

So often these days inside large corporations the IT landscape for a particular business domain is chock-full of home-grown legacy applications.  In many cases the reason for the existence of these applications has been lost in the mists of time and yet the organisations that spawned these beasties still waste good money and good people’s time on keeping these old Jalopies running.  Teams that work in this world of pain no longer focus on the improvement of an application. Instead their blood sweat and tears are spent on a product that should have died years ago.

What a waste.

It comes as no surprise that the good and great developer minds that invented these systems are also long gone, presumably following the quest in the Holy Grail of software development: the Green Field Project.  However back on the ranch, the powerful people that commissioned these software gems in the first place are getting tetchy because of the perceived stagnation in terms of functional development coupled with an ever-increasing cost of ownership. So they start throwing their toys in exasperation at the IT department.

By this stage the major stakeholders in any given software system have had so many sparing matches that they are no longer able to communicate effectively.

Two distinct and diametrically opposed architectural approaches bring about this malaise. Some of the larger legacy applications that I have worked on appear to reach a “critical level of complication”.  This is a point where the code has become so complex that even the most seasoned senior developer blanches at the very thought of simple enhancements as there may be many unwelcome side effects .  Put simply, some systems are allowed to grow to become too monolithically complex to be usefully maintainable

Other projects have gone the other way, embracing Solution Oriented Architecture (SOA) principles too tightly. The result is an application landscape that represents a teenagers face: pimpled with lots of little applications that do things no one understands and are all inextricably linked to one another through a spaghetti of messaging flows.  This is what I call “Implicated Dependency”

To me these two cases seem like two ends of a spectrum. I have often wondered why projects tend toward one architectural extreme or another and not toward a moderate middle ground.  Both end games seem, well … unnatural.

While we are all striving for software utopia, expecting that our digital solution is somehow cleaner than our real world problem, the cost is pragmatism.  There is a distinct lack of moderation in the way the techniques behind how software systems are written. Many developers insist on using only certain techniques at the expense of others. These are the software evangelists.

Software evangelists tout a narrow band of technologies in the belief that use of this collection is the veritable silver bullet to any conceivable software engineering problem. Evangelism simultaneously halts the software’s architectural trajectory at a point in time, effectively carbon-dating the code.  Under hard, critical analysis, these touted techniques may not in fact be as good a fit to the problem as expected.

A narrow band of technologies may limit application authoring to developers with a narrow set of skills, skills which can become rare and therefore harder to supplement as time goes on.  Ironically, many open-source engineering approaches such as Methodologies, Frameworks and Patterns abound for the sole purpose of software development simplification. Yet software evangelism, even of these approaches, may contradict the simplification ideal by inadvertently creating a state of unmaintainable complexity.

As a result of influential evangelism, unwittingly or otherwise the current developer(s) on your project are probably not applying maintenance friendly development techniques.  What do I mean?  Here are some examples of development unfriendliness:

  • not enough care is taken over making the code as simple as it possibly can be. All to often the adage “there is no problem that cannot be solved by another layer of indirection” makes an execution pathway too convoluted with respect to its purpose.
  • the code is not written to allow ease of maintenance. Let us not forget that maintenance occurs both during future development cycles and within the current runtime context.
  • what internal configuration mechanisms exist are simply not flexible enough. They are often the last item considered in a development cycle and as such implemented in a hurry.
  • so often business configuration is not exposed to the user but instead left to the IT department to take care of, dramatically increasing cost, unnecessarily lengthening time to market and increasing the risk of failure.
  • documentation (both technical and user) is almost always deficient. Not enough care is taken to articulate the systems core behaviour in a clear and effective manner

All of these anti-techniques lead to the embarrassing situation where developers and users alike have no choice but to research the systems that they inherit in order to understand the software behaviour before any changes can be made to the code.  This undesirable effect is independent of context: it occurs in both monolithic- or swarming SOA- component landscapes.

So beware your software evangelists.

OK, you say. Big deal. So we like to use what we know. Whats so wrong with that? We know what we are doing and how to do it.  True, but shortsighted.  Most projects with a development budget over 500,000 USD have a production life span of 5-15 years.  Within that lifetime at least two significant frameworks are expected to appear that will be directly relevant to the application.  Why prevent the project from reaping the benefits of these new methods?

The solution?  There is no silver bullet. There is however a very successful human strategy we can employ here: common sense.  Sit in your chair for a few moments and run through some simple “What If” scenarios. Imagine you are the poor sod who has to come along in 12 months and perform some major surgery on the code you are writing today.  Can you make implementation choices now that make your future developer’s life easier?  Imagine for another moment you are the poor soul who has to make some future static data change.  What can you do to make that person’s world less pain-wracked: a simple GUI perhaps?  How easy is it to change the logging level in your software?  How easy is it to reconfigure resources?  How easy is it to automate the testing of this thing?   This is a useful exercise but be careful not to turn the few moments anticipated for deliberation into the next few days.

And the rest of the time you spend pondering should be spent on a question that no developer likes to consider:  How easy is it to decommission the application?  What nasty little dependencies have you inadvertently coded into your solution?  Are your interfaces clear?  Have you pared down your code to its absolute minimum?  How is it presented?  Hows your documentation?

A few common sense/natural decisions made when the software is being born will dramatically reduce the chance that your code will become hated in years to come.  Common sense will reduce the production lifetime dollar numbers.  Common sense will help save the relationship to the sponsor.  Fewer people will be needed. Enhancements will be made to keep the application current and not to back fill original user requirements.  Time to market will be shorter.  Testing will be simpler. Above all, it will be a pleasure to work with such a system.

“KIS,S”: yes, you know what that means.

“Moderation in all things, especially lines of code”

“Work smart, not hard”

“Indirection is powerful. Use it wisely and sparingly.”