Sunday, 23 October 2011

Control the code generation process

In this best practices I'd like to explain when and how to best adapt EMF’s default code generation facilities. The goal of this best practise is to motivate developers to get in control of their code generation process. Knowing how EMF's code generation process works and if needed, where to start to make changes, is a big step towards extensive model driven development. EMF comes with a set of default templates which support the generation of model code, UI independent controller code and Eclipse specific editor code. According to my experience, one can go a long way with EMF’s default templates and the code generation configuration mechanisms available on genmodel level. However, knowing about the possibility to interfere in the generation process empowers developers to apply project specific template adaptation, decide weather to make changes to generated code or templates and extend code generation to areas not yet covered by EMF.

EMF default templates can be found in the plugin org.eclipse.emf.codegen.ecore. The subfolder /templates/ contains all EMF templates necessary to generate model, edit, editor and model test code. During code generation EMF compiles its templates to Java template classes holding all template text in String member variables and a single method generate.

Once done and no changes have been made to the template, thecompilation step may be omitted to speed up the generation process. This can be controlled through the GenModel attribute dynamicTemplates. Setting dynamicTemplates to false will only compile the Java template classes if not yet available. Setting dynamicTemplates to true will recompile template classes anytime. Thus any change to a template will lead to changes in the final generation artefact.

To let developers override EMF templates on a per model basis the GenModel attribute templateDirectory is used. The attribute specifies the location of the new template directory with respect to the workspace root (e.g. at.somecompany.somePluginProject/templates). While name and location of the directory are arbitrary, its internal subdirectory structure must stick to the predefined directory structure in org.eclipse.emf.codegen.ecore/templates.

It is always best to selectively copy original templates to the specified template directory. If the GenModel attribute dynamicTemplates is set to true EMF’s Generator implementation will first try to retrieve the required template from the specified directory, if none could be found EMF’s default template directory is searched.

EMF’s template mechanism is based on Java Emitter Templates (JET). JET supports JSP like syntax. A template contains fixed text, which is output as is, and text within JSP tags which are used an navigate through a model or directly express java code. To learn more about JET syntax see this 
EMF Corner Article. A downturn of using JET is its limited tool support. Up  to Eclipse Helios 3.6 no working jet template editor was available.

Hopefully to be continued...

Working with model instances

EMF does not only provide modeling and code generation facilities, but as well powerful runtime support for manipulating model instances. Runtime support builds upon the reflective nature of EMF models and on generated metadata facilities such as model specific factory (EFactory) and metadata holder (EPackage) implementations. When starting to work with EMF and not knowing about this support, one will treat model instance as any other object structure and use home made patterns to access and manipulate your models.

Within a software project not all team members share the same knowledge and understanding of EMF. Team members concerned with architecture and design might have deeper insight into EMF compared to other developers merrily being “forced” to work with EMF models. To some extend this is fine, designing models and handling the generation process is not a task every team member has to accomplish. However, when programming against EMF models there are a number of use model Even you actively try to limit these differences, at any point of a project team members may come and go. Clearly, new team members

This and later posts shall introduce a minimum set of very useful framework features and starting points client programmers should know about. The following issues are covered:
  • Use EcoreUtil as your starting pointNavigate through your model instance
  • Identify usage of model elements
  • Extend behaviour of model elements
  • Testing equality of object structures
  • Copy model elements

Use EcoreUtil as a starting point

The class EcoreUtil in the package org.eclipse.emf.common.util is probably the best starting point to learn about EMF’s runtime support for model instances. Just skimming and reading through the implementation code will reveal EMF useful utilities as well as interesting EMF internals to developers. EcoreUtil provides static methods and nested inner classes which exploit the reflective nature of EMF models to generically work with model elements. Let’s assume we want to remove a model element from its contained object structure. Without any EMF insight the straight forward approach would be to retrieve the parent and directly unset the model element or in the case of a multiplicity many features remove the model element from the list of model elements. The following snippet displays EcoreUtil’s implementation of the remove method, which reflectively retrieves the elements container and feature, and removes the element.

/**
* Removes the object from its {@link EObject#eResource containing} resource
* and/or its {@link EObject#eContainer containing} object.
* @param eObject the object to remove.
*/

public static void remove(EObject eObject) {
  InternalEObject internalEObject = (InternalEObject)eObject;
  EObject container = internalEObject.eInternalContainer();
  if (container != null) {
     EReference feature = eObject.eContainmentFeature();
     if (FeatureMapUtil.isMany(container, feature)) {
       ((EList<?>)container.eGet(feature)).remove(eObject);
     }
     else {
      container.eUnset(feature);
     }
  }
  Resource resource = internalEObject.eDirectResource();
  if (resource != null) {
    resource.getContents().remove(eObject);
  }
}

Saturday, 22 October 2011

EMF Best Practices

EMF is cool thing and when working with eclipse and java one should realy give EMF a try. This is advice I gave many times to other software developers. The response I got was often something like "EMF is way to complex", "the threshold is simply to high" "I'll better create my models in handcrafted code". Therefor I decided to write down best practices I developed over the years using EMF and which might help to lower the threshold for using EMF. I want to cover the following topics, which I think are key factors for successfully using EMF.

Working with Model Instances - EMF does not only provide modeling and code generation facilities, but as well powerful runtime support for manipulating model instances. Runtime support builds upon the reflective nature of EMF models and on generated metadata facilities such as model specific factory (EFactory) and metadata holder (EPackage) implementations. When starting to work with EMF and not knowing about this support, one will treat model instances as any other object structure and use home made patterns to access and manipulate your models. This best practice introduces a minimum set of very useful framework features and starting points developers should know about.
Adapt default templates - In this best practices I explain when and how to best adapt EMF’s default code generation facilities. The goal of this best practise is to motivate developers to get in control of their code generation process. Knowing how the code generation process works and if needed, where to start to make changes, is a big step towards extensive model driven development.

Mark model features as derived - When creating a domain model one may face the problem that values and state of model attributes may depend on other attribute values and that changes to one attribute must instantly trigger updates of dependent model valuei. A simple modeling technique is to mark model features which depend on others as derived. This can be achieved through marking an attribute or reference in your model editor as derived. Subse EStructuralFeatures as derived. flag on helps to represent this domain logic on model and implementation level by marking model features as derived. However setting the derived flag in your ecore editor leaves the generated code uneffected (an exception is the metadata initialization). This comes because the value of derived is somehow "derived" itself. Derived features are typically marked as volatile, transient and non-changeable. This leads to code which omitts feature serialization (transient), member variables and getter implementation (volatile) and declaration of setters (non-changeable).

Models change so you better be prepared - At some point a domain model will change. Be it due to deeper domain insight, the rise of new requirements or even technical issues such as performance optimization. As long as your model lives within a protected development environment even big changes are of no problem but as soon as you release, even minor changes can become real problem. Meta-Model and model instance evolution are a hot topic and various approaches such as cope or epatch provide assistance. A simple but yet very imported thing to do is to start to version your models. This can be achived through verious ways. I simple use a version number within a models package URI. So use something like http://at.somecompany/4/somemodel.ecore.

Hopefully to be continued....