Feeds:
Posts
Comments

Posts Tagged ‘Bluprint’

In this entry I wanted to share my thoughts on how Agile MDA can be used for the 99% of projects that don’t have the luxury of being new Greenfield Blue Sky developments.

The Reality of the Real World

I am sure we have all experienced joining a new company or transferring to a new team and being assigned to a project that has an existing code base.  Usually the code base, often your company’s flagship product, has been careful crafted, lovingly maintained and nurtured over a number of years.

Being a top-down kind of person, one of the first questions I ask is ‘can you show me the architecture’? This is met with varying reactions ranging from embarrassed laughter to frenzied scribbling on a whiteboard.  It is very unlikely, in fact I have never encountered, that a set of up to date UML diagrams representing the current state of the application will be produced.  In more mature organizations, if we are lucky, we may be pointed at a file directory containing the detailed design documentation for the various components that have been implemented over the years.  Naturally these are never maintained, as there isn’t time.

So as a new team member you are usually left to familiarize yourself with the code under the careful guidance of a developer who is experienced with the code base of the application.  As familiarity builds you may fix a few simple bugs and after a few weeks or months enough confidence may be established to implement some functional enhancement or even new components.  Most of these changes are made directly to the code without a formal design and review process being followed.

The above is an illustration of the reality for the majority of us.  We are rarely in the position to be starting from scratch.  So how can we start picking ourselves up by the bootstraps to improve our productivity?  In this type of environment it appears to be next to impossible to introduce improved productivity techniques such as Agile MDA.

Architecture Modernization, Software Archaeology and Surveying

Many people assume that MDA is only suitable for brand new implementations where code is generated fresh from a model. If your recall a tool like Bluprint allows existing code to be merged with the engineering model describing the software.  In order to perform code merging, Bluprint internally constructs a model representing the existing code.  The model of the existing code is then merged from with the engineering model.  It is from the merged model that the new code is then generated.

Now imagine the situation where we do not have an engineering model, e.g. an existing code base without a description of its design – much like the scenario we described earlier.  You can see that Bluprint would still work in this case as Bluprint would create a model of the existing code that when merged with an empty or nil engineering model would remain the same.  If we could preserve the resulting model, we would have uncovered the original blueprint for the code.

This is incredibly useful because now we have bootstrapped ourselves by creating a description of the application code in the form a model.  We can then proceed to maintain the application by making changes to our newly recovered model.  At this point it would be as if we had been using Agile MDA all along.

The process of model recovery is sometimes called Software Archaeology, but often I like to think of it as more like software surveying as it is consistent with the metaphor of a model blueprint.  The Object Management Group (OMG) has a task force looking specifically at evolving software assets using model driven approaches.  It operates under the rather grand title of Architecture-Driven Modernization (ADM).

Some pragmatics

Part of the value of adopting MDA is to have a diagrammatic representation of the application.  When recovering a model from its code, there is no diagrammatic representation for it.  As a consequence any recovery tool will need to automatically generate this.  This presents a few challenged, as what is the best approach generating the model diagram?  Many software products, especially UML modelling tools, incorporate function to automatically layout a model diagram.  However no matter how sophisticated they are, they can never perform this in a satisfactory manner. It will always require manual tweaking afterwards.  From practical experience, it is better for the tool to create an initial layout of the model in diagrammatic form, but to realise that this will then be subsequently rearranged.

If we were creating a UML model from a code base, such as Java, we would create a class diagram for each package.  On each class diagram the classes that inherit from each other would be arranged in balanced class hierarchy trees.  Classes from other packages would also be included on the diagram if there are direct associations from the classes within the package represented by the diagram.  Theses external classes would be placed at the periphery of the diagram.

The layout of associations is a complex problem to solve and this is where most tools flounder.  If is difficult to design an algorithm that ensures the lines representing associations avoid crossing over or under other classes and that also minimise the number of times these lines cross.  In practice it is better to include all associations as straight lines, creating a tangled web of lines and to assume that an engineer will manually rearrange these in their modelling tool.  This usually only takes a few minutes to perform.  Once an engineer has rearranged a diagram its layout can be saved and preserved.  By rearranging the diagram, engineers also start to familiarize themselves with the structure of the application.

