Archive for the 'Design Patterns' Category

Let design guide, not dictate

Tuesday, May 27th, 2008

A good design should be intended to guide implementation, not dictate it, and for good reason as in the real world of software development requirements and systems are far to complex and dynamic in nature to view a technical design as anything more than a basic prescription intended to form the basis of an efficient implementation. Yet far too often many people seem to believe that once a detailed design has been completed and approved implementation should be a breeze; however this is just not a very realistic expectation.

For instance, one of my core job responsibilities is to review technical design documents and provide feedback and direction. This is an iterative process which typically has between 1-3 iterations depending on the complexity of the system. Initially an engineer is given requirements for review; he/she then begins an initial draft of the design and once completed passes it on to me for review. I then review the document and provide feedback where applicable, either via annotations to the document itself or by sitting with the developer, which is by far my preferred process. Should modifications be required the developer will then make revisions as needed. This process is repeated until final design has been approved. At first it may appear as if only a single iteration of design and review would be needed, however more often than not, requirements may not be completely understood during the beginning stages of design, nor are they set in stone so it is very common that a design will need to change during the early stages of a project or even throughout the entire development stage. Once final design has been completed an engineer then begins implementing the design. Theoretically this may appear to be a quite simple process: create a great design which contains as much detail as possible, review it, make revisions and approve it, then just pass it off to any old developer to implement and that’s it, done - wrong!

