Friday, February 12, 2010
I don't see my words in your design
Usually we go and meet these users to grab the requirement of the system/application they are looking for and then try to draw a mapping between the requirement and the software logical constructs such as classes, objects, services, components etc. During the process some new terms pop up based on the abstraction of the designer which might not surface the exact word specified in the requirement. Designers try to map the features/requirement of the application with the logical software constructs which is sometimes beyond the understanding of some of the stakeholders.
Based on the technical knowledge on software design of the stakeholder it becomes harder or easier to bridge the gap and make them happy. I am sure all the designers have experienced these kinds of sessions where the audience is shouting at you syaing "I don't see my words in your design, make me understand how are you arriving at this model of yours..". It will be followed by a long discussion of why I did it.
For example, a person who drives a car might not be very familier with the internal structure or mechanism of a chasis or gear box, but you have to make him/her understand how is it related to the process of driving else S/he will not buy the car... I just had this kind of session today :)
Wednesday, June 4, 2008
Code Generator Part VII: Controller Layer
The Control Layer
It’s layer from where the Code Generator gets executed by the user. It has mainly two classes Generator and GeneratorUtility as shown in Fig 1.
This shows that the Generator class instantiates the Importer and Exporter type of classes. In case of Java source code generation, the Generator instantiates the XMLOOImporter (Fig 6) which implements the Importer interface for importing the XML input model. Once the XML model is imported and stored in the memory in the form of IOM model, the Generator instantiates the JavaExporter (Fig 7) which implements the Exporter interface for generating the Java source files as per the IOM model (Fig 3).
Generator is the common entry point for both code generation and template generation processes. This class has mainly two methods called “generate” and “main”.
The “generate” method takes 4 parameters as input – input model type (i.e. XML), output source code language (i.e. Java), name of the input model file (i.e. XML model file name) and the output destination directory. To generate the source codes, this class invokes the importer and the exporter simultaneously to read the class specifications from the XML input model file and to generate Java source code according to the class specifications.
Since this class also has a “main” method, it can be invoked from the command-line by using the 4 parameters described above. The Generator class is shown in figure 1.
GeneratorUtility is a common utility class that gets used by most of the classes involved in the code generator system. It contains some static values and utility methods used for intermediate processing or formatting. The GeneratorUtility class is shown in figure 1.
Below is a high-level sequence diagram of the Code Generator.
Actor invokes the Code Generator by calling the generate() method of the main class “Generator”. The actor specifies the input type (i.e. XML), output type (i.e. Java), input model file (XML file) name and the output destination (directory or path) while calling this method (Fig 2).
In case of Java source code generation, the generate() method instantiates XMLOOImporter class (which implements Importer) and invokes its start() method to read the class specifications from the XML model file provided as input (Fig 2). Once the classes are identified from the input model (XML), Generator instantiates the JavaExporter class (which implements Exporter interface) to generate java source files from those classes as specified in the XML model (Fig 2). At the end of generating the source files the Code Generator system will display a list of source files that have been generated and a message with the number of source files. Incase an invalid (not an XML) input document is provided to the system it will throw an exception and display the stack-trace for the exception.
Figure 3 shows detailed sequence diagram of the code generation process.
Figure 4 shows the relationship between different components defined in XML and realized in IOM for the source code generation process. Blue boxes marked with "XML Tag" in the diagram represents the tags used in the input XML model and other boxes are representing the IOM classes already shown in Part IV of this series. The attributes shown in the XML-tags (blue boxes) are the XML-attributes. The names of the XML-attributes are quite identical to those of the corresponding IOM class e.g. the attributes – name, stereotype, visibility, documentation, isStatic, isFinal, isAbstract etc. of IOMClass are having identical names with the respective XML-attributes (i.e. name, stereotype, visibility, documentation, static, final, abstract) in the Class tag. The attributes that are not in the XML-tags but present in corresponding IOM class are used for internal processing of Code Generator.
Since XML does not allow data types other than character strings, the data type of XML-attributes is given as string. After the XML input model file is parsed, individual XML tags are parsed and translated to the respective IOM objects and stored as the internal object model in the memory. During the translation of input XML the string data types are also converted to appropriate Java data types e.g. value of isStatic is given as “yes/no” in the XML, it’s converted to Java boolean (true/false) type. While generating the output the exporter reads the internal object model from the memory and generates appropriate documents accordingly.
Wednesday, May 21, 2008
Code Generator Part VI: Exporter Layer
The Exporter Layer
The exporter has the responsibility of translating the IOM created by the importer and generating the desired output document (i.e. Source Codes or Documents in a specific format).
Incase of code generation the exporter translates the IOM created by the importer and generates the desired output source codes from the IOM. The code generator can have different exporters depending on different output types (i.e. output languages like Java, C++ etc.). Currently we are generating the Java source codes by the exporter. The exporter has been designed using a generic interface (Exporter) as the parent. Any class that generates source codes in a specific object-oriented language from the IOM should have the Exporter interface as its parent. In our case we have an exporter class (JavaExporter) that exports Java source codes according to the object-oriented class specification as defined in the input XML model. This class, called JavaExporter implements another interface called OOCodeExporter which already implements the Exporter interface (Fig 7). The reason behind introducing the OOSpecExporter interface is to encapsulate the activities involved in generating source code in all object-oriented languages in a single interface. This way the Exporter interface can be further implemented by other exporters for generating source codes in different object-oriented languages other than Java (e.g. C++, C# etc.). Below are the descriptions for the classes that belong to the exporter layer.
Please refer to Fig 1 for the classes involved in the Exporter layer.
Fig 1
Exporter is designed as a generic interface. The interface contains the start(), initialize() and finalize() methods. The main entry point of the code generator i.e. the Generator class invokes the exporter using the start() method of this interface. To use the code generator for generating source code in a specific object-oriented language (e.g. Java, C++, C# etc.), new exporter classes can be introduced implementing the same Exporter interface.
OOCodeExporter is an interface implementing the Exporter interface. The purpose of this interface is to encapsulate the operations required to generate source codes in object-oriented languages. Currently the JavaExporter implements this interface to generate Java source codes according to class specifications defined in the input XML model. In future new exporters can be introduced as children to this interface for generating source codes in different OO languages other than Java, e.g. C++, C#, VB etc. The implementation of the Exporter interface depends on the type of OO languages (Java in our case) in which the source code will be generated, so different languages can have very different implementations.
JavaExporter implements the OOCodeExporter interface. The architecture of this class is closely bound to the SAX parser philosophy. This class works on the IOM objects (i.e. IOMClass, IOMAttribute, IOMOperation etc.) stored in the IOMOOController by XMLOOImplorter. The start() method begins to navigate through each object in the internal object model (IOM) and calls the startClass() method each time a IOMClass object is processed, and in general the startXxx() method each time an instance of IOMXxx is processed. The exporter then invokes the endXxx() methods when an instance of IOMXxx is finished to be processed. It creates an output file using the name of the class and adding the JAVA extension. Then it writes, by using the information coming from the IOMClass object, Java code for declaring a class. By implementing all the methods, the JavaExporter class generates the Java classes corresponding to XML model in terms of attributes, operations, and associations. The JavaExporter works based on certain assumptions as described below.
The generated Java source files involved in the DTOs will by default
- Do not need to implement a base class.
- Implement the "Serializable" interface.
- Import "java.util.*" and “java.io.Serializable”.
- Have the stereotype as "class".
- Have visibility "private" for attributes.
- Uses public getter/setter operations.
- Has non-final and non-static attributes or operations.
- Use attributes with type "String".
- Use attributes with multiplicity as "1".
Tuesday, April 15, 2008
Code Generator Part V: Importer Layer
The Importer Layer
The importer has the responsibility of reading the model as input and creating the IOM. The code generator can have different importers for different input data sources (XML, CSV, Database schema etc.).In accordance with MDA paradigm, the importer for code generation process reads an input model — representing UML and created by UML tools, such as Rational Rose. Currently we are creating the XML model manually. Presently the importer has been designed using a generic interface (Importer) as the parent. Any class that imports a model should have the Importer interface as its parent. In our case we have an importer class (XMLOOImporter) that imports XML model containing the specification for the classes whose source files has to be generated. The class named XMLOOImporter implements another interface called OOSpecImporter which already implements the Importer interface (Fig 6). The reason behind introducing the OOSpecImporter interface is to encapsulate the activities involved in importing an object-oriented model in a single interface.This way the Importer interface can be further implemented by other importers for importing models defined in different formats other than XML (e.g. XMI, CSV, XML schema, Database schema etc.). Below are the descriptions for the classes that belong to the importer layer. Please refer to Fig 6 for the classes involved in the Importer layer.
An Importer (as shown in fig 6) is designed as a generic interface. The interface contains the start() method that starts the importing process. The main entry point of the code generator i.e. the Generator class invokes the importer using the start() method of this interface. To use the code generator for generating source codes in a specific object-oriented language (e.g. Java, C++, C# etc.) new importer classes can be introduced as the children to the same Importer interface. New importer classes can be written for different formats (e.g. XML, Database schema, DTD, XML schema, XMI etc.) of the input model to the code generator as well.
XMLOOImporter class is inherited from the OOSpecImporter interface and org.sax.helpers.DefaultHandler class (to handle SAX parser events). This class works on a XML representation of UML. The XML structure is straightforward—it recalls UML concepts such as classes, attributes, operations, parameters, associations, and roles. The XMLOOImporter class uses a SAX parser. For each relevant element found in the XML as input, it calls the proper method of the OOSpecImporter interface. For example the element
Thursday, March 20, 2008
Code Generator Part IV: IOM
The IOM Layer
For the object-oriented code generation process the IOM has been designed borrowing UML concepts. Basically, the internal model can be a representation of the object-oriented concepts following the structure of UML model and notation. Therefore, a set of classes and associations has been designed representing UML classes, attributes, operations, parameters, and associations. Basically in this case the UML features and rules have been designed by using UML itself. As a convention, IOM classes start with the IOM prefix. Fig 3 shows a class diagram of the IOM classes. The IOMClass class models a UML class. It has an aggregation with the IOMAttribute and IOMOperation classes because classes have attributes and operations. Since operations have parameters, an aggregation is modeled between the IOMOperation and the IOMParameter classes. The IOMAssociation class represents a UML association. It has two roles (start and end) that are modeled by the IOMRole class. Then, that last class has an association with the IOMClass class (involved), which represents the start or the end class of the UML association. IOMOOController class acts a controller and stores the entire IOM (collection of all classes and associations included in the IOM) as a static aggregation. IOMOperationBody is an interface that represents the body of any operation to be defined at a later time. Any class that represents the body of an operation will have to implement the IOMOperationBody interface. For instance, ToXMLStringBody class contains the implementation of the “transform” method (a method to print out the values of all the attributes of a DTO) for all the generated DTOs. The descriptions of the classes involved in the IOM layer are given below. Fig 3 shows the classes involved in the IOM layer for the source code generation process.
IOMClass class represents a class in object-oriented scenario according to UML. It has ten attributes: name (the name of the class), stereotype (the UML associated stereotype), documentation (documentation for the class), packageName (the package in which the class belongs to), visibility (the visibility of the class, the values of this attribute can be private, public, protected.), isFinal (indicates whether the class is a final one), isAbstract (indicates whether the class is an abstract class), baseClasses (list of base classes of this class), baseInterfaces (list of base interfaces of this class) and imports (list of links to other libraries or APIs, e.g. “import” clause in Java). The aggregations with the IOMAttribute and IOMOperation classes are implemented by two ArrayList (attributes and operations) and related get/set/add methods. The class also contains the getAssociations() method that returns all the IOMAssociations in which the class is involved as a start or end role.
IOMAttribute class represents an attribute/member of a class in object-oriented scenario. It has twelve attributes: name (the name of the attribute), type (the type of the attribute, currently the code generator supports boolean, char, byte, integer, float, double, long, string, date, short or any custom type like “MyClass”), multiplicity (multiplicity of the attribute, if it’s a collection or array), documentation (documentation for the attribute), visibility (the visibility of the attribute/member, permitted values are private, public, protected.), defaultValue (the default value with which this attribute will be initialized, if not specified, the attribute will be initialized by it’s default value according to Java standards e.g. string type will initialized by “new String()”), isStatic (indicates whether the attribute is a static one), isFinal (indicates whether the attribute is a final one), isTransient (indicates whether the attribute is a transient, i.e. uses the transient keyword of Java), classParent (this is a reference to the IOMClass instance to which the attribute belongs), elementTag (XML tag in which the value of this attribute will be encapsulated during XML transformation) and groupTag (If the member is a collection of values i.e. multiplicity is more than one, the value of groupTag will be used as an XML tag encapsulating the group of values during XML transformation).
IOMOperation class represents an operation / method of a class in object-oriented scenario. It has sixteen attributes: name (the name of the operation), returnType (the return type of the operation, currently the supported types by the code generator are boolean, char, byte, integer, float, double, long, string, date, short or any custom type like “MyClass”), documentation (documentation for the operation), visibility (the visibility of the operation / method, the permitted values are private, public, protected.), isStatic (indicates whether the operation is a static one), isFinal (indicates whether the operation is a final one), isAbstract (indicates whether the operation is an abstract one), isConstructor (indicates whether the operation is a constructor. The constructor name will always be same as the class name for Java code generation), isDestructor (indicates whether the operation is a destructor. Currently this attribute is not used it’s kept for future uses for generation in other languages like C++.), exceptions (list of exceptions that this operation might throw while executed), isSynchronized (indicates whether the operation is synchronized), isNative (indicates whether the operation is native), classParent (this is a reference to the IOMClass instance to which the operation belongs), directive (this indicates any other options that might be required in future, not used currently), bodyClassName (the name of the class that returns the body content of this operation) and body (the body content of the operation as returned by the class whose name is mentioned in bodyClassName. The class with the given name will be loaded at the runtime by the code generator and invoked using reflection to get the body content of the operation), body (the body content of the operation that has been returned by the class mentioned in the bodyClassName) and classParent (the parent class to which the operation belongs). The usage of bodyClassName attribute makes the code generator independent of the business logic of an operation. This way the logic of an operation is externalized from the code generator.
IOMParameter class represents a parameter of an operation in object-oriented scenario. It has three attributes: name (the name of the parameter), type (the type of the parameter, currently the supported types by the code generator are boolean, char, byte, integer, float, double, long, string, date, short or any custom type like “MyClass”) and operationParent (the operation name that takes this parameter as the input).
IOMAssociation class represents an association with another Class in object-oriented scenario. It has two roles (start and end) that are modeled by the IOMRole class i.e. two IOMRole instances indicating start and end of the association. It has one attribute: name, which is the name of the Association. This class contains the get/set methods for the above-mentioned attributes.To explain the way in which the associations will be implemented we can consider an example. In this example, four different cases of relations between two classes have been considered. Fig 4 shows those cases.
The root class of the model is IOMOOController, which is shown in Fig 3. It contains and provides the possibility of access to the instances of IOMClass and IOMAssociation involved in the model. This class is designed as a static class. Since the Code Generator System is not a part of any client-server system or product and it is to be used by a project team member/developer in stand-alone mode, this class has not been designed to run in a multi-threaded environment. In addition, the IOMOOController class implements the queryClass() method that may be useful to search a class by name. Importers and exporters start from that class respectively to create the IOM and to read metadata from it to write the output.
Thursday, February 14, 2008
Code Generator Part III: Code Generation using MDA
- Parsing the code that is supplied as the input. This is known as import.
- Collecting the theme or model of a language from the input, known as internal modeling.
- Generating the theme in a form of code that can be understood by the target, known as export. The target might be hardware or another software interpreter.
Based on the functionality the architecture of a typical Code Generator can be perceived as below. A code generator can be imagined of being consisted of three different modules / layers as shown in (Fig 2):
Fig2
Importer – This module reads the model as input and translates it into a platform-independent internal format based on an object model. An importer could be seen as a sort of XML parser. But, by generalizing the design of an Importer any kind of input can be read.
Internal Object Model (IOM) – This is the platform-independent internal format of the input model and could be considered as the core of the code-generator architecture. IOM contains a set of classes that make it easy to manipulate the information coming from the model to generate outputs. The structure of the IOM is a very important issue— if designed carefully it can be a powerful target-technology (Java, C++, etc.), independent representation that can be converted easily in source code.
Exporter – This module accesses the IOM and takes the relevant information to generate code. It could use templates, which drives the generation process and makes the exporter more generic and independent of the output language syntax. For the current version code generator, the exporter has been designed without using the Template-Based approach.
The architecture described above has following benefits for code generation:
- The input is completely independent of the output in terms of technologies. For instance, an importer can be created that reads a UML diagram and then an exporter writing C#-ADO code and another one writing Java-JDBC code, but both work with the same UML model as input.
- If the IOM is implemented following the UML, everything that can be represented with UML can be done with IOM as well, which means that every kind of input can be represented and converted into a real object-oriented design. It is a big advantage in writing importers and exporters manipulating the model. The IOM layer adds flexibility to the code generator and introduces loose coupling between the importer and the exporter.
- By implementing multiple exporters and applying a simple pattern, different layers of code can be created—source code, descriptors, documentation, scripts, and so on—with a single pass that assures consistency and synchronization among the different outputs.
Tuesday, February 12, 2008
Code Generator Part II: Architecture of a typical Code Generator
Depending on the type of input, code generators can be classified in two types – code driven and model driven. A code-driven generator takes as input a file containing source code and special tags, which drive the code generation process e.g. JavaDoc. Model-driven generators can also be sub-classified into two types – custom and MDA. A custom generator takes as input a proprietary model representing the information that must be converted in source code e.g. Apache Velocity. When the model as input is a representation of UML, then the code generator follows the Model-Driven Architecture (MDA). An MDA code generator takes a platform-independent model (usually XMI, an XML representation of UML) as input and turns it into a platform-specific model, which can be converted easily in source code by means of templates.
In this article and the following articles I will try to explain a code generator that converts a set of object definitions (expressed in an object-oriented paradigm i.e. UML) of simple Data Transfer Objects (DTO) from a XML text to a Java program. The same code generator can be enhanced to generate C++ programs, SQL scripts, PHP scripts from the same XML input. In the real world scenario, a programmer might not possess the skills in all the languages but he/she can be well conversant with the concepts of the object-oriented (OO) paradigm and is able to design an OO system. The concepts or design of a system can be stored in a widely popular common format e.g. XML. The utility of this tool is to facilitate the transformation of the concepts and design from the XML to a desired language. Most of Computer-aided Software Engineering (CASE) tools like Rational Rose etc. support this sort of code generation.
Thursday, February 7, 2008
Code Generator Part I: Compiler, Interpreter and Code Generator
In the internet age, the most popular way of expressions and communications are being done using the markup languages like HTML, XML, WML, SGML, SVG etc. The reason behind the popularity of these languages is that they are English text based and easily explicable to the common people and other software systems. The languages are very helpful in communicating in the global community of heterogeneous software systems.
Think of a scenario where my program which is built using a latest technology (e.g. C++/Java, J2EE .Net etc.) is trying to talk with another program which is built using COBOL running on the other part of the world, we need a language or protocol of communication that can be understood by both of them. This is where the markup languages could help a lot. My program can interpret its data to a XML text and send it to the other program while it can translate the data back from XML to a format that it can understand. The other program can reply to my program in a similar fashion.
I will try to explain the Architecture of a typical Code Generator in the following posts.