Easy Modeling and Smart Code Generation

Since many years, MDSD (model-driven software development) and closely related topics are regularly found in magazines, books, on conferences and in forum discussions. The application of MDSD hasn’t become mainstream, though. If you speak to developers who use or develop with the Eclipse Modeling Project, naturally, you will hear the statement “modeling is alive”. However, there are a lot of developers – if not the majority – who neither do modeling nor generate code (or interpret models). By the way: commencing in March 2010 Generative Software and the FZI are going to run an online-survey on the topic MDSD (in German only). Amongst others it has the goal to find out, how many software developers actively use MDSD in one or the other form.

For MDSD there are a lot of modeling options and modeling tools available. You can do

  • textual modeling with a stand-alone modeling language (aka external DSL)
  • graphical modeling with UML
  • graphical modeling without UML
  • modeling with a general purpose programming language (aka internal DSL)
  • tabular modeling (kind of a spread sheet)
  • tree structured modeling (XML for instance)

For the generation part there are also a lot of tools available to do the job. Most of them apply a template approach where you express generation logic with the help of a template language.

Looking at how many years the model-driven approach for software development exists – CASE-tools in the 1990ies and MDA/MDSD since 2000 – and knowing how many different tools there were available on the market – and are not anymore – one may say: “MDSD has turned out not to fulfill its promises”. I would rather say: “It has been brought back down to earth”.

Let me try to outline some critical aspects of model-driven software development. By doing so you may get an idea of how MDSD, in many cases, can easily work when you do the following:

  • use an API-based, component-oriented, open source code generation tool that is integrated well into your IDE – JenerateIT is one example
  • for your modeling tasks and for the development of generation logic, use the general purpose programming language that you anyway use for your software under development
  • re-use and extend existing meta-models and generation logic that is provided by the community

Costs for MDSD Tools

There were and are modeling and generation tools out there that cost a lot of money. While a few of those tools may be worth the money, there are also lots of other tools that are open source and are of value. Ideally, there is a tool that comes with no licensing costs and at the same time doesn’t require a lot of effort to learn and comprehend how it works and how it should be used and adapted.

It is easy to find out whether you can use a tool without licensing costs. It is much more difficult, though, to find out, which additional, hidden costs are involved in using such a tool.

As a matter of fact, if you use Java (or another object-oriented programming language) as your meta-meta-model and use your IDE as modeling tool, you do not have to pay (additional) money for a modeling tool. Also, you do not have to spend additional efforts for installation, set-up and maintenance of a modeling tool.
Doing so does not limit you to use your IDE as modeling tool. You are still free to add another modeling tool to your MDSD tool-landscape. In that scenario, a model-to-model transformation converts the model (created with the new tool) to a model that conforms to the meta-model that is understood by your existing generation logic.

Quick and smooth Introduction of MDSD

When you start applying MDSD, you are confronted with the following tasks.

  • install and configure modeling and generation tool
  • learn how to use modeling tool
  • learn how to use generation tool
  • learn how to design and implement modeling language
  • design of modeling language
  • implement modeling language
  • learn how to develop generation logic
  • develop generation logic
  • add generation steps to your continuous integration infrastructure
  • create and maintain a reference model for the development and testing of your generation logic
  • develop unit tests for generation logic

You do not only have to handle those tasks once. There also need to be people who are responsible for some of those tasks, not only at the begining of a project but constantly. The sheer number of tasks together with the uncertainty on what risks and efforts are involved with them, acts as a deterrent.

By using your IDE as modeling tool and using a general purpose programming language as the language to develop generation logic, you get rid of some of those points and risks and make some of them being not deterrent.

Flexibility and Agility in Modeling and Generation

This is a double-edged sword. You may find it helpful, if the modeling or generation tool limits the options to design a modeling language or to develop, maintain and control generation logic. On the other hand, you loose agility and flexibility due to those limitations. The more often you ask “Can I do this or that with tool x?” and you get answers like “No” or “Yes, but you have to use a hack/trick” or “Yes, but it is slow” or “No, but in a year this may be possible”, you should consider using a different tool or a different approach.

With regards to flexibility in code generation, the following features may be worth thinking about.

  • non-sequential writing to an artifact, e.g. writing a Java import statement while writing a method body
  • from inside generation logic, having the ability to find/access objects that represent other artifacts that are being generated and objects that encapsulate other generation logic
  • back-tracking to easily find out and visualize, which part of generation logic is responsible for the writing of which part of an artifact
  • full access to the content of the previously generated artifact, including potential manual changes therein

JenerateIT is capable of doing all this … and more.

Reuse and Encapsulation of Generation Logic

Often it is difficult – if not impossible – to reuse existing generation logic. This is escpecially true when template-based generation is applied. When generation logic is implemented by means of an object-oriented general purpose programming language like for instance Java, support for reuse is built-in.