There are a number of problems to this approach. Below I have outlined the three I feel are most significant and the solutions I have found to address each.

  • Creativity
    The first problem is that a design which goes into too much detail completely limits or even worse, kills creativity - which in my opinion is the single most important trait a developer can possess, especially when designing. The developer is now merely a typist and will undoubtedly become very bored when implementing the design, especially if it is not even his/her design to begin with! Because of this lack of creativity the final code will ultimately suffer and bugs can be expected. Keeping design on a higher level allows developers to have the creative freedom needed to provide quality implementations and work they can feel is their own.
  • Flexibility
    The second problem is that the more detailed and precise the design the less flexibility there is when requirements change and modifications need to be made to the design and thus implementation. For example, if a design contains very low level details, such as method signatures and other implementation specific details the ability to change the design now becomes increasingly complex and will result in much of the design needing to be reworked significantly. In addition the more detail there is the harder it is to write unit tests against the design as the actual implementation has already been defined. Designs need to be very high level and should not go beyond identifying class names, their responsibilities, relationships and dependencies.
  • Tools
    The third problem, which is probably the single most consistent problem I have recognized in my experiences is that far too often developers get caught up in all the details of UML notation and related tools. Again this negates creativity and results in the developer concentrating more on making the design look technically correct rather than concentrating on designing towards a great solution to the problem at hand. In addition this also results in unnecessary time being spent to complete the design, time which could be much better spent on something that produces a better pay off for the project. Now this is not to say that UML shouldn’t be used, actually quite the contrary. I strongly feel that a final design must be in UML as a shared language is needed in order for everyone involved in the design and implementation to easily understand the design. I insist on a technique where developers draw out their design in any way that can be easily understood by them without having to give any thought to anything other than the design itself. Only once the design is finished is the use of Visio or other UML tools to be used.
  • The above illustrates the three most common design issues I have encountered, most of which pertain to over detailed designs, as well as the approach I take in addressing each. If you have not encountered any of these issues in your own work than that is generally a good sign, however try to keep them in mind when designing as it will pay off in the end. The important thing to keep in mind when designing is to design for flexibility and simplicity. Less is usually more and the KISS principle, especially when applied to software design will always pay off in the end.

    Principle of Least Knowledge

    Saturday, February 2nd, 2008

    One very important (yet often overlooked) design guideline which I advocate is the Principle of least knowledge.

    The Principle of Least knowledge, also known as The law of Demeter, or more precisely, the Law of Demeter for Functions/Methods (LoD-F) is a design principle which provides guidelines for designing a system with minimal dependencies. It is typically summarized as “Only talk to your immediate friends.”

    What this means is a client should only have knowledge of an objects members, and not have access to properties and methods of other objects via the members. To put it in simple terms you should only have access to the members of the object, and nothing beyond that. Think if it like this: if you use more than 1 dot you are violating the principle.

    Consider the following: We have three classes: ClassA, ClassB and ClassC. ClassA has an instance member of type ClassB. ClassB has an instance member of type ClassC. This can be designed in such a way which allows direct access all the way down the dependency chain to ClassC or beyond, as in the following example:

    // ClassA defines a member of type ClassB and provides
    // access to the instance
    public class ClassA
    {
        private var b:ClassB;
       
        public function getB() : ClassB
        {
             return b;
        }
    }

    // ClassB defines a member of type ClassC and provides
    // access to the instance
    public class ClassB
    {
        private var c:ClassC = new ClassC();
       
        public function getC() : ClassC
        {
             return c;
        }
    }

    // ClassC could expose additional members and on and
    // on creating more and more direct dependencies
    public class ClassC
    {
        public someType:SomeType;
        …
    }

    // client implementation
    var a:ClassA = new ClassA();
    var sometype:SomeType = a.getB().getC().someType;
     

    The above example is quite common, however it violates The Principle of Least Knowledge as it creates multiple dependencies, thus reducing maintainability as should the internal structure of ClassA need to change so would all instances of ClassA.

    Now keep in mind that in all software development there are trade-offs to some degree. Sometimes performance trumps maintainability or vice-versa, other times readability trumps both. A perfect example of where you would not want to use The Principle of Least Knowledge is in a Cairngorm ModelLocator implementation. The Cairngorm ModelLocator violates the Principle of least knowledge for good reason - it simply would not be practical to write wrapper methods for every object on the ModelLocator. This is the main drawback of the Principle of least Knowledge; the need to create wrapper methods for each object, which are more formally known as Demeter Transmogrifiers.

    The goal of good software design is to minimize dependencies, and by carefully following the guidelines provided by The Principle of Least Knowledge this becomes much easier to accomplish.

    API Design: Method parameter objects

    Saturday, January 12th, 2008

    When defining a constructor or method with more than three parameters it is considered a best practice to create a parameters object for holding the values which are required. This especially holds true when some of the parameters are optional (as they will contain default values) and also when two or more consecutive parameters are of the same type (as developers may accidentally transpose these parameters - which will not result in compile time or runtime errors, making debugging a nightmare!)

    The most appropriate solution for such cases is to break up the method into separate methods, however when this is not feasible creating a parameters object will improve both code readability and provide a cleaner design which leaves less room for unexpected errors.

    Consider the following method:

    public function someMethod(a:String,
                               b:Object,
                               c:int = 1,
                               x:int = 2,
                               y:int = 3,
                               z:Boolean = true):SomeType
    {

    The parameters defined in this method are typical of what you will often see, however it is much cleaner and reliable to create a parameters object for holding these parameters. In addition, a parameters object allows for a much easier client implementation as default values need not be reassigned for all parameters which proceed a parameter which you need to specify a value other than the default value. For instance, if a method accepts 5 parameters and the first two parameters are required but the last three are optional, if you you need to specify a value for the last parameter you will need to re-assign the default values for the proceeding parameters, when in fact you really only need to specify three parameters.

    The following example demonstrates creating a parameter object which can be passed to “someMethod”:

    package
    {
        public final class SomeMethodParams
        {
          public var a:String;
          public var b:Object;
          public var c:int = 1;
          public var x:int = 2;
          public var y:int = 3;
          public var z:Boolean = true;
           
          //only specify required parameters in constructor
          //optional parameters are simply public properties
          //which have default values assigned
          public function SomeMethodParams(a:String, b:Object)
          {
              this.a = a;
              this.b = b;
          }  
       }
    }

    When invoking “someMethod” clients can now simply instantiate an instance of the parameter object, set values only for what is needed and pass it in as follows:

    var params:SomeMethodParams= new SomeMethodParams("a",{}) ;
    params.z = false;

    instance.someMethod( params );

    So if you would like to improved code readability and provide proactive exception precautions, consider utilizing parameter objects for methods which require more than three parameters.

    AS3 Singletons, revisited

    Friday, December 7th, 2007

    The topic of Singletons in ActionScript 3.0 has been coming up again lately and it has been very interesting to see all of the unique solutions the community has come up with. In particular I like the idea of having Singleton metadata which would allow the compiler do all of the work for us.

    Personally I feel the Singleton pattern is extremely useful. It is arguably one of the most common design patterns around today. Practically every management centric API requires a Singleton one way or another. Some developers claim that the Singleton pattern is nothing more than a euphemism for a global variable, to some extent this is true, however the intent of a Singleton is clearly different.

    As useful as the Singleton pattern is my biggest complaint about Singletons has always been the actual construction code required to create / protect the Singleton instance. This extra code often becomes quite verbose and it is annoying to have to sift through all of the Singleton code when working with the actual class implementation code. It would also be nice to not have to constantly re-write the Singleton construction and implementation code every time a Singleton is needed.

    So is there a way around all of this? Yes!

    I developed a simple class called SingletonMonitor which singleton classes can extend to allow the omission of all Singleton specific construction code. All that is needed is to have the class which is to be a Singleton extend SingletonMonitor. That’s it. No more getInstance(), inner classes, type checking and so on is needed. As a best practice I recommend that you define the Singleton instance in the class itself in order to improve code readability.

    An example demonstrating how to use the SingletonMonitor can be seen in the following:

    package
    {
        public class Manager extends SingletonMonitor
        {
            // define the singleton instance of Manager
            public static const instance:Manager = new Manager();
        }
    }

    As you can see no Singleton construction code is needed. Additionally, by extending SingletonMonitor you are clearly stating that the class is intended to be a Singleton.

    So how is this accomplished? It’s pretty simple…

    When a derived class is instantiated the SingletonMonitor constructor is invoked, the constructor parses the current stack trace in order to determine the derived class’ name (hence the hack). The name of the derived class is then used as a key in the SingletonMonitor hash table. When a subsequent instantiation of the class is made SingletonMonitor checks the name of the class and if it has previously been defined in the hash an exception is thrown. I originally developed this using introspection to determine the fully qualified name of the class, however the preferred implementation is to have the class eagerly instantiated at compiled time (i.e. constant), thus the stack trace is not available.

    Admittedly this is a bit of a hack, but so are the alternatives, otherwise this issue would never have been a topic of discussion in the first place.

    However what I like about this new approach is that the Singleton is being managed outside of it’s concrete implementation, and that is the goal of this post; to present an alternative means of managing Singleton construction. Through this the Singleton construction and management code can be omitted as it is being handled by a completely separate object.

    So the SingletonMonitor was the first example of how Singleton management can be achieved. The second example demonstrates the Singleton management approach implemented via composition as opposed to inheritance - which is my preferred mechanism of Singleton Management. In addition to creating the SingletonMonitor which utilizes inheritance I also created a SingletonManager which utilizes composition. The SingletonManager is the implementation I recommend and prefer.

    An example demonstrating how to use the SingletonManager can be seen in the following:

    package
    {
        public class Manager
        {
            // define the singleton instance of Manager
            public static const instance:Manager = new Manager();

            // the constructor simply invokes SingletonManager
            // validateInstance and passes a reference of the
            // instance, that’s it.
            public function Manager()
            {
                 SingletonManager.validateInstance( this );
            }
        }
    }

    The SingletonManager requires the class constructor to invoke SingletonManager.validateInstance and pass in a reference of the instance. This is automated in the SingletonMonitor as the class name is determined automatically which is convenient, however the readability of the SingletonManager is preferred as it clearly states intent. Additionally the SingletonManager guarantees the correct type is resolved.

    So this is a new way of thinking about Singletons; to provide a management system from which Singleton construction and protection can consistently provided.

    To be honest, this was really just an experiment I have been playing around with for some time now that I thought I should share, I am not sure if I would use the SingletonMonitor in production code as the parsing of the stack trace just feels a bit to much like a hack. However I will most likely utilize the SingeltonManager moving forward as it is a great way to abstract Singleton construction and protection from the class implementation.

    My hope is that there will be a true solution available as we move forward, but for the time being if you would like to create Singletons without the need for all of the Singleton implementation code feel free to extend SingletonMonitor for management or SingletonManager for compositional management.