Reflective Architectures and Code Generation.

ã Moisés D. Díaz. www.moisesdaniel.com

1.- Let’s start with an example: AnotherAmazon.com .

2.- Source Code generation (or manual development).

3.- What a reflective architecture is.

4.- When do we have to develop a reflective architecture.

 

 

 

1.- Let’s start with an example: AnotherAmazon.com.

 

Imagine we have to build up a commercial site focused on web sales of products like books, films, DVDs, CDs, printers, mouses, cameras, mp3 players, TVs and all kind of electronic products.

 

Each type of object can be defined by its characteristics. So, we will have:

 

 

To manage all this information, we certainly need to keep it in data bases, in order to be able to manage it in a suitable way and to have all this software guaranties. So we will have a table for each type of object, where fields will coincide with its (particular and common) characteristics. So, the information related to each object will be kept in the table of the type of object it belongs (for instance, books will be kept in the “Books” table).

This is a simplification of reality but it is a good example to illustrate what we want to explain.

 

Our duty consists, basically, of managing the web publication of all this information  (forget the shopping trolley). Publishing this information consists of giving the user the permission, using a web navigator, to be able to:

 

 

 

There are two technical possibilities to achieve successfully this duty:

 

 

§          We can have an only web component which works in such a way that is able to show any object of any type by reading the properties of each type of object (these data are kept in the MetaInformation table). It is like having an only JSP/ASP to list (List.jsp?type=DVD), and another one to visualize entries (ShowElement.jsp?type=DVD&id=83838). The information that describes the structure of each type of object is called metainformation. Creating it can be expensive or not, but its maintenance has a very low cost.

 

 

 

 

 

 

 

2.- Code generation (or manual development).

 

Each type of object has a group of characteristics that are common to other types, in the same way, each of them has its own ones that are different to the own characteristics of the others. This implies that we will have some tables related to each type in the data base, and that the web components which lists and visualises each type must have a very similar structure, as their function is basically the same. But, at the same time, that structure or code must be a little bit different, due to the specific characteristics of each table (type of object), to which it acts as the latter web interface.

 

In fact, the code of each component related to a type is absolutely independent of the structure of the table to which it works as interface. So, once we have defined the table, we can automatically generate all or part of the code that is going to list it, visualize it, and so on. The other possibility is using the well known technique: “copy-paste-modify”. Both techniques are almost equally successful, but the last one is much more expensive and can produce more mistakes.

 

There are many tools to generate code, for instance, CodeCharge, Xcripter,  and many wizards from different development frames.

 

As  using the first mentioned technique we obtain the same results, but with a very low cost, we could think that this option is the solution to the problem described at the beginning of this article (“AnotherAmazon.com” building up). However, generating code has many points against (less than the copy-paste-modify technique), that is why it is not the most suitable technique for all projects.

 

For this reason we are going to focus on source code generation.

 

Code generation is frequently found when there are interfaces between different layers, components, and so on. Places where a little amount of information can be used to generate all the repetitive code required (e.g.: Wsdl à Soap, mapping OO à RDBMS, tables à forms)(in this case, from tables to Html lists and Html visualisation of their entries).

 

There are, basically, 3 code generation types [ACG]:

 

§          Templating. A draft of non-functional to be edited source code is generated. Doing this way we do not have to write down the most repetitive part of the code (usually, not very complex). It is usually a good solution. For instance: If we use Oracle JDeveloper to build a new Servlet, this software is going to automatically generate a “Servlet” class with the basic imports and the methods this class has.

§          Partial.  Source code that partially implements the required functionality is generated. The programmer will use it as a base to modify, integrate or adapt according to his needs. It is not recommended. For instance: we generate an application to maintain ddbb tables (as web applications build up using CodeCharge, or BC4J components created with JDeveloper). If we want to modify it, integrate it with other developments or just adapt it to other lightly different needs, we have to dive through a huge quantity of code that we do not understand but that we have to modify a lot.

§           Total. Functionally complete source code  is generated, but it is not going to be modified by the programmer. If it is necessary the code will be regenerated. Usually, it is not a very complex code. A very recommended option. For instance: a Stub generation for a WebService in JDeveloper.

 

We are going to focus on the partial generation (that means automatic generation + modifications and some developments in it). Usually, there are some problems with that, as:

 

§          The generated code is so complex that it is difficult to modify from the point of view of the implemented functionality.

§          Its regeneration is usually very expensive, as we have to modify it again to adapt it to the problem.

§          We have to maintain all the generated code, which implies the higher cost of a project.

