[ovirt-devel] Thoughts on modularization

Yair Zaslavsky yzaslavs at redhat.com
Sat Nov 8 09:41:57 UTC 2014



----- Original Message -----
> From: "Vojtech Szocs" <vszocs at redhat.com>
> To: "Alon Bar-Lev" <alonbl at redhat.com>
> Cc: "Mark Proctor" <mdproctor at gmail.com>, devel at ovirt.org
> Sent: Friday, November 7, 2014 4:45:57 PM
> Subject: Re: [ovirt-devel] Thoughts on modularization
> 
> 
> 
> ----- Original Message -----
> > From: "Alon Bar-Lev" <alonbl at redhat.com>
> > To: "Vojtech Szocs" <vszocs at redhat.com>
> > Cc: devel at ovirt.org, "Mark Proctor" <mdproctor at gmail.com>
> > Sent: Wednesday, November 5, 2014 5:16:15 PM
> > Subject: Re: [ovirt-devel] Thoughts on modularization
> > 
> > 
> > 
> > ----- Original Message -----
> > > From: "Vojtech Szocs" <vszocs at redhat.com>
> > > To: "Alon Bar-Lev" <alonbl at redhat.com>
> > > Cc: devel at ovirt.org, "Mark Proctor" <mdproctor at gmail.com>
> > > Sent: Wednesday, November 5, 2014 6:07:50 PM
> > > Subject: Re: [ovirt-devel] Thoughts on modularization
> > > 
> > > 
> > > 
> > > ----- Original Message -----
> > > > From: "Alon Bar-Lev" <alonbl at redhat.com>
> > > > To: "Vojtech Szocs" <vszocs at redhat.com>
> > > > Cc: devel at ovirt.org, "Mark Proctor" <mdproctor at gmail.com>
> > > > Sent: Wednesday, November 5, 2014 4:32:31 PM
> > > > Subject: Re: [ovirt-devel] Thoughts on modularization
> > > > 
> > > > 
> > > > 
> > > > ----- Original Message -----
> > > > > From: "Vojtech Szocs" <vszocs at redhat.com>
> > > > > To: "Alon Bar-Lev" <alonbl at redhat.com>
> > > > > Cc: devel at ovirt.org, "Mark Proctor" <mdproctor at gmail.com>
> > > > > Sent: Wednesday, November 5, 2014 5:24:14 PM
> > > > > Subject: Re: [ovirt-devel] Thoughts on modularization
> > > > > 
> > > > > 
> > > > > 
> > > > > ----- Original Message -----
> > > > > > From: "Alon Bar-Lev" <alonbl at redhat.com>
> > > > > > To: "Vojtech Szocs" <vszocs at redhat.com>
> > > > > > Cc: devel at ovirt.org, "Mark Proctor" <mdproctor at gmail.com>
> > > > > > Sent: Wednesday, November 5, 2014 4:12:06 PM
> > > > > > Subject: Re: [ovirt-devel] Thoughts on modularization
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > ----- Original Message -----
> > > > > > > From: "Vojtech Szocs" <vszocs at redhat.com>
> > > > > > > To: devel at ovirt.org
> > > > > > > Cc: "Mark Proctor" <mdproctor at gmail.com>
> > > > > > > Sent: Wednesday, November 5, 2014 5:04:24 PM
> > > > > > > Subject: [ovirt-devel] Thoughts on modularization
> > > > > > > 
> > > > > > > Hi guys,
> > > > > > > 
> > > > > > > I've discussed this recently with Yair and Mark, I just wanted to
> > > > > > > share
> > > > > > > some more thoughts on this topic -- in particular, how
> > > > > > > modularization
> > > > > > > problem can be approached (regardless of implementation details).
> > > > > > > 
> > > > > > > I see two approaches here. The typical one is to define APIs for
> > > > > > > modules
> > > > > > > to consume. For example, oVirt Engine extension API has API for
> > > > > > > auth
> > > > > > > stuff; oVirt UI plugin API has API for showing tabs and dialogs,
> > > > > > > etc.
> > > > > > > The advantage is strict consistency, disadvantage is burden of
> > > > > > > having
> > > > > > > to maintain the whole API. With this approach, you tell modules:
> > > > > > > "This
> > > > > > > is the API to work with system, defining how you can plug into
> > > > > > > it."
> > > > > > > 
> > > > > > > Now turn 180 degrees. The other approach, which is really
> > > > > > > interesting,
> > > > > > > is to let modules themselves export API. This naturally leads to
> > > > > > > module
> > > > > > > hierarchies. Ultimately, this leads to micro-kernel-style
> > > > > > > development,
> > > > > > > where all logic resides in modules. Now you might ask: "What if
> > > > > > > we
> > > > > > > want
> > > > > > > to employ some consistent work flow across multiple modules? For
> > > > > > > example,
> > > > > > > have some pluggable *auth* infra?" -- this can be done via some
> > > > > > > "higher"
> > > > > > > level module, that exports API and "lower" level modules consume
> > > > > > > that
> > > > > > > API.
> > > > > > > 
> > > > > > > If you have any ideas, please share!
> > > > > > 
> > > > > > Both solutions can be applied using existing extension api, an
> > > > > > extension
> > > > > > can
> > > > > > locate other extension and interact with it the same way the core
> > > > > > interacts
> > > > > > with extensions.
> > > > > 
> > > > > But how does core interact with extensions? I assume via well-defined
> > > > > API, i.e. in accordance with first approach mentioned above.
> > > > 
> > > > presentation:
> > > > http://www.ovirt.org/File:Ovirt_3.5_-_aaa.pdf
> > > 
> > > Thanks for sharing!
> > > 
> > > > 
> > > > package org.ovirt.engine.api.extensions;
> > > > 
> > > > /**
> > > >  * Interface of an extension.
> > > >  */
> > > > public interface Extension {
> > > > 
> > > >     /**
> > > >      * Invoke operation.
> > > >      * @param input input parameters.
> > > >      * @param output output parameters.
> > > >      *
> > > >      * <p>
> > > >      * Interaction is done via the parameters.
> > > >      * Exceptions are not allowed.
> > > >      * </p>
> > > >      * <p>
> > > >      * Basic mappings available at {@link Base}.
> > > >      * </p>
> > > >      *
> > > >      * @see Base
> > > >      */
> > > >     void invoke(ExtMap input, ExtMap output);
> > > > 
> > > > }
> > > 
> > > OK, so it was my lack of knowledge of AAA implementation :)
> > > 
> > > Since Extension interface is invoke-based, I assume that Engine
> > > core (backend) invokes extensions on specific occasions, right?
> > 
> > correct, and nothing prevents extension to invoke other extensions.
> 
> I see. I just wanted to clarify who makes the initial invocation.
> If there is some core, extensions just extend that core. This is
> different from my view of pure modularization, where there is no
> core, there are just modules and all important logic resides in
> modules.