Reuse does not only mean that you may use existing generation logic for more than one project or more than one piece of software. It also means, that you do not need to repeat yourself when developing generation logic. Lets assume we generate several artifacts. How does the generation logic for artifact A know what is going to be written to artifact B? A basic solution may simply know (by convention), what is getting written to artifact B. A more sophisticated solution, in a generation tool that uses not templates but an API to write generation logic, generation logic for artifact A would find out, what is getting written to B.

With the API approach, tasks like the following are getting easy to implement:

  • find fully-qualified names of all Java classes that are going to be generated
  • find all internationalization files that are going to be generated
  • find the fully-qualified name of the class that holds data for data binding for a graphical user interface
  • find names of all files that are going to contain the online help

JenerateIT‘s API is capable of doing all this. The generation logic of gApp makes extensive use of those capabilities.

Flexible Models

In MDSD a model is an instance of a meta-model. And a meta-model is described by means of a meta-meta-model. An EMF meta-model for instance consists of objects of type EClass, EAttribute, EPackage, etc. (all Ecore types). A meta-model created with MetaEdit+ consists of objects of type Graph, Object, Relationship, Role, Port and Property (GOPPRR).

That’s all fine. However, what if you want to use (existing) data/information that has not been created by means of an MDSD modeling tool? You have to spend extra efforts to somehow transform that data/information to be available in a form that is based on Ecore, GOPPRR or whatever meta-meta-model you use for modeling.

Things become different when you use the Java language’s model as the meta-meta-model for your meta-models. With this, everything that can be read by means of Java is a model. Defining a meta-model then is equivalent with writing Java classes. Creating a model based on that meta-model is equivalent with creating instances of those Java classes. Your Java-IDE automatically turns into a modeling tool. All Java support in your IDE also supports your modeling tasks. No apprehension that your modeling tool will not be available on the market anymore or that it won’t be under further development.
In addition to this, your knowledge and experience about the Java language and libraries and object-orientation (OOA/OOD/OOP) instantly can be leveraged. JenerateIT fosters this way of modeling, while using models based on other formats like EMF, UML, XML, etc. is still possible and supported.

Mixing generated and hand-crafted Code

Most experts for MDSD say to generate at most 80% of your code is a realistic scenario. So you have at least 20% manually written code (note that “manually written” can also mean “automatically created through your IDE”). There are a few well-known solutions to mix generated with hand-written code.

  • generation gap pattern
  • protected regions/areas/code (aka developer areas)
  • one-off targets – artifacts that will never be re-generated once their content has been manually modified (in fact that is a special case of protected regions/areas/code)

While it is good to have those solutions, additional, more sophisticated, specialized solutions are required to efficiently and comfortably mix generated with manually written code. And those solutions do not require protected regions/areas/code.

  • protect manual changes in a property file from being overwritten (e.g. for application internationalization)
  • merge manually added Java import statements with import statements that are being created by generation logic
  • protect manual changes in originally empty method bodies
  • protect manually added fields or methods of a Java class
  • … further specific solutions …

Note that for those solutions to work, it is required that the content of previously generated artifacts are available during generation. And using a general purpose programming language to write generation logic makes it easy and straightforward to handle these things. JenerateIT does exactly that.

Integration in Development-Environment

Some MDSD tools are stand-alone tools. Using those tools makes it difficult to integrate them into a software developer’s IDE. It is still possible to work with the tools and the IDE. But the acceptance of software developers may be low. Also, due to the fact that a stand-alone tool runs in a separate process, synchronization tasks have to be executed. And such tasks may have a negative effect on the development round-trip and generation performance.
A better tooling solution is to have a modeling and generation environment, that is integrated in the IDE. And even better than this is a solution that provides the same modeling and generation support accross different IDEs for the same target platform (e.g. Eclipse, NetBeans and IntelliJ for the Java platform).

JenerateIT is well integrated into Eclipse. Integrations into NetBeans and IntelliJ are easy to accomplish since the core of JenerateIT is not dependent on any of those IDEs. This modularization also allows for running an Ant-based generation, for instance as part of the continuous integration process.

Teamwork and Model-Partitioning

One of the biggest challenges in the modeling part of MDSD is how to model in a team. Things like partitioning of models, model diffs, model versioning and model merge are not easy to accomplish. MDSD modeling tool providers typically have their proprietary solution to this problem. And that solution normally costs a lot of money.
When you use textual modeling, no matter whether it is through internal DSLs on top of a general purpose programming language or through an external DSL (e.g. by using Eclipse Xtext), teamwork works the same way as teamwork in traditional software development works. Any version control tool that is capable to do versioning, diffing and merging of textual artifacts can be used to store the model. Open source examples for such tools are Apache Subversion and Git.

Conclusion

Doing model-driven software development can be really easy, without the burden of complex theory and without a lot of new things to learn and digest. It is not necessary to completely bend your development environment and yourself. The biggest challenge that remains is to add at least two new levels to your thinking: meta-model and model, together with transformation/generation steps to get utilizable results. That’s the price you have to pay to gain a lot of power, flexibility and agility.

You may want to give the open source code generation tool JenerateIT a try, to experience the simplicity of MDSD.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.