[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipse-incubator-e4-dev] What I dislike about using EMF for e4...

Ed Merks wrote:
I would also assert that that EObjects really do feel just like DOM.

Yes it does. But as Eric pointed out, there are a already DOM-like interfaces in eclipse:

  org.eclipse.ui.IMemento
  org.eclipse.core.runtime.IConfigurationElement
  org.eclipse.jface.preference.IPreferenceStore
  org.eclipse.jface.dialogs.IDialogSettings
  org.eclipse.debug.core.ILaunchConfiguration
  org.eclipse.core.databinding.observable.value.IObservableValue
  ... (I am sure I forgot some)

And I would add reflective EMF to that list. Only EMF and IObservableValue
support change propagation.

I am a great fan of reflective data-structures. And I would love to see
a unification of all the different DOM like data-structures. If we can
adapt all of the data-structures to EObject then we would have a common
reflective API. Unfortunately the EObject API is not as easy to use as
say IMemento. One of the problem is that you have to have a metamodel
in order to create instances. But even IMemento is hard to use.

When to use reflective style and when java interfaces?
------------------------------------------------------

Reflective API is great for:
 - serialization
 - generic UI
 - databinding
 - data driven UI
 - scripting
 - verification ,
 - code generation (based on a model)
 -...

Reflective access gets very difficult if it is used in hand-written
code. In those cases interfaces are much better.


MagicInterface --------------

Some years ago when I figured out that there are so many reflective
interfaces in eclipse I thought, how can I unify them and make all
of them type safe. Reflective interfaces are great for generic
tools like my generic editor (http://tinyurl.com/4rbe5j). However
using reflective interfaces "by hand" is annoying. It is much better
to use real interfaces. But with EMF, you have to create a meta-model
and then generate a whole bunch of code. Which is also inconvenient.

So, I invented what I called MagicInterface. The idea is that you
write the data-structure as interfaces and there is some magic
that binds the interface to the underlying DOM like representation.

Let's stick with IMemento. Some code from org.eclipse.ui.internal.FastViewBar:

    public void saveState(IMemento memento) {
        memento.putInteger(IWorkbenchConstants.TAG_FAST_VIEW_SIDE, getSide());

        Iterator iter = viewOrientation.keySet().iterator();
        while (iter.hasNext()) {
            String next = (String) iter.next();
            IMemento orientation = memento
                    .createChild(IWorkbenchConstants.TAG_FAST_VIEW_ORIENTATION);

            orientation.putString(IWorkbenchConstants.TAG_VIEW, next);
            orientation.putInteger(IWorkbenchConstants.TAG_POSITION,
                    ((Integer) viewOrientation.get(next)).intValue());
        }
    }

With MagicInterface you'd create an ad-hock interface that represents
you data-structure (very much like the EMF annotated java):

   interface FastViewState extends MagicInterface { //MagicInterface is empty marker interface
        int getFastViewSide();
        void setFastViewSide(int side);
        Orientation[] getOrientation();
        Orientation addOrientation();
   };
   interface Orientation extends MagicInterface {
	String getView();
        void setView(String view);
        int getPosition();
        void setPosition(int pos);
   };

With the magic interface and the memento you go to the MagicFactory
(today I'd call it MagigAdapter) and it will create you an
implementation (based on java.lang.reflect.Proxy):

    public void saveState(IMemento memento) {
   	FastViewState state=(FastViewState )MagicFactory.cast(FastViewState.class, memento);
   	state.setFastViewSide(getSide());

        Iterator iter = viewOrientation.keySet().iterator();
        while (iter.hasNext()) {
            String next = (String) iter.next();
            Orientation orientation = state.addOrientation();

            orientation.setView) next);
            orientation.setPosition( ((Integer) viewOrientation.get(next)).intValue());
        }
    }

The advantage is, that you have real interfaces (refactoring is your friend)
but no overhead in generating a model.  Sure, this does not scale, but it
makes your code a bit more readable. Instead of ad-hoc string properties,
it uses ad-hoc interfaces.

Well and if you want to save the state as IDialogSettings, just use
the MagicFactory to convert the dialog settings to magic interfaces.
Any of the DOM mentioned above are all used in the same way. To add
support for a new DOM type, all you have to do is to implement my
special version of a simple interface called IDataStore.

The implementation is based on naming conventions. I also had a version
where you could give additional hints to the underlying implementation
using final attributes (I did this long before jdk1.5 and annotations existed)
using fluent interface (http://en.wikipedia.org/wiki/Fluent_interface)

    final MagicMember name=new MagicMember().setDefault("default-value");
    String getString();

But my colleagues thought this is too much complexity, so I removed it.

Summary
-------

Reflective access to data-structures is great when used by frameworks in
a generic fashion. In hand written code, should use interfaces instead.
EMF is great for both. Unfortunately, it is not really simple to be used
in an ad-hoc way (like Magic Interfaces) and it is too hard to be used
in in a reflective way, because you have to define a meta-model first.
(I have a solution to that too, but that's maybe too much for this
mail)

Michael