Often times I see new programmers come onto the board and show some code demonstrating very dynamic programming. Fantastic, but then they attempt to either hard code values into it or have the dynamic activities spread all over the program instead of having it in one place. Then when the code gets a bit unruly, they have too many things changing that they can’t keep up and find the error. As a designer, not just a developer, your job is to find the places which are likely to change, and if possible, put them together into something that makes maintenance easier for others… and yourself. We will cover a few of these tell tale signs of change and how to attack them in such a way that it makes maintenance a breeze. All this on the Programming Underground!
One thing common to great designers is their ability to predict what part of a system will change. If they can identify these places early, they can design it in such a way that future developers can quickly see what needs changing and change it without affecting the rest of the system. After all, wouldn’t that be pretty nice? Change one line of code or build in a new feature and the rest of the system remains as is?
So what are some places that are likely to change? If we can identify some of these areas then we can easily look for them in our next project. Here are some areas to cover…
1) Business rules. Business rules are the rules of a business (duh) that govern how that business operates. They determine work flow, how things are done, why people do the things they do and are often the rules your software must abide by. The idea is that businesses change to meet market demands, thus their rules change. A great example of this are tax rates on a product sold. If you are hard coding 7.5% as your tax rate, if that tax rate changes for any reason you are going to have to go in and change that variable… or worse yet change it in many places! This is just one of many business rules and, depending on the industry, the rules could change a little or a lot!
2) Hardware dependencies. Any code or any part of a design that relies on hardware being of a certain type or doing something a certain way, then if that hardware is changed it could break your system.
3) Input and output. This would be the data coming in and out of the system. Like an external file or a database. If the format behind this external source changes, like adding a new column to the database table, then obviously you are going to go back into the program and account for this external change in format. A good practice is to isolate a database using a class (covered later).
4) Nonstandard language features. Any time your system uses something that is non standard you are dealing with fire. Not that you shouldn’t use it, but help secure your system because if it is not standard it may be open to radical changes from one version to the next.
5) Difficult design areas. Anywhere the code is really complex to understand and the process is very lengthy are usually good areas for change. Usually with high complexity comes increased chance of it being done poorly and thus will probably need tweaking in the future.
6) Status variables. These are variables that hold state information in the program. Our tax rate variable is a good example of a variable that might be defined right at the top of our program as a status variable. It tells our program to use a specific tax rate in all its calculations and in order to change our program we would be changing the variables which manipulate the program. These can also be any kind of global variables that more than one function is using. Even though global variables are discouraged in design, sometimes they are still needed.
You probably can think of a few more, but these are just some of the places for changes in a system. By quickly identifying these key areas you can make it easier for someone to locate and modify them without having to do a bunch of code everywhere in the program.
How do we go about setting these problem areas up for easy modification in our design? Good question. The first step was to identify the problem areas, as we just did. The second step would be to separate these areas out of the regular code. Modularize or compartmentalize these areas. If we can get the problems out of the flow of the “good” independent code, then we can easily go to step three and isolate them into their own functions, their own modules, their own “one stop” location for all system changes.
This might mean putting all the status variables into their own class called “settings” or some kind of control class. It could mean creating a class which handles the control of multiple other classes. It might be a function designed specifically to handle a particular piece of hardware so that if the hardware changes, we need to simply change that function. This way if I need to change the behavior of the system I know to go to a specific class/function and make the changes there, confident that no other code needs changing.
A great example is what I eluded to earlier about the database. If we can put all the code related to handling database functionality into a single class, shielding our program from the tedious work of having to write code for SQL Server, then if we change databases to Oracle, all we need to do is modify the one class if the database type changes. The rest of the program will be unaware that we changed the database.
Once we have everything broken out and isolated, we can create class interfaces which are insensitive to change. We can generalize them, build a shield around the classes/functions to handle incoming and outgoing data that are immune to any real fluctuations. In PHP a function that works along this principle (but of course is not bulletproof) is the strtotime() function. You can feed that function all sorts of formats. If I give it a date with the year listed first and change it to an American formatted time where the year is listed last, it still gives me the proper timestamp either way. It is insensitive to that change of date format.
In conclusion if we identify the areas likely to change, pluck them out of the flow and put them into isolated modules and functions, put these classes and functions in one location for easy access, and make them insensitive to changes in input and output, then you will quickly see some improvements in the stability of your code. Keep in mind that once this is all done, you should be able to easily pull out one of these classes or functions and drop them into another project and they still work. They should have no dependency on any other code in your system. Excellent code for library of useful functions.
Hope you enjoyed this entry and got some great ideas how to clean up your code to make it a bit more bulletproof and stable. Thanks again for reading. 🙂