10.20.08

Art of Defensive programming

Posted in Design Patterns, Frameworks, Java at 6:48 pm by Administrator

Its been a while since i wrote my last post; Been busy working on a reporting framework of sorts (that attempts to abstract out all implementation details of various reporting tools like Crystal, Business Objects or JASPER reports, BIRT and work seamlessly without developers using the API being bothered with implementation details.

Building a framework is always a learning curve. I have been involved with building frameworks in the past, each one adding different but consistent experiences over their predecessors and so far the only fixed learning experience I have drawn from is that one must always code defensively while developing any piece of logic or code. That would mean assuming following things:

  1. All API users are careless or will get careless at some point
    Meaning most of the framework users will have time crunches and desperate times call for desperate measures. In their desperation they might resort to quick and dirty solution which might not be what the framework was intended to be used for; and although this might work perfectly in use case A, but will most likely cause confusion and break some other piece of code causing chain reaction and finally blame coming down to framework developer. :)
  2. Developers might override the default functionality to fit in their use case
    This is sort of a controversial point but I still standby it. There are times when we must put an end to amount of extensibility even though we live in Object oriented paradigm. As an example; if today i create some class as follows:

    // java docs removed for clarity
    class X {
    
            // bound value.
    	private Integer boundValue = null;
    
    	// sets the bound value ... java docs removed for clarity.
    	public X(final Integer pBoundValue) {
    		setBoundValue(pBoundValue);
    	}
    
    	// gets the bound value ... java docs removed for clarity.
    	public Integer getBoundValue() {
    		// FIXME : Note that this method is not finalized!
    		return this.boundValue;
    	}
    
    	// sets the bound value ... java docs removed for clarity.
    	public void setBoundValue(final Integer pBoundValue) {
    		// FIXME : Note that this method is not finalized!
    		this.boundValue = pBoundValue;
    	}
    }
    

    As you can probably make out methods are not finalized, lets see how that can ruin the whole show … :)

    public static void main(final String[] args) {
    
    		// some long block of code goes here ...
    		final X x = new X(100) {
    
    			// java docs and annotations removed for clarity.
    			public Integer getBoundValue() {
    				return null;
    			}
    		};
    
    		// huge chunks of code here ... and suddenly developer needs x variable afterwards ...
    		// FIXME : Throws a null pointer because some developer decided to play i am the boss :-)
    		System.out.println(x.getBoundValue().intValue());
    	}
    

    The above scenario might be hypothetical, but things like above (not same events necessarily) can happen, hence importance of making your code protected. However this statement has to be qualified by a big if ; and that means making it protected only when a developer cannot for-see that in near future people might need to override this code for some “legitimate” reason. By legitimate I mean, using it the way it was intended to be used and adding additional functionality to it and not necessarily breaking what the original contract was. An example of such a case might be a state object, which maintains the state of say variable x; in such a case it is always wise to finalize accessors and mutators for x, so that it is only used for what it was intended to be.

To account for all above issues and plethora of others defensive programming is the mantra.Defensive programming techniques are not new, in fact this concept is an old one, referring to wikipedia for for formal definition:

Defensive programming is a form of defensive design intended to ensure the continuing function of a piece of software in spite of unforeseeable usage of said software. The idea can be viewed as reducing or eliminating the prospect of Murphy’s Law having effect. Defensive programming techniques are used especially when a piece of software could be misused mischievously or inadvertently to catastrophic effect.

Defensive programming helps reduce code unpredictability; makes code cleaner, more consistent and truly re-usable (by true re-usability I mean re-usability based on applicability not intended to break the contract that is set forth by the developer of the API). This becomes a serious issue once we start dealing with multi-threaded environment; where multiple threads deal with shared data; if the shared data is immutable (state wise at least), we can say that it is safe to share the same amongst different threads.

Not only does defensive programming helps in producing cleaner, efficient and more reliable code; but it also helps support team developers. Being a production support developer is not an easy task by any means. Imagine a programmer being called at 2 in the night to fix some urgent issue and he has to sift through ton of code. In such cases, (Even with the tools available today with likes of Rational Application Developer, Eclipse, IDEA etc), it becomes extremely difficult to debug things, especially when they are being used in a particular fashion in each spot. An example of such scenario might be debugging say a method (non-final) that gets overridden (which was NOT intended to be) in 3 places and each in different ways; This would drive me nuts … yea try doing that at 2 in the morning :D. Needless to say in such cases defensive programming on part of developer helps just a tad bit.

