System Consistency and Predictability
by e. sammer - esammer@lifeless.net

Oh, how many ways can I parse a configuration file? Let's go one better - how many different configuration file formats can we have within one system? How many ways can we pull data from the database or from cached sources? There seems to be no limit to the ingenuity of some developers, and that's good. There also seems to be no limit to their freedom to write one-off components, and that's bad.

Most systems evolve over time and with good reason. One would be hard pressed to know (exactly) where a system needs to be in a year or two. I have heard talk of long term planning for system development, but I can't say I've ever worked in an environment where the requirements stay steady enough that the design doesn't change along the way. I'm young, still, so I suppose there's hope.

What I have seen, and certainly more of my share of, are companies full of smart people doing smart things even when it's not so smart to do them. Far too often, team leads or system designers (or whoever purports to be in charge) either restrict too heavily or provide too much leeway to the individual developers or teams. There must be a middle ground where developers can remain autonomous and functional (not to mention happy) and, at the same time, be respectful of system consistency. Managers should not lord over coders waiting to pounce on the slightest variation in methodology where the derivation is subject to opinion. That certainly won't endear you to others, be they subordinates or otherwise. The desire should be more to maintain the consistency of the behavior of the system and the elements it is composed of (frameworks, libraries, etc.).

Realize that the initial investment in stabalizing behavior, core codebase, and even methodologies is one worth making. I'm not talking about sitting around and debating the sole cases where a Factory pattern is to be used rather than an Abstract Factory - that remains the job of the implementor (or at least pre / post review). You can run your budget and everyone else's patients down with over analysis of things, straight away. That said, there needs to be an agreement between team leaders as to the shape of a system. It's easier to work in examples here.

All systems tend to require similar abilities (or functionality, as some would say), at some level. What we want to do is decide what the best approach is to each one of these core abilities. You can decide how generic they can be, or if not at all, how the interface to them may be made to be generic so they can be interchangable as necessary. The goal would be to minimize the variations and number of the implementations of these abilities or subcomponents so you can benefit from code reuse, consistent behavior (a side effect of consistent code bases, most of the time), and developer familiarity. Let's take an example case of a framework that is to be the core of many interrelated systems at a company. The idea would be to write a framework that all applications and systems could take advantage of, even if piecemeal. Here is a far from complete base analysis of the abilities the system may require.

Configuration handling
You can always assume there is some level of configuration to an application, be it XML files with complex data structures and relationships, constant defines in C / C++, or somewhere in the middle.
Network handling / abstraction
Most modern applications have some distributed element to them. You may need to abstract network operations like web services, raw socket IO, messaging services, and file transfers, so that part of the system that was local today can be a web service or ESB service end point tomorrow.
Data access
Applilcations and systems that access data of any form can usually benefit from a common access layer to the relational database, XML file set, CSV file store, or other. This can also form the basis of your configuration handling structure.
Error handing / reporting
Trust me, making sure everything in your system handles errors the same way is something you'll never be sorry you did. Think exception handling verses C-style return-0-or-1-or-negative verses whatever. There's nothing worse than thinking something will throw an exception, not getting one, and thinking everything is okay while the method returned -10 (which, of course, means the file doesn't exist).

This is, of course, a very brief and incomplete look at what may be required within our example framework, but you can see how having standard ways of doing these things can promote stability and consistency within a system. You'll want to look at systems and applications you're familiar with (or not) and try and analyze the commonality of components. This is even higher level than just traditional concepts of object oriented programming and code reuse - there's more to it than just this. You can create an environment that is not only highly modular, being composed of many smaller simple subcomponents, but something that can extended with ease. This is really the combination of a number of important design concepts like loose coupling, encapsulation, interface-centric design, reusability, and other flavorful things.

The abstraction of common features (which manifest as components) will change how you think about things. You may need to further explore or revisit some of your more tried and true favorite solutions to common problems. Don't take that as something negative. Consider the need to constantly evolve your view of system development much like you would evolve the system, itself; methodically and with caution, but striving to make it better at what it does and needs to do as things change around it.

Was this interesting? Are there inaccuracies? Could it be better? Do you want to contribute? Send me your comments.