Enabling Bluprint for ADM

Currently Bluprint contains most of the components needed for deployment within existing software implementations.  As described previously it currently constructs internally a model of the existing code when it is creating code from a model.  However it does not contain the components for generating the diagrammatic representation of the constructed model or for a means of persisting it.  These changes are currently in the works and I will keep you abreast of developments.

Read Full Post »

Bluprint Icon

Bluprint


I just wanted to update you on some of the exciting things that have been happening since my last post. Previously I mentioned that I am incubating an open source software project. That project is called Bluprint. Bluprint is an MDA tool designed to support Agile MDA. Key-points are:

  1. It is built using itself – although to the end user this isn’t too relevant, it does mean it has been put through its paces and can accommodate non-trivial software projects. The current Bluprint software model and code contains over a hundred classes.
  2. It makes very few uses of UML stereotypes. I was aiming to use none, but I had to concede and adopted one, called <<nogen>>. This is used to prevent the generation of code from some parts of the model and is useful when you are modelling third-party APIs.
  3. It supports full lifecycle software development, you can generate code from models, amend the generated code, amend the model and re-generate. All user modifications to the code are preserved because the tool supports intelligent model/code merging. There is no need to use sub-classing for user written extensions or annotations to mark and protect sections of the code.
  4. Bluprint interprets UML models to create Java code currently (but other target languages will be possible in the future). It supports:
    • Classes
    • Interfaces
    • Enumerations
    • Inheritance, both extends and implements
    • Associations
    • Generation of member variables and corresponding accessors.
      • unary members
      • non-unary members, from associations with cardinality greater than one
      • qualified associations
    • Generation of constructors
    • Generation of stub-methods, including throws clauses

Family Tree Example

Let me show you Bluprint in action, to give you a taste of some of Bluprint’s capabilities. It will demonstrate some of Bluprint’s code generation and model/code merging features showing Agile MDA in action.