We’ll discuss some of the well known techniques in java world (this should apply to general programming as well) :

  1. Finalize methods where-ever applicable / possible
    Use your common sense to allow extensibility or overriding capacity to methods. This should mean that unless we foresee that in near future this method might be used in n different number of ways (in which case this should be an abstract method in the first place ;) ) it would make more sense to finalize it. A non final method is dangling there to be misused, unless there is some future flexibility that we want account for and provide.
  2. Finalize parameters as a thumb rule!
    Parameter finalization not only makes intentions of a method published or unpublished clear; but also helps in clear understanding of the underneath code; allows usage by references (unless we are dealing with tiered architectures where some stuff lies on a different JVM… ); If those benefits are not enough, here’s a leaf from Martin Fowler’s book : As a first step to refactor code (refactoring to improve code re-usability), finalize parameters. Need less to say finalization of parameters helps in making the refactoring of the code easy. Imagine going through a long method and watching parameters being re-assigned every third line; needless to say this form of coding practice is horrible, but its not unheard off.
  3. finalize classes whenever applicable
    A class finalized will have the same benefits as above, plus will guarantee that the intended functionality is locked and sealed and should only be used and not meant for extension. As an example, take the case of a Shape abstraction that follows non final class Car and a sub class BMWCar and further sub classed to particular model, type etc. (down to very bare specifics); if such a sub specific class is left non final, it could be anonymously subclassed at runtime and the intended behavior would change! imagine a BMW X5 behaving like BMW X3! (i was tempted to say Honda Odyssey but that was probably far-fetched! :D)
  4. Check for nulls, Check the current state, Infer and throw exceptions where-ever possible
    Invariably and this is common practice; arguments might arrive either as being null, or assigned an empty or blank value. In such cases programs can be explicit by throwing exceptions as a thumb rule to ensure that no processing begins without verification of input arguments. Not only input arguments might be null, but even if they are not, they might just be either stale or plain invalid and might leave the state of the entire current instance of class in an inconsistent state, in such cases it would be helpful to throw an IllegalStateException and be explicit about checks. Some documentation as to what might happen on various values being passed always helps in such cases.
  5. Use static typing as much as possible
    I am not proposing that Generics is the ONLY way to go; but i am a big proponent of using generic types and defining type parameters at class level. Taking a leaf from our example of getBoundValue( ) above in class X, here’s the modified code:

    class X<VALUE extends Number> {
    	private final VALUE x;
          // getters and setters for x go here
    }
    

    We have done two things in the above code: 1.) we have made the type of the value x, very explicit (helps in code debugging). 2.) we have made this class extremely re-usable (imagine that we don’t have to create a new class now every time, i use a different bound value type, like a Long would warrant a new class if we go by older code, here i just specify the type explicitly while initializing.

  6. Favor enumerations for maintaining configurations
    An XML file is all fine and dandy for portability, and I would be happy if XML files had some sort of mechanism of self-validation(in fact they do); but since I come from development world, I would like to see compile time errors better than run time errors especially while parsing the file. How is an enumeration configuration buying me defensiveness? Well simply put (and i will not spend much time on discussing enumerations here, refer to : Enumeration tutorials at Sun Site for more details) enumeration consists of only finite states of a class type. It is 1.) type safe. 2.) Immutable (because it is a fixed state). 3.) You cannot extend an enumeration configuration.

    As an example, take some formatting configuration that a business tier logic dictates. for example setting width, height etc (not a good example, since we don’t want those coupled but still); this configuration could reside in an enum with several states like : DEFAULT, DEFAULT_WITH_HEIGHT_MAXED, DEFAULT_WITH_WIDTH_MAXED etc. By providing an enumeration here we have ensured that API users will always use configurations as expected, and just in case they need an extra configuration, they might have to go in and add it. (But this would be highly unlikely, since at the time of decision making and coding, it is the job of an API developer to account for most common and foreseeable cases for different configurations that are needed.).

  7. Favor annotations
    I know that this is probably the most controversial of the points, but I still think that making a language less dynamic reduces the code complexity and reduces the production support time. Development time cost is always much less than bug resolution in commercial software world. For example if I have to allow a bean to be managed by container and if i have to specify in what way i want it managed; i would rather have it as an annotation, like @Scope( ) for example. This approach ensures a compile time error given if the scope is not applicable for the class which i want to be managed. In dynamic environment, a runtime exception would be thrown … How would this make my code defensive? well for one thing; if i have my configuration sitting in an XML file or somewhere else, anyone could go in and change things around transparently without me as a developer having any control over it. If I use annotations on the other hand;I would be free of such a worry. The other reason to favor annotations is their documentation ability, An annotation over a class would inject more static information available to a developer to illustrate its intent and purpose; makes their lives simpler and efficient. Josh bloch wrote in his ever so popular Effective Java stating that we should favor annotations vs naming conventions, here’s another instance of why annotations make our code more defensive; because Naming conventions rules are not enforced, but annotations can be compile time enforcing!

I tried to do justice to complex subject of defensive programming; In keeping with simplicity, I tried focusing only on Java programming language, although conceptually they are applicable in almost all of the languages, traditional in some respects, and non traditional in many others. I would love get feedback. Thanks once again for encouraging emails, makes blogging a lot more fun! :)

Regards
Vyas, Anirudh

« Previous entries