System Consistency and Predictability
by e. sammer - firstname.lastname@example.org
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,
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
shape of a system. It's easier to work in
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
return-0-or-1-or-negativeverses 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.