Imagine we are going to create a program for the creation and management of family trees. In the following example we’ll be able to create people and define their descendants.

  • The Initial Model
    We start by modelling a simple class for representing people in our family tree called Person, which initially looks like this.
    Person class step 1

    Person class step 1


    Bluprint has been developed, initially and tested, with MagicDraw 16.0. The model is created in MagciDraw and exported as an EMF UML 2 (v1.x) XMI file for use by Bluprint. Bluprint is designed to work with any tool that can export UML models in this format.

    After running Bluprint for the first time, the following code is generated. Notice the generation of member variables, accessors and stub methods for main(), print() and the constructor.

    package org.family;
    
    /**
     * Class Person has been generated from a UML model by @author Bluprint.
     * Date: Tue Mar 24 15:18:23 GMT 2009
     */
     
    import java.util.Date;
    import java.lang.String;
    
    
    public class Person {
    
    	private String name;	
    
    	private Date dob;	
    
    
    	public Person(String name) {	
    		// TODO - Auto-generated
    	}
    
    	public static void main(String[] args) {
    		// TODO - Auto-generated
    	}
    
    	public void print() {
    		// TODO - Auto-generated
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String value) {
    		this.name = value;
    	}
    
    	public Date getDob() {
    		return dob;
    	}
    
    	public void setDob(Date value) {
    		this.dob = value;
    	}
    }


  • Edit the Code
    We fill in the details of the stub methods, as follows. For the constructor we just set the name of the Person.

    	public Person(String name) {	
    		this.setName( name );
    	}


    For now the print() method is very simple

    	public void print() {
    		System.out.println( getName() );
    	}


    And in main() we create a single Person object and ask it to print itself

    	public static void main(String[] args) {
    		Person fred = new Person( "Fred" );
    		
    		fred.print();
    	}


    At the moment the model and the code only support the definition of a single stand-alone person. Executing the program we get the following output.

    Fred

  • Amend the Model and Code Merge
    Now we have the basics working, we want to be able to define the descendants of a Person. We amend the model to add a one to many associations from Person to Person. One end represents the parent and the other the descendants. We could have made it many to many, but I wanted to show that Bluprint can handle associations of different cardinalities.
    Person class step 2

    Person class step 2


    We also add a new private method for printing. Note, we don’t need to add this to the model, we could have added it straight to the code, but it is easy to do it here while we are thinking about it.

    We export the model again and run Bluprint against the new model and our original code. Bluprint interprets both and generates the following result for the Person class.

    package org.family;
    
    /**
     * Class Person has been generated from a UML model by @author Bluprint.
     * Date: Tue Mar 24 15:44:16 GMT 2009
     */
     
    import org.family.Person;
    import java.util.Date;
    import java.lang.String;
    import java.util.Vector;
    
    
    public class Person {
    
    	private String name;	
    
    	private Date dob;	
    
    	private Person parent;	
    
    
    	private Vector descendants = new Vector();
    	
    
    	public Person(String name) {	
    		this.setName( name );
    	}
    
    	public static void main(String[] args) {
    		Person fred = new Person( "Fred" );
    		
    		fred.print();
    	}
    
    	public void print() {
    		System.out.println( getName() );
    	}
    
    	private void print(Person person, int depth) {
    		// TODO - Auto-generated
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String value) {
    		this.name = value;
    	}
    
    	public Date getDob() {
    		return dob;
    	}
    
    	public void setDob(Date value) {
    		this.dob = value;
    	}
    
    	public Person getParent() {
    		return parent;
    	}
    
    	public void setParent(Person value) {
    		this.parent = value;
    	}
    
    	public void addDescendant(Person aDescendant) {
    		this.descendants.add( aDescendant );
    	}
    
    	public void removeDescendant(Person aDescendant) {
    		this.descendants.remove( aDescendant );
    	}
    
    	public Person getDescendantAt(int index) {
    		return this.descendants.get( index );
    	}
    
    	public int getDescendantsSize() {
    		return this.descendants.size();
    	}
    }


    Notice the original code changes have been preserved. Bluprint has helpfully added member variables for the parent and the descendants. Some helper methods have been created to allow descendants to be added and removed. In addition members of the descendants collection can also be accessed.

    (The sharp eyed amongst you will notice the Bluprint understands plural names for collections and has created singular forms when adding and removing individual members. So although the Person has many descendants, you add, remove and get individual descendants.)

    A stub method has also been created for the private print() method, which will be used for indenting the name of a person based upon their depth in a descendant tree.

  • Edit the code again
    We add a printIndented() function

    	private void printIndented( String string, int tabs ) {
    		for( int i = 0; i < tabs; i++ ) {
    			System.out.print(  "\t" );
    		}
    		System.out.println( string );
    	}


    We don’t need to add every method to the model since Bluprint is designed to be pragmatic. You can decide what to include in your model and what to leave out as detailed implementation. Bluprint provides reporting so you can identify what has been coded and not included in the model.

    Next we amend our print() methods to look like this

    	public void print() {
    		print( this, 0 );
    	}
    
    	private void print(Person person, int depth) {
    		printIndented( person.getName(), depth );
    
    		for( int i = 0; i < person.getDescendantsSize(); i++ ) {
    			print( person.getDescendantAt( i ), depth + 1 );
    		}
    	}


    Finally we set up some test data in the our main() function

    	public static void main(String[] args) {
    		Person fred = new Person( "Fred" );
    		Person mary = new Person( "Mary ");
    		Person bill = new Person( "Bill" );
    		Person benn = new Person( "Benn" );
    		Person jill = new Person( "Jill" );
    		
    		fred.addDescendant( mary );
    		fred.addDescendant( bill );
    		mary.addDescendant( benn );
    		mary.addDescendant( jill );
    		
    		fred.print();
    	}


    When we run the program we get the following output

    Fred
    	Mary 
    		Benn
    		Jill
    	Bill


    Summary
    The above is a very simple example, but it does demonstrate some of the powerful features of Bluprint including code generation and intelligent model/code merging. Bluprint removes the burden of creating and maintaining a lot of boilerplate code. The engineer can focus on the value add parts of their task which is the coding of the business logic. The power of Bluprint comes into its own for much larger, real world, models containing many classes, interfaces, associations and inheritance.

    Read Full Post »