Programming for Change

Clayton Neff Programming 5 Comments

It has become cliché to say that the only constant in life is change, and most people accept it as a given. However, we often don’t take it to heart when we code. We prototype something together using “Magic Number” hard-coded values, we use a new library by making calls directly into its functionality, we cut-and-paste a function that does almost what we need, changing one or two lines to get it to work, and so on. All those decisions seem harmless and allow us to get our prototype working more quickly, but they invariably come back to bite us (and if not us directly, the poor guy who has to maintain our code).

There are things we can take better advantage of to help us avoid a lot of these situations. You are probably aware of most (if not all) of them, but being reminded about them every once in a while helps us all remember to use them, even if it slows us down a bit.

Note: this article is based on a presentation I originally prepared for a computer conference back in the early 2000s. However, based on some of my recent experiences, it is still quite relevant, so I thought I would resurrect it here.

Avoiding “Magic Numbers”

Most modern languages provide constructs for easily dealing with “Magic Numbers.” In Java, there are enums to hold collections of constant data. And now that we can extend them to add our own methods, they are even more powerful. If you have a constant that is pretty stand alone, make it a static. I usually put it in the interface of the class that needs it defined.

For those things that are constant across an activation of your program, but perhaps not across all activations (database access parameters are a classic example of this), property files are best used. This allows you to take advantage of the constant-ness of the values in your code, and yet swap them out depending on the environment you are running in.

See Also:  JSON Web Token .NET Core Demo

Another good tool for managing these pseudo-constants is dependency injection. By programming to the interface we can swap out the implementation as desired, changing the “constants” as needed.

Avoiding Duplicated Code

This is one of those situations that we all mean to avoid, but often use when push comes to shove. One of my colleagues espouses the attitude that you should never type the same code twice. If you have two classes that have a similar method, should they have a common superclass? Our tools have improved much over the decades, and creating that superclass (if it doesn’t already exist) has become almost trivial, so why not do it?

Oftentimes you need similar functionality across many different types of classes. Before you copy that method, think about what it is trying to accomplish. Would it make sense to have that capability encapsulated in a utility class? If so, take some time to explore the utilities that are already available to you. I recently ran into a situation where some older code was doing a somewhat specialized string comparison (multiple strings with unusual null handling). The code was long and somewhat convoluted (not to mention very specific to the problem domain). By making use of the null aware functions in org.apache.commons.lang.StringUtils, we were able to reduce the lines of code by an order of magnitude.

Sometimes the similar functionality needs to interact with the surrounding code more than a simple utility method will allow for. This may be a good candidate for using the Strategy pattern. Utilizing this pattern allows you to use common code across many different classes, without having to worry about a complex or convoluted class hierarchy.

See Also:  Progressive Web App Tips and Tricks

Avoiding Library Dependency

As more and more open source tools are made available, the likelihood that your team will want to change which library they depend upon goes up. As different libraries leap-frogging one another, you want a clean way to take advantage of the new features offered. If they all programmed to the same API, you could handle that with dependency injection, as was mentioned above. However, that is rarely the case between competing projects in relatively new problem spaces. So what’s the solution? Create your own interface.

You can start out small, incorporating only the functionality you need. You can even “improve” the functionality from your point of view, combining several library calls into a single interface call. This can simplify a more complex and configurable interface to something more suited to your applications use.

One recent client was using three different libraries for accessing Excel(tm) worksheets from Java. They didn’t really need all three, but they had coded directly to each as they used it. The problem arose when they wanted to use a new feature from one library in a project that had started in a different library. If they had coded to a common interface they could have made the change quite simply.

None of these suggestions are revolutionary, but remembering to follow them from the beginning of a project will make everyone’s life easier in the long run.

— Clayton Neff, [email protected]

Comments 5

  1. Nicely done! I am starting to work with JSON in Java, and persisting it to the database in some cases. I have wrapped one of the open source libraries with some classes and methods that I believe will allow me to swap out the underlying library if a dominant one comes to the fore. This approach has also allowed me to make the JSON parsing process very similar to code that I have developed around SAX parsing, so I can re-use the design patterns at least.

    1. Thanks Jay. That is a perfect example of what I was talking about. It is hard to make ourselves do it, especially when we are working with the first library of its type, but it really does pay off in the long run.

  2. Yep. These are some of the first things I remember Clayton taught me when I was getting started with Java. Use the interface so you can change out the implementation. So many people make this common mistake, especially with Collections, and then have to make massive changes whenever their implementation changes.

    As for code reuse…I remember working for a manager many years ago who believed that the code would “perform faster” if it didn’t have to call another method or class, and we were not allowed reuse for that reason.

    Clayton, I think you probably could make all your blogs follow this topic and never run out of material!

    1. Glad I could help you see the light all those years ago Dave. As for writing about the same thing all the time, that would get boring for all of us.

What Do You Think?