Archive for the 'Software Engineering' 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.

    Package-level function closures in ActionScript

    Tuesday, May 6th, 2008

    Package-level function closures are very useful for creating generalized functionality which does not require a class (static methods) or instance of a class (instance methods).

    Unlike static and instance methods package-level function closures are not associated with a class or instance of a class but rather with a package. There are no syntactical differences between package-level functions and static or instance methods.

    Package-level functions are for the most part utility functions; for instance the flash.utils package contains a number of package-level functions, the most common of which are describeType(), getDefintionByName(), getTimer() and so forth.

    Package-level function closures are created by defining a function directly inside the body of a package (where class and interfaces are defined), as can be seen in the following example:

    package com.ericfeminella.display
    {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.IBitmapDrawable;
    import mx.graphics.ImageSnapshot;

    /**
     *
     * Creates a snap shot of a <code>Bitmap</code> object
     * from the specified <code>IBitmapDrawable</code>
     * implementation.
     *
     * @param  display object in which to create the snapshot
     * @return <code>Bitmap</code> snapshot of the display object
     *
     */
        
    public function createSnapShot(target:IBitmapDrawable) : Bitmap
    {
        return new Bitmap(ImageSnapshot.captureBitmapData(target));
    }
    }

    Calling a package level function is straightforward, simply import the function just as you would a class or interface and then invoke the function directly…

    // import package function
    import com.ericfeminella.display.createSnapShot;

    // once imported the function can be invoked
    createSnapShot( this );

    Typically you will find that most functionality can be grouped to a Class or an instance object, however on occasion you may identify specific functionality which is common to packaged functionality as opposed to a specific object, and in these cases utilizing package-level functions is a great option.

    Web-Based UML Sequence Diagram Generator

    Monday, April 14th, 2008

    If you need to create sequence diagrams quickly and do not have the time to use the more traditional Software Modeling tools; Together, Enterprise Architect, Visio etc. you should take a look at www.websequencediagrams.com.

    This handy little tool is pretty capable for a free web based utility and is very easy to use. It took me just seconds to create the simple sequence diagram below…

    Web-Based UML Sequence Diagram Generator

    So the next time you need to create UML sequence diagrams in a hurry make sure to check out this very useful tool.

    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.