10 common EMF mistakes
1. Treating EMF generated code as only an initial code base
EMF is a good startup kit for introducing MDSD (Model-Driven Software Development) in your project. Anyone who has been introduced to EMF and had their first code generated using EMF will for sure be impressed by the short turn around time needed to have an initial version of your model based application up and running. For many, the thrill ends as soon as you need to change the behaviour of generated code and have to dig into it and understand it. It is complex, but only complex as any other similar sized framework. Many projects I have come across make a mistake at this point. They start treating the EMF generated code as an initial code base and start making it dirty by modifying it by hand. Adding @generated NOT tags in the beginning and not anymore later. At this point you part ways with “EMF way of doing things” and also with MDSD.
The customizations mostly start with the generated editor. This is quite acceptable as the editor is intended as an initial “template” and it expects you to customize it. However, this is not the case with model and edit projects. They have to be in sync with your model and this needs making some strong decisions, specifically – ”I will not touch the generated code”. Follow EMF recommended way of changing generated code or use Dependency Injection.
2. Model modification without EMF Commands
In EMF you deal a lot with model objects. Almost any UI selection operation hands over a model object to you. It is so easy to fall into the trap of changing the state of the model objects directly once you have access to it, either using the generated model API or using reflective methods. Problems due to such model updates are detected only later, mostly when Undo/Redo operations stops working as expected.
Use EMF Commands! Modify your model objects only using commands. Either directly using EMF commands, extending them or creating your own commands. When you need to club many operations as a single command use CompoundCommands. Use ChangeCommand when you are up to making a lot of model changes in a transactional way.
3. Not reacting to notifications/Overuse of notifications
EMF notification is one the most powerful features of the framework. Any change to model objects are notified to anyone who is interested in knowing about it. Many projects decide to ignore listening to model changes and react to model changes by traversing the model again to look for changes or making assumptions about model changes and combining the behaviour into UI code.
When you want to react to a model change, don’t assume that you are the only one going to originate that change. Always listen to model changes and react accordingly. Don’t forget the handy EContentAdapter class.
On the contrary, some projects add a lot of listeners to listen to model changes without applying proper filters. This could greatly slow down your application.
4. Forgetting EcoreUtils
Before writing your own utility functions, keep an eye on EcoreUtils class. Mostly, the generic function you are trying to implement is already there.
5. Leaving Namespace URI as default
When you create an Ecore model, EMF generates a default Prefix and Namespace URI for you. Mostly this is left as it is without realizing that this is the most important ID for your new model. Only when newer versions of the model needs to be released later, people start looking out for meaningful URIs.
Change the default to a descriptive one before generating code. For example, including some version information of the model.
6. UI getting out of sync with model
The EMF generated editor makes use of Jface viewers. These viewers are always kept in sync using the generated ItemProviders. However these viewers cannot always satisfy the different UI requirements. You might have to use other SWT components or Eclipse forms. At this juncture, many implementors mix UI and model concerns together and in turn lose the sync between the model and UI.
Although, you could go ahead and implement your custom viewers, the easier way would be to use EMF Databinding.
7. Relying on default identification mechanism
Every EMF object is identified by a Xpath like URI fragment. For example, //@firstname.lastname@example.org. This is the default referencing mechanism within an EMF model or across models. If you look closely you could see that the default mechanism is based on feature names and indexes. The default implementation could turn dangerous if the index order changes and the references are not updated accordingly.
Extend this to uniquely identify your model object or simply assign an intrinsic ID to your model object. EMF will then use these IDs to reference your objects.
8. Forgetting reflective behavior
Instead of depending fully on generated APIs, think about creating generic reusable functions which makes use of the meta information every EObject carries. Have a look at the implementation of EcoreUtil.copy function to understand what I mean.
9. Standalone? Why do I bother
While developing applications based on EMF you should design your applications such that the core is not tied to Eclipse. This would allow your applications to be run even in a non OSGi server-side environment.