§          It makes the code dependent on another extra development tool. This is very restrictive, as the maintenance becomes more complicated (most of the times, it is not the firm that developed it the firm that maintains it; some times other environments emerge  where those generation tools are not useful (for instance: at first, CodeCharge generated JSPs, now, it generates Servlets!!)). It is another strong dependence.

§          Functional code generation usually contains most of the functionality needed, but not all of it. And  modifying it is very complicated.

 

One of the main objectives of software engineering  is creating a reusable software, that means generating a very hard code, with few mistakes.

 

Then, why do not parametrise all this repetitive but different code unifying it (that means refactorising)? All depends on the dimension of the application, as this refactorisation is, usually, a result of reflective architectures. We do not have to forget that developing an architecture has a cost. There are only two positive aspects of partial code generation:

 

-          Usually, it has a better performance than the r.a.

-          Its developing is quicker (unless you have the r.a. implemented).

 

The generation of web components associated to types of object is categorised as partial code generation. We can generate code to list and visualise the entries of the tables, but this code is usually part of an application that has to be integrated in other specific developments, as security code, the using of specific technologies related to data base access (for instance, a connexions pool), navigation elements, style and visualisation patterns, the using of logs, personalisation mechanisms, printing services, and so on. When we have to face the building up of  big/medium applications, code generation is very problematic.

 

3.- What a reflective architecture is.

 

As it says in [POSA], reflective architectures have been used in many different systems and are specially recommended when flexible and adaptative applications are needed.

 

A reflective architecture is characterised by having a number of elements that contain structural information about part of the system, that means that it describe the system. The system uses this metainformation as a basic element that let it interact with those described elements (generally called base).

 

One of its main characteristics is that, usually, all base elements that are described share a number of characteristics, in such a way that they can be object of certain transformations (operations) uniformly. However, they have elements that make them different, so these operations depend on each base element.

 

Because of these differentiated characteristics we have to generate a specific code for each of these base elements. Nevertheless, there are some times when it is more profitable developing a reflective architecture as it treats all these elements uniformly.

 

 

Base Elements implement each Operation.

The programmer has to develop a lot of specific code for each Operation of each Base Element.

 

 

All this architecture can be also seen as a typical strategy of centralisation or as an application of the encapsulator-centraliser metapattern.

 

Now Operations are encapsulated and centralized in one Class, that uses the metainformation contained in the Descriptor, in order to customise  each operation of each Base Element.

The Programmer has to develop only Generic Operations for all the class.

 

 

Pros:

 

 

Cons:

 

Reflective architectures are not always the best option, above all if there are not many base elements to generate the code.

 

With regard to their performance, they are architectures that add an additional layer of indirection, and that, a cause of that, depending of the specific application can be slow (though they generally do not have to be that way). Besides, there are some means to increase their performance, like, for instance, the using of cache.

 

4.- When do we have to develop a reflective architecture.

 

Developing an architecture has some costs and it is always not the most suitable technique, that depends on different aspects.

 

Generally, implementing a reflective architecture requires developing complex code elements, it needs some additional classes, it needs that additional level of indirection that give us the necessary potential and flexibility.

 

So, if it is a little application, implementing a reflective architecture is not recommended, as this will increase the complexity of the application, its cost and the needed knowledge for its maintenance without contributing much to it in exchange.

 

Then, when we should implement it?:

 

 

Let’s imagine a site like the one we have described at the beginning of this article (AnotherAmazon.com). A site that manages several different tables of different objects to be sold. That means that here we will have many base elements. This is the ideal scenario to implement a reflective architecture that let us modify, in a centralised and easy way, the information contained in these elements, add new elements of information like “DVD Players”, and so on.

 

Some useful references to look at:  

 

§               [ACG] “Automated Code Generation”: http://c2.com/cgi/wiki?AutomatedCodeGeneration
 
§               [CGIDS] “Code Generation is a Design Smell”: http://c2.com/cgi/wiki?CodeGenerationIsaDesignSmell
 
 
§               [OAOO] “Only and Only Once”: http://c2.com/cgi/wiki?OnceAndOnlyOnce
 
 
§               [RCG] “Reflection versus Code Generation”: http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html
  • [POSA] Pattern-Oriented Software Architecture: A System of Patterns (POSA) Buschmann, Meunier, Rohnert, Sommerlad, Stal; Wiley and Sons, 1996.
§               [WIR] “What is Refactoring” http://c2.com/cgi/wiki?WhatIsRefactoring

 

 

ã Moisés D. Díaz. www.moisesdaniel.com