Well, with the proper resources (time + personnel) I see no reason why engine cannot be transformed into pure modularization appraoch, as you suggest for UI, besides of course having a small
microkernel or call it whatever you want that will be responsible on loading the extesnsions, resolving dependencies etc...

> 
> > 
> > > > 
> > > > > With second approach mentioned above, core would not interact with
> > > > > extensions at all (or in a very limited way), instead - extensions
> > > > > would interact with each other. In other words, extension would not
> > > > > need to implement core-specific API (there would be none), instead
> > > > > it would inject its dependencies (other modules/extensions) and
> > > > > consume their APIs. This is the difference I wanted to point out :)
> > > > 
> > > > The extension interface is primitive to enable exactly that, provided
> > > > java
> > > > people will open their minds :)
> > > 
> > > Simple interface means great flexibility, now I understand the
> > > rationale behind typed maps in extension API.
> > > 
> > > What I had in mind was something like this (maybe crazy):
> > > 
> > > * imagine for a moment that the backend is fully modular
> > >   (logic lives in modules, no logic outside modules)
> > > 
> > > * @DependsOn("SomeOtherModule") // modules can form hierarchies
> > >   public class MyModule implements Module {
> > >     public void loaded() {} // executed just once per module
> > >   }
> > 
> > you again using java magic for something that can go to declaration...
> 
> Java annotations are static metadata, they are not magic :)
> 
> Annotations are helpful because they declare what should be
> done, not how it should be done. @DependsOn in example above
> means that some infra will process/scan classes and if it
> finds this annotation, it will invoke extra logic according
> to the semantics of this annotation.
> 
> Yes, it could also go into "conventional" declaration like
> properties files etc. I have nothing against that, the major
> point is declaring useful metadata in some way :)
> 
> > 
> > > 
> > > * API for fetching modules, i.e. getModuleByName('xxx')
> > 
> > there is no need as within the extension context you have access to this
> > information, all you need is iterate a list, see Base.java.
> 
> What I meant: module A exports API "foo", module B depends on
> module A and therefore can consume API "foo".
> 
> IIUC, in Engine ext-api you must find appropriate extension
> yourself, in order to invoke it. This is the difference,
> because what I suggested above is to allow modules to state
> their dependencies, instead of having to locate them on their
> own.
> 
> Declaring dependencies in advance has many advantages, one
> of them is you can avoid "always load all dependencies in
> some sequence" because you don't know which module will
> need which other module.
> 
> > 
> > >   API for exporting module API, i.e. exportApiObject(foo)
> > 
> > not sure why it is needed... once extension is loaded it is available.
> 
> It was meant as means of communication between modules.
> 
> Engine ext-api invoke-based interface defines communication
> between extensions via input & output maps. What I meant is
> different mean of communication -> one module exports its
> API (i.e. object) and another module can consume that API.
> 
> > 
> > > This way, you'd have one "core" module, providing most general
> > > functionality/abstractions. Then you'd have more specific modules,
> > > plugged into "core" module's API etc. In other words, hierarchy of
> > > modules. This is essentially modularization taken to extreme :)
> > > 
> > > (BTW, above is just an idea.)
> > 
> > not sure I understand what is the functionality difference between this and
> > the primitive approach we already have...
> 
> The difference is:
> 
> a, have some (monolithic) core, which invokes extensions
> b, have no core, everything is a module
> 
> > 
> > 1. every configuration at /etc/ovirt-engine/extensions.d and
> > /usr/share/ovirt-engine/extensions.d are loaded during engine startup.
> 
> In a modular architecture, where everything is a module, module
> "tree" is determined (according to module dependency declarations)
> and loaded.
> 
> In a typical extension architecture, all extensions are always
> loaded in some sequence.
> 
> > 
> > 2. each extension has two phases load and init, during init an extension
> > can
> > locate other extensions by name via its context. it is true that probably
> > missing functionality is to support ordering of the init and load, we left
> > it into future as there was no actual need for this.
> 
> This is actually quite similar to how our UI plugins are loaded,
> except for that "locating other plugins" is not implemented.
> 
> > 
> > 3. each extension can interact with other extension.
> > 
> > 4. there must be core model to trigger the entire thing, core cannot be
> > just
> > a loader.
> 
> This is a design decision. A "core" can be either monolithic base
> (includes business logic) that invokes extensions. Alternatively,
> "core" can be just module loader, and all logic is in modules.
> 
> So I disagree - core CAN be "just" a module loader.
> 
> See http://requirejs.org/docs/whyamd.html for details on this topic.
> 
> > 
> > Alon
> > 
> _______________________________________________
> Devel mailing list
> Devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/devel
> 



More information about the Devel mailing list