Tuesday, January 1, 2013

Singleton - the good, the bad & the ugly

Well, lets just jump in, for the ones don't know what a Singleton is here is a short desc:

The Goal

  • Make sure a certain class has only one instance, and provide a global point of access to it.
  • Implement “just-in-time initialization” or “initialization on first use”, meaning DO NOT initialize the class before we specifically asked for, and do so only on the 1st time. 
  • Encapsulate it for god sake! 

The Implementation

    Shell we start with the ugly

    Why is this ugly? well first because it being use as the typical interview question everybody likes to ask & everybody knows how to answer, second these code snippet is only good from Java 5+ which means all your legacy code won't be able to use it due to a stupid JVM bug allowing the instance reference to be returned before the Singleton constructor is executed.
    Last - those are way to many lines of code using synchronization, locking, volatile (will need a new post only to explain that one...) when all we wanted is a simple implementation...
     
    public class Singleton {
      private static volatile Singleton instance = null;
     
      private Singleton() {       }
     
      public static Singleton getInstance() {
        if (instance == null) {
          synchronized (Singleton.class){
            if (instance == null) {
              instance = new Singleton();
            }
          }
        }
        return instance;
      }
    }

    Let's move on with the bad, well, compare to the other ones :-)
    So this one goes straight forwards, but this time uses a static block which is too many lines of code to do such a simple task, also it may seduce us to write some additional code in it.

    A Lazy initialization implementation
    public class Singleton {
      private static final Singleton instance;
     
      static {
        try {
          instance = new Singleton();
        } catch (IOException e) {
          throw new RuntimeException("An error occurred!", e);
        }
      }
     
      public static Singleton getInstance() {
        return instance;
      }
     
      private Singleton() {
        // Do something here...
      }
    }
    
    
    An eager initialization implementation (rarely being used as we prefer to be lazy & save memory & CPU)
    public class Singleton {
      private static final Singleton instance = new Singleton();
     
      private Singleton() {}
     
      public static Singleton getInstance() {
        return instance;
      }
    }
    
    
    So we came to the good, or maybe the nice & clean, so simple that when you look at it at the first time, it takes couple of minute to even understand what is going on there, so take couple of minutes before you read the explanation below & try to figure it out by yourselves.
    
    
    public class Singleton {
      private Singleton() { }
       
      private static class SingletonHolder { 
        public static final Singleton INSTANCE = new Singleton();
      }
     
      public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
      }
    }
    • The nested class is referenced only once & no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is Called.
    • Thus, this solution is thread safe without requiring special language constructs (violate or synchronized) and has lazy initialization.
    • Work on any Java version
    No go & fix your code :-)

    Saturday, December 29, 2012

    Continues Integration

    What?
    OK, so first let's understand what the hell is Continuous Integration (CI), it is the way of making different modules work together, so is this case, what are the modules? Or in other words, what is Modular Programming? "it is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality." Wiki.

    How?
    There are several principles of CI
    1.      Plan a stable environment
    2.      Maintaining a code repository
    3.      Automated the build
    4.      Make the build self testing
    5.      Commit frequently, build after each commit & use nightly build
    6.      Store your builds
    7.      Optimize builds execution

    Plane a stable environment
    First, decide how many environments you need to have, and what they are used for.  Integration takes place every time code migrates from one environment to the next. But don't go too far with it, don't build too many environments which you will never use, your rule of thumb is using as few as you can get away with, but enough to properly support the business.
    The minimum you'll probably build is the following:
    ·         Developing - Which is the environment in your PC, there will be light integrated here
    ·         Testing - For QA, functional & performance testing, here we'll have massive integration
    ·         UAT - Your client tests & confirms that the system mutually agreed-upon requirements. 
    ·         Staging - A mirror of the production environment
    ·         Production - The real world with real end users

    We need to automate these integration points.


    Maintaining a code repository
    You can call it "Revision Control", "Version Control" or "Source Control", the most important this about it is to actually have it! You will be surprised to meet teams (usually small ones in startups) not using it. Why should we use a code repository well that is very simple to explain, while your team is writing code on a daily basis, you do want to have the ability to:
    ·         Atomic commits your code, notice CVS doesn't support it.
    ·         To have File Locking, so that only 1 developer can 'check out' a given file, others can read that file until that developer 'check in' that updated file.
    ·         To have the capability of Merging Versions, this is done usually by a simple text merging tool, like Beyond Compare.
    ·         Be able to tag/label your build so you can identify a given artifactory snapshot


    Automate the build
    This is an automated process that compiles the binary files, generates documentation, website pages, statistics and distribution media. All should be done within a single command using tools like Maven, Ant, make.
    ·         Compiling computer source code into binary code
    ·         Packaging the binary code
    ·         Deploy the artifactory to the following environment
    ·         Creating documentation and/or release notes


    Make the build self testing
    After the build process terminate the unit testing stage should begin, running hundreds or even thousands of unit tests to isolate each part of the program and show that the individual parts are correct.

    Commit frequently after each commit & use nightly build
    If you don't do so, so change your habits! Your team should commit small, functional changes, understanding that the team owns the code, not the individual is crucial.
    ·         If your code, on your environment builds successfully, but not on another's, it is impossible to know if it's a source of environmental issue.
    ·         It doesn't mater if your code builds successfully in your environment, what's most important is that your code should build successfully on the build server.

    Why commit frequently? It is straight forward, by doing that you reduce the number of conflicting changes, imagine you commit only once a week, you'll have so many conflicts when merging back to the baseline repository that sometime you might spend the same amount of time you develop to merge! Besides, when team members commit frequently it make them communicate with each other, a simple gesture we often forget to do.
    A nightly build is an automated process takes place when no one change the code, the results of the build are inspected by the arriving programmers, who generally place a priority on ensuring the recent changes to the source code have not broken the build process or functionality of the software.


    Store your builds
    A good lifeline when your current build failed, also a good place to start searching when someone is asking a specific version 2 months ago. You can just pull it out & use it, just remember that usually your environment keep changing over time, and if you didn't put any effort supporting those old version, you might spend some time on configuration issues.


    Optimize builds execution
    Using tools like JFrog's Artifactory to manage, host and control the flow of binary artifacts from development to production.