More Good Coding Practices

Don’t introduce ordering where not necessary.

Be advised of more subtleties here than are visible at first glance. Consider enumerations; an enumeration value has a name and a code. The code is redundant and is probably there for optimization purposes; as such, you should not work with it. The code associated with a value is order-dependent and as such it will change as soon as we change the order of the values within the enumeration. I’m not saying it ever will; what I am saying is you should not have to care about it. Code that takes little details like the above into consideration is bound to be more robust.

Don’t put half-baked features in.

Say you’re writing an ASP CAPTCHA script. It generates a bitmap but portions of the algorithm are hardcoded to work with a fixed bitmap size. For example, you output a bitmap header that encodes, among other things, the size 86×21 packed in nice hexadecimal words. Down below, you have a huge case statement that processes the image knowing it has a predefined number of sections, based, among other things, on the size. And the list goes on. You now decide to put some constants in there to define the size (width and height) of the image. Now, as far as the algorithm won’t work properly with variations of the values of these constants, there’s no force on earth that should compel you to place the constants in. Better to leave the hardcoded values in there so as to warn any potential reader that you’ve done a really bad job of this CAPTCHA job you’re doing. Note: the example is real, all but the constants—we’re talking about an ASP CAPTCHA module freely available and easy to locate online.

Honor the logical grouping of the code.

Attempt to minimize the context switches needed by the readers of your code. When building complex objects that end up aggregated within a collection or yet another object, instantiate the container no sooner than you need to work with it. For example: (C#, .NET 3.0+)

var animal = new Class("Animal");
animal.Add(new Property("ID", Type.String));
animal.Add(new Property("Name", Type.String));
...

var colors = new Enum("Color");
colors.Add("Blue");
colors.Add("Blue... no, yellOOOWWW!");
...

var human = new Class("Human");
human.BaseClass = animal;
human.Add(new Property("FavoriteColor", colors));
...

var context = new EntityContext();
context.Add(colors);
context.Add(animal);
context.Add(human);

You’ll notice this pattern mostly with unit tests, but also when writing code that is logically separated into steps that build on the objects produced by previous steps, composing them into ever larger objects. One may be tempted to start from the goal, which is to return the end result of the composition, and this temptation may result in a top-down approach to build it. They start with the root of the object graph, then they create some dependent objects and push them in and so forth. This is a good situation where the code that creates the various instances should be pushed closer to their use. The positioning of the object instances close to the code that uses them promotes refactoring by method introduction.

Post a Comment

You must be logged in to post a comment.