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! Vojtech

----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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. Alon

----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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. 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 :)
Alon

----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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 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); }
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 :) Regards, Alon

--Apple-Mail=_EFCB2602-4A51-4D64-9D5F-1F81EDF760BA Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Not sure if my previous email made it to the wider level@ovirt.org list. = I just subscribed :) So I=E2=80=99ll repeat the info. Here is a migration path, with detailed explanation on GWTP mappings: = https://docs.google.com/presentation/d/1KImrCvvqaUTgULP-CksUfGwLchJv4uB-dK= QSgHPX6rU/edit#slide=3Did.p14 = <https://docs.google.com/presentation/d/1KImrCvvqaUTgULP-CksUfGwLchJv4uB-d= KQSgHPX6rU/edit#slide=3Did.p14> Here presentation I gave yesterday, showing all the work we=E2=80=99ve = done in BRMS and BPMS and doing. = http://blog.athico.com/2014/11/red-hat-jboss-brms-and-bpms-workbench.html = <http://blog.athico.com/2014/11/red-hat-jboss-brms-and-bpms-workbench.html= > It also shows a little around our Screens and Perspective plugins, or = two units of extensions. Both of which have polyglot bindings = (GWTExported, will migrate to @JsType later). Implicitly Maven is our = unit of modularity, with maven dependency tree to declare this - however = this is not recognised in any internal registry. CDI just scans and = picks up any @Screen, @Perspective etc. But could be added, to give = physical representation of that unit of modality, with life cycle = callbacks - we just haven=E2=80=99t had a need for this yet. Our plan over 2015 is to use JsType to create a contract for all the = things a module needs. We will then compile modules separately against = this, with iframe separation, so each Module is loaded as a separate GWT = app. This does mean GWT core repetition, a pita, but that atleast gets = us started and may be solvable by a custom GWT linker. Longer term we=E2=80=99d like to work with GWT team. They now use the = Closure compiler, this support symbol tables, and I expect how their = incremental compiler works for their super dev mode. We want to achieve = two things 1) stop recompilation of maven modules, when aggregated into = sub projects. 2) declare apis that cannot be pruned 3) export a symbol = table to allow later compilation of runtime extensions against those, = without requiring a repetition of the GWT core (i.e. problem with our = first attempt). We will still continue with our polyglot bindings approach, such as with = the AngularJS stuff we have done. But I do not see this as the ideal = programming model - it hides much of what Errai brings, around event = bus, and general java refactoring capabilities. However it is still = useful for our customers, who want to write extensions, but do not want = to touch or learn GWT. Mark =20 > On 5 Nov 2014, at 15:32, Alon Bar-Lev <alonbl@redhat.com> wrote: >=20 >=20 >=20 > ----- Original Message ----- >> From: "Vojtech Szocs" <vszocs@redhat.com> >> To: "Alon Bar-Lev" <alonbl@redhat.com> >> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> >> Sent: Wednesday, November 5, 2014 5:24:14 PM >> Subject: Re: [ovirt-devel] Thoughts on modularization >>=20 >>=20 >>=20 >> ----- Original Message ----- >>> From: "Alon Bar-Lev" <alonbl@redhat.com> >>> To: "Vojtech Szocs" <vszocs@redhat.com> >>> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> >>> Sent: Wednesday, November 5, 2014 4:12:06 PM >>> Subject: Re: [ovirt-devel] Thoughts on modularization >>>=20 >>>=20 >>>=20 >>> ----- Original Message ----- >>>> From: "Vojtech Szocs" <vszocs@redhat.com> >>>> To: devel@ovirt.org >>>> Cc: "Mark Proctor" <mdproctor@gmail.com> >>>> Sent: Wednesday, November 5, 2014 5:04:24 PM >>>> Subject: [ovirt-devel] Thoughts on modularization >>>>=20 >>>> Hi guys, >>>>=20 >>>> 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). >>>>=20 >>>> 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." >>>>=20 >>>> 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. >>>>=20 >>>> If you have any ideas, please share! >>>=20 >>> 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. >>=20 >> But how does core interact with extensions? I assume via well-defined >> API, i.e. in accordance with first approach mentioned above. >=20 > presentation: > http://www.ovirt.org/File:Ovirt_3.5_-_aaa.pdf = <http://www.ovirt.org/File:Ovirt_3.5_-_aaa.pdf> >=20 > package org.ovirt.engine.api.extensions; >=20 > /** > * Interface of an extension. > */ > public interface Extension { >=20 > /** > * 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); >=20 > } >=20 >> 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 :) >=20 > The extension interface is primitive to enable exactly that, provided = java people will open their minds :) >=20 > Regards, > Alon --Apple-Mail=_EFCB2602-4A51-4D64-9D5F-1F81EDF760BA Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html = charset=3Dutf-8"></head><body style=3D"word-wrap: break-word; = -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" = class=3D"">Not sure if my previous email made it to the wider <a = href=3D"mailto:level@ovirt.org" class=3D"">level@ovirt.org</a> list. I = just subscribed :) So I=E2=80=99ll repeat the info.<div class=3D""><br = class=3D""></div><div class=3D"">Here is a migration path, with detailed = explanation on GWTP mappings:</div><div class=3D""><a = href=3D"https://docs.google.com/presentation/d/1KImrCvvqaUTgULP-CksUfGwLch= Jv4uB-dKQSgHPX6rU/edit#slide=3Did.p14" = class=3D"">https://docs.google.com/presentation/d/1KImrCvvqaUTgULP-CksUfGw= LchJv4uB-dKQSgHPX6rU/edit#slide=3Did.p14</a></div><div class=3D""><br = class=3D""></div><div class=3D"">Here presentation I gave yesterday, = showing all the work we=E2=80=99ve done in BRMS and BPMS and = doing.</div><div class=3D""><a = href=3D"http://blog.athico.com/2014/11/red-hat-jboss-brms-and-bpms-workben= ch.html" = class=3D"">http://blog.athico.com/2014/11/red-hat-jboss-brms-and-bpms-work= bench.html</a></div><div class=3D""><br class=3D""></div><div = class=3D"">It also shows a little around our Screens and Perspective = plugins, or two units of extensions. Both of which have polyglot = bindings (GWTExported, will migrate to @JsType later). Implicitly Maven = is our unit of modularity, with maven dependency tree to declare this - = however this is not recognised in any internal registry. CDI just scans = and picks up any @Screen, @Perspective etc. But could be added, to give = physical representation of that unit of modality, with life cycle = callbacks - we just haven=E2=80=99t had a need for this yet.</div><div = class=3D""><br class=3D""></div><div class=3D"">Our plan over 2015 is to = use JsType to create a contract for all the things a module needs. We = will then compile modules separately against this, with iframe = separation, so each Module is loaded as a separate GWT app. This does = mean GWT core repetition, a pita, but that atleast gets us started and = may be solvable by a custom GWT linker.</div><div class=3D""><br = class=3D""></div><div class=3D"">Longer term we=E2=80=99d like to work = with GWT team. They now use the Closure compiler, this support symbol = tables, and I expect how their incremental compiler works for their = super dev mode. We want to achieve two things 1) stop recompilation of = maven modules, when aggregated into sub projects. 2) declare apis that = cannot be pruned 3) export a symbol table to allow later compilation of = runtime extensions against those, without requiring a repetition of the = GWT core (i.e. problem with our first attempt).</div><div class=3D""><br = class=3D""></div><div class=3D"">We will still continue with our = polyglot bindings approach, such as with the AngularJS stuff we have = done. But I do not see this as the ideal programming model - it hides = much of what Errai brings, around event bus, and general java = refactoring capabilities. However it is still useful for our customers, = who want to write extensions, but do not want to touch or learn = GWT.</div><div class=3D""><br class=3D""></div><div = class=3D"">Mark</div><div class=3D""><br class=3D""></div><div = class=3D""> <br class=3D""><div><blockquote type=3D"cite" = class=3D""><div class=3D"">On 5 Nov 2014, at 15:32, Alon Bar-Lev <<a = href=3D"mailto:alonbl@redhat.com" class=3D"">alonbl@redhat.com</a>> = wrote:</div><br class=3D"Apple-interchange-newline"><div class=3D""><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><br style=3D"font-family:= Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">----- Original Message -----</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><blockquote type=3D"cite"= style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D"">From: "Vojtech Szocs" = <<a href=3D"mailto:vszocs@redhat.com" = class=3D"">vszocs@redhat.com</a>><br class=3D"">To: "Alon Bar-Lev" = <<a href=3D"mailto:alonbl@redhat.com" = class=3D"">alonbl@redhat.com</a>><br class=3D"">Cc: <a = href=3D"mailto:devel@ovirt.org" class=3D"">devel@ovirt.org</a>, "Mark = Proctor" <<a href=3D"mailto:mdproctor@gmail.com" = class=3D"">mdproctor@gmail.com</a>><br class=3D"">Sent: Wednesday, = November 5, 2014 5:24:14 PM<br class=3D"">Subject: Re: [ovirt-devel] = Thoughts on modularization<br class=3D""><br class=3D""><br class=3D""><br= class=3D"">----- Original Message -----<br class=3D""><blockquote = type=3D"cite" class=3D"">From: "Alon Bar-Lev" <<a = href=3D"mailto:alonbl@redhat.com" class=3D"">alonbl@redhat.com</a>><br = class=3D"">To: "Vojtech Szocs" <<a href=3D"mailto:vszocs@redhat.com" = class=3D"">vszocs@redhat.com</a>><br class=3D"">Cc: <a = href=3D"mailto:devel@ovirt.org" class=3D"">devel@ovirt.org</a>, "Mark = Proctor" <<a href=3D"mailto:mdproctor@gmail.com" = class=3D"">mdproctor@gmail.com</a>><br class=3D"">Sent: Wednesday, = November 5, 2014 4:12:06 PM<br class=3D"">Subject: Re: [ovirt-devel] = Thoughts on modularization<br class=3D""><br class=3D""><br class=3D""><br= class=3D"">----- Original Message -----<br class=3D""><blockquote = type=3D"cite" class=3D"">From: "Vojtech Szocs" <<a = href=3D"mailto:vszocs@redhat.com" class=3D"">vszocs@redhat.com</a>><br = class=3D"">To: <a href=3D"mailto:devel@ovirt.org" = class=3D"">devel@ovirt.org</a><br class=3D"">Cc: "Mark Proctor" <<a = href=3D"mailto:mdproctor@gmail.com" = class=3D"">mdproctor@gmail.com</a>><br class=3D"">Sent: Wednesday, = November 5, 2014 5:04:24 PM<br class=3D"">Subject: [ovirt-devel] = Thoughts on modularization<br class=3D""><br class=3D"">Hi guys,<br = class=3D""><br class=3D"">I've discussed this recently with Yair and = Mark, I just wanted to share<br class=3D"">some more thoughts on this = topic -- in particular, how modularization<br class=3D"">problem can be = approached (regardless of implementation details).<br class=3D""><br = class=3D"">I see two approaches here. The typical one is to define APIs = for modules<br class=3D"">to consume. For example, oVirt Engine = extension API has API for auth<br class=3D"">stuff; oVirt UI plugin API = has API for showing tabs and dialogs, etc.<br class=3D"">The advantage = is strict consistency, disadvantage is burden of having<br class=3D"">to = maintain the whole API. With this approach, you tell modules: "This<br = class=3D"">is the API to work with system, defining how you can plug = into it."<br class=3D""><br class=3D"">Now turn 180 degrees. The other = approach, which is really interesting,<br class=3D"">is to let modules = themselves export API. This naturally leads to module<br = class=3D"">hierarchies. Ultimately, this leads to micro-kernel-style = development,<br class=3D"">where all logic resides in modules. Now you = might ask: "What if we want<br class=3D"">to employ some consistent work = flow across multiple modules? For example,<br class=3D"">have some = pluggable *auth* infra?" -- this can be done via some "higher"<br = class=3D"">level module, that exports API and "lower" level modules = consume that<br class=3D"">API.<br class=3D""><br class=3D"">If you have = any ideas, please share!<br class=3D""></blockquote><br class=3D"">Both = solutions can be applied using existing extension api, an extension<br = class=3D"">can<br class=3D"">locate other extension and interact with it = the same way the core interacts<br class=3D"">with extensions.<br = class=3D""></blockquote><br class=3D"">But how does core interact with = extensions? I assume via well-defined<br class=3D"">API, i.e. in = accordance with first approach mentioned above.<br = class=3D""></blockquote><br style=3D"font-family: Helvetica; font-size: = 12px; font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D"">presentation:</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><a = href=3D"http://www.ovirt.org/File:Ovirt_3.5_-_aaa.pdf" = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" = class=3D"">http://www.ovirt.org/File:Ovirt_3.5_-_aaa.pdf</a><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><br style=3D"font-family:= Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">package = org.ovirt.engine.api.extensions;</span><br style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><br style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">/**</span><br style=3D"font-family: Helvetica; = font-size: 12px; font-style: normal; font-variant: normal; font-weight: = normal; letter-spacing: normal; line-height: normal; orphans: auto; = text-align: start; text-indent: 0px; text-transform: none; white-space: = normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: = 0px;" class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D"">* Interface of an = extension.</span><br style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D"">*/</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">public interface Extension {</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><br style=3D"font-family:= Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> /**</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> * Invoke = operation.</span><br style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D""> * = @param input input parameters.</span><br style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> * @param output output = parameters.</span><br style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" = class=3D""> *</span><br style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> * <p></span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> * Interaction is done = via the parameters.</span><br style=3D"font-family: Helvetica; = font-size: 12px; font-style: normal; font-variant: normal; font-weight: = normal; letter-spacing: normal; line-height: normal; orphans: auto; = text-align: start; text-indent: 0px; text-transform: none; white-space: = normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: = 0px;" class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D""> * = Exceptions are not allowed.</span><br style=3D"font-family: Helvetica; = font-size: 12px; font-style: normal; font-variant: normal; font-weight: = normal; letter-spacing: normal; line-height: normal; orphans: auto; = text-align: start; text-indent: 0px; text-transform: none; white-space: = normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: = 0px;" class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D""> * = </p></span><br style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D""> * = <p></span><br style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D""> * = Basic mappings available at {@link Base}.</span><br style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> * </p></span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> *</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> * @see Base</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> */</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D""> void invoke(ExtMap input, = ExtMap output);</span><br style=3D"font-family: Helvetica; font-size: = 12px; font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><br style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" = class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; = font-style: normal; font-variant: normal; font-weight: normal; = letter-spacing: normal; line-height: normal; orphans: auto; text-align: = start; text-indent: 0px; text-transform: none; white-space: normal; = widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: = none; display: inline !important;" class=3D"">}</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><br style=3D"font-family:= Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><blockquote type=3D"cite" = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D"">With second approach = mentioned above, core would not interact with<br class=3D"">extensions = at all (or in a very limited way), instead - extensions<br = class=3D"">would interact with each other. In other words, extension = would not<br class=3D"">need to implement core-specific API (there would = be none), instead<br class=3D"">it would inject its dependencies (other = modules/extensions) and<br class=3D"">consume their APIs. This is the = difference I wanted to point out :)<br class=3D""></blockquote><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><span = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">The extension interface is primitive to enable = exactly that, provided java people will open their minds :)</span><br = style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; = font-variant: normal; font-weight: normal; letter-spacing: normal; = line-height: normal; orphans: auto; text-align: start; text-indent: 0px; = text-transform: none; white-space: normal; widows: auto; word-spacing: = 0px; -webkit-text-stroke-width: 0px;" class=3D""><br style=3D"font-family:= Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">Regards,</span><br style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px;" class=3D""><span style=3D"font-family: = Helvetica; font-size: 12px; font-style: normal; font-variant: normal; = font-weight: normal; letter-spacing: normal; line-height: normal; = orphans: auto; text-align: start; text-indent: 0px; text-transform: = none; white-space: normal; widows: auto; word-spacing: 0px; = -webkit-text-stroke-width: 0px; float: none; display: inline = !important;" class=3D"">Alon</span></div></blockquote></div><br = class=3D""></div></body></html>= --Apple-Mail=_EFCB2602-4A51-4D64-9D5F-1F81EDF760BA--

Hi Mark, sorry for late response. I've looked at GWTP -> UberFire migration presentation, looks interesting. It will be best if we discuss everything next week, I'll schedule a meeting on Monday (Nov 10) and also share it on devel-list for anyone interested to participate. @other, if you're interested in GWT, GWT-Platform, GIN, Errai, CDI, UberFire or JavaScript in general, please join this session. Some inline comments below. Regards, Vojtech ----- Original Message -----
From: "Mark Proctor" <mdproctor@gmail.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 5:06:24 PM Subject: Re: [ovirt-devel] Thoughts on modularization
Not sure if my previous email made it to the wider level@ovirt.org list. I just subscribed :) So I’ll repeat the info.
Here is a migration path, with detailed explanation on GWTP mappings: https://docs.google.com/presentation/d/1KImrCvvqaUTgULP-CksUfGwLchJv4uB-dKQS... <https://docs.google.com/presentation/d/1KImrCvvqaUTgULP-CksUfGwLchJv4uB-dKQSgHPX6rU/edit#slide=id.p14>
Here presentation I gave yesterday, showing all the work we’ve done in BRMS and BPMS and doing. http://blog.athico.com/2014/11/red-hat-jboss-brms-and-bpms-workbench.html <http://blog.athico.com/2014/11/red-hat-jboss-brms-and-bpms-workbench.html>
It also shows a little around our Screens and Perspective plugins, or two units of extensions. Both of which have polyglot bindings (GWTExported, will migrate to @JsType later). Implicitly Maven is our unit of modularity, with maven dependency tree to declare this - however this is not recognised in any internal registry. CDI just scans and picks up any @Screen, @Perspective etc. But could be added, to give physical representation of that unit of modality, with life cycle callbacks - we just haven’t had a need for this yet.
For us, I'd like to have modularity implemented in a way to avoid "the big GWT app compilation" step. Doesn't matter if we ultimately go for "pure modular" approach or "core that invokes modules" approach, the big goal for us is to split frontend build into several projects. Maven as unit of modularity is cool but only for compile-time-known projects. I'd like to try a different approach, as you wrote - give them some physical representation and load them at runtime.
Our plan over 2015 is to use JsType to create a contract for all the things a module needs. We will then compile modules separately against this, with iframe separation, so each Module is loaded as a separate GWT app. This does mean GWT core repetition, a pita, but that atleast gets us started and may be solvable by a custom GWT linker.
Actually, this iframe approach is what we took in oVirt UI plugins! :) So I see that you're approaching modules from GWT perspective, sounds interesting. However, there are already existing JS frameworks and tools that solve modularization (but they come from JS perspective), like RequireJS (AMD) or ES6's module spec. Assuming JS is here to stay as the dominant web UI technology, I'd rather utilize existing ES6 modules than implementing some GWT-specific module system on my own. But let's discuss that in detail next week.
Longer term we’d like to work with GWT team. They now use the Closure compiler, this support symbol tables, and I expect how their incremental compiler works for their super dev mode. We want to achieve two things 1) stop recompilation of maven modules, when aggregated into sub projects. 2) declare apis that cannot be pruned 3) export a symbol table to allow later compilation of runtime extensions against those, without requiring a repetition of the GWT core (i.e. problem with our first attempt).
Very interesting stuff! :)
We will still continue with our polyglot bindings approach, such as with the AngularJS stuff we have done. But I do not see this as the ideal programming model - it hides much of what Errai brings, around event bus, and general java refactoring capabilities. However it is still useful for our customers, who want to write extensions, but do not want to touch or learn GWT.
If we take modular approach, nothing prevents us to implement "root" module in UberFire/Errai and expose high-level API for sub-modules to consume. Sure, GWT/Java brings advantages of Java statically typed language and its development/build tools, I agree. The concept of event bus is also good as it allows decoupling of application components. For me, learning lessons from oVirt UI plugins, I'd rather avoid the "have core app as runtime monolith and just expose some JS API for small extensions customers can do" scenario. I'd rather treat both core and 3rd party modules/extensions on the same level.
Mark
On 5 Nov 2014, at 15:32, Alon Bar-Lev <alonbl@redhat.com> wrote:
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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 <http://www.ovirt.org/File:Ovirt_3.5_-_aaa.pdf>
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);
}
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 :)
Regards, Alon

----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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?
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 } * API for fetching modules, i.e. getModuleByName('xxx') API for exporting module API, i.e. exportApiObject(foo) 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.)
Regards, Alon

----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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.
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...
* 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.
API for exporting module API, i.e. exportApiObject(foo)
not sure why it is needed... once extension is loaded it is available.
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... 1. every configuration at /etc/ovirt-engine/extensions.d and /usr/share/ovirt-engine/extensions.d are loaded during engine startup. 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. 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. Alon

----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 6:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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.
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...
Vojtech, I have to agree with Alon here, as much as I enjoyed in the past seeing hibernate move to annotations , I think in our case a configuration file is better.
* 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.
API for exporting module API, i.e. exportApiObject(foo)
not sure why it is needed... once extension is loaded it is available.
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...
1. every configuration at /etc/ovirt-engine/extensions.d and /usr/share/ovirt-engine/extensions.d are loaded during engine startup.
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.
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.
Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Alon _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 10:40:05 PM Subject: Re: [ovirt-devel] Thoughts on modularization
4. there must be core model to trigger the entire thing, core cannot be just a loader.
Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Well, there is a balance between generic and specific. If you go this route, can the Java JRE be the core you are looking for? The wisdom is to draw the line where the building blocks serves the purpose of building the application you need. Alon

----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Yair Zaslavsky" <yzaslavs@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 10:45:53 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 10:40:05 PM Subject: Re: [ovirt-devel] Thoughts on modularization
4. there must be core model to trigger the entire thing, core cannot be just a loader.
Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Well, there is a balance between generic and specific. If you go this route, can the Java JRE be the core you are looking for?
No, you need some loader/starter to enumerate your extensions and load them. Maybe a thin service that uses ExtensionsManager.
The wisdom is to draw the line where the building blocks serves the purpose of building the application you need.
I agree.
Alon

----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 9:40:05 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 6:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message ----- > From: "Vojtech Szocs" <vszocs@redhat.com> > To: devel@ovirt.org > Cc: "Mark Proctor" <mdproctor@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.
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...
Vojtech, I have to agree with Alon here, as much as I enjoyed in the past seeing hibernate move to annotations , I think in our case a configuration file is better.
I'm not against config files, annotations are static metadata too anyway.
* 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.
API for exporting module API, i.e. exportApiObject(foo)
not sure why it is needed... once extension is loaded it is available.
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...
1. every configuration at /etc/ovirt-engine/extensions.d and /usr/share/ovirt-engine/extensions.d are loaded during engine startup.
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.
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.
Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Alon _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

Hi, I can summarized that you want again to go into the "Java way" and not the "Simple/primitive way". I think it is a mistake and will not have any benefit, "API" can be a wrapper over primitive interaction. We were there at past discussions, and as there is no leader of project we can discuss this to death, and I am not intend to do this yet another time (we have done this at branding, we have done this for aaa, partially for ui plugins [there we should kill gwt], and ...). I will make this short... 1. the current extension api is sufficient to construct a very complex implementation using very simple and primitive interface. 2. the current extension api enable implementing extensions using non java technologies, such as javascript/jpython. 3. the current extension api enable to not have any difference if core or extension interacts with extensions. 4. the current extension api enable forward and backward compatibility in simple methodology,. 5. a wrapper over the extension api can provide whatever high level api that is preferred by developer as an optional utility. we can always over engineer solution or have java specific solutions, I always vote for simplicity. Alon ----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Yair Zaslavsky" <yzaslavs@redhat.com> Cc: "Alon Bar-Lev" <alonbl@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Friday, November 7, 2014 4:53:49 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 9:40:05 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 6:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> > To: "Vojtech Szocs" <vszocs@redhat.com> > Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> > Sent: Wednesday, November 5, 2014 4:12:06 PM > Subject: Re: [ovirt-devel] Thoughts on modularization > > > > ----- Original Message ----- > > From: "Vojtech Szocs" <vszocs@redhat.com> > > To: devel@ovirt.org > > Cc: "Mark Proctor" <mdproctor@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.
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...
Vojtech, I have to agree with Alon here, as much as I enjoyed in the past seeing hibernate move to annotations , I think in our case a configuration file is better.
I'm not against config files, annotations are static metadata too anyway.
* 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.
API for exporting module API, i.e. exportApiObject(foo)
not sure why it is needed... once extension is loaded it is available.
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...
1. every configuration at /etc/ovirt-engine/extensions.d and /usr/share/ovirt-engine/extensions.d are loaded during engine startup.
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.
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.
Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Alon _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: "Yair Zaslavsky" <yzaslavs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Friday, November 7, 2014 5:17:56 PM Subject: Re: [ovirt-devel] Thoughts on modularization
Hi,
I can summarized that you want again to go into the "Java way" and not the "Simple/primitive way". I think it is a mistake and will not have any benefit, "API" can be a wrapper over primitive interaction. We were there at past discussions, and as there is no leader of project we can discuss this to death, and I am not intend to do this yet another time (we have done this at branding, we have done this for aaa, partially for ui plugins [there we should kill gwt], and ...).
I will make this short... 1. the current extension api is sufficient to construct a very complex implementation using very simple and primitive interface. 2. the current extension api enable implementing extensions using non java technologies, such as javascript/jpython. 3. the current extension api enable to not have any difference if core or extension interacts with extensions. 4. the current extension api enable forward and backward compatibility in simple methodology,. 5. a wrapper over the extension api can provide whatever high level api that is preferred by developer as an optional utility.
we can always over engineer solution or have java specific solutions, I always vote for simplicity.
Hmm, I think that going the "Java way" will be a bit "sad", especially since objects in JS are maps. I understand that GWT stuff gets compiled from Java, and since Java is more strongly typed and we have Java classes to work with, Vojtech is looking probably to a solution which is more "the java way". Having said that, I still see no reason why we can't use ExtAPI in GWT, yes, maybe we will need to do some "porting" so it matches the GWT java limitations, and yeah - we cannot use JBoss modules there, we need something else (and we can't use JS either, as JS is the compilation result) - but still, if possible I would consider to try use EXTAPI in GWT as well. Yair
Alon
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Yair Zaslavsky" <yzaslavs@redhat.com> Cc: "Alon Bar-Lev" <alonbl@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Friday, November 7, 2014 4:53:49 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 9:40:05 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 6:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message ----- > From: "Vojtech Szocs" <vszocs@redhat.com> > To: "Alon Bar-Lev" <alonbl@redhat.com> > Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> > > To: "Vojtech Szocs" <vszocs@redhat.com> > > Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> > > Sent: Wednesday, November 5, 2014 4:12:06 PM > > Subject: Re: [ovirt-devel] Thoughts on modularization > > > > > > > > ----- Original Message ----- > > > From: "Vojtech Szocs" <vszocs@redhat.com> > > > To: devel@ovirt.org > > > Cc: "Mark Proctor" <mdproctor@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.
> 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...
Vojtech, I have to agree with Alon here, as much as I enjoyed in the past seeing hibernate move to annotations , I think in our case a configuration file is better.
I'm not against config files, annotations are static metadata too anyway.
* 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.
API for exporting module API, i.e. exportApiObject(foo)
not sure why it is needed... once extension is loaded it is available.
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...
1. every configuration at /etc/ovirt-engine/extensions.d and /usr/share/ovirt-engine/extensions.d are loaded during engine startup.
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.
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.
Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Alon _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

On 11/07/2014 04:53 PM, Vojtech Szocs wrote:
----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Vojtech Szocs" <vszocs@redhat.com>, "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 9:40:05 PM Subject: Re: [ovirt-devel] Thoughts on modularization
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: "Mark Proctor" <mdproctor@gmail.com>, devel@ovirt.org Sent: Wednesday, November 5, 2014 6:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> > To: "Vojtech Szocs" <vszocs@redhat.com> > Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> > Sent: Wednesday, November 5, 2014 4:12:06 PM > Subject: Re: [ovirt-devel] Thoughts on modularization > > > > ----- Original Message ----- >> From: "Vojtech Szocs" <vszocs@redhat.com> >> To: devel@ovirt.org >> Cc: "Mark Proctor" <mdproctor@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.
----- Original Message ----- 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.
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... Vojtech, I have to agree with Alon here, as much as I enjoyed in the past seeing hibernate move to annotations , I
----- Original Message ----- think in our case a configuration file is better. I'm not against config files, annotations are static metadata too anyway.
correct and CDI has both abilities - annotation and XML configuration some of the things you are talking about here is established for long time using jboss-osgi btw. will dig for examples for OSGI & CDI interactions as I seen few .
* 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.
API for exporting module API, i.e. exportApiObject(foo) not sure why it is needed... once extension is loaded it is available.
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...
1. every configuration at /etc/ovirt-engine/extensions.d and /usr/share/ovirt-engine/extensions.d are loaded during engine startup.
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.
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. Alon, can you elaborate here on number 4? In an ideal world, wouldn't you want to have the "engine core" be a small as something that goes over the extensions and loads them? and maybe let each extension expose somehow its relevant part of rest-api (besides of using ext-api to interact between extension and of course each extension should have the relevant logic implementerd within)
Alon _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel
Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

----- Original Message -----
From: "Alon Bar-Lev" <alonbl@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 5:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: devel@ovirt.org Cc: "Mark Proctor" <mdproctor@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.
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

----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: "Mark Proctor" <mdproctor@gmail.com>, devel@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 5:16:15 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:32:31 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Vojtech Szocs" <vszocs@redhat.com> To: "Alon Bar-Lev" <alonbl@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@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@redhat.com> To: "Vojtech Szocs" <vszocs@redhat.com> Cc: devel@ovirt.org, "Mark Proctor" <mdproctor@gmail.com> Sent: Wednesday, November 5, 2014 4:12:06 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message ----- > From: "Vojtech Szocs" <vszocs@redhat.com> > To: devel@ovirt.org > Cc: "Mark Proctor" <mdproctor@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@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

On 05/11/14 17:07, Vojtech Szocs wrote:
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 :)
Welcome to dependency hell or circular dependencies etc. would you like to code your own dependency resolver? I like modularization, but you can overengineer everything. -- Mit freundlichen Grüßen / Regards Sven Kieske Systemadministrator Mittwald CM Service GmbH & Co. KG Königsberger Straße 6 32339 Espelkamp T: +49-5772-293-100 F: +49-5772-293-333 https://www.mittwald.de Geschäftsführer: Robert Meyer St.Nr.: 331/5721/1033, USt-IdNr.: DE814773217, HRA 6640, AG Bad Oeynhausen Komplementärin: Robert Meyer Verwaltungs GmbH, HRB 13260, AG Bad Oeynhausen

----- Original Message -----
From: "Sven Kieske" <s.kieske@mittwald.de> To: devel@ovirt.org Sent: Wednesday, November 5, 2014 6:36:39 PM Subject: Re: [ovirt-devel] Thoughts on modularization
On 05/11/14 17:07, Vojtech Szocs wrote:
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 :)
Welcome to dependency hell or circular dependencies etc.
would you like to code your own dependency resolver?
I assume dependency resolving can be based on Topological sorting of Graph theory. I assume the extensions that will participate as nodes in the graph will be those who are enabled in their configuration
I like modularization, but you can overengineer everything.
-- Mit freundlichen Grüßen / Regards
Sven Kieske
Systemadministrator Mittwald CM Service GmbH & Co. KG Königsberger Straße 6 32339 Espelkamp T: +49-5772-293-100 F: +49-5772-293-333 https://www.mittwald.de Geschäftsführer: Robert Meyer St.Nr.: 331/5721/1033, USt-IdNr.: DE814773217, HRA 6640, AG Bad Oeynhausen Komplementärin: Robert Meyer Verwaltungs GmbH, HRB 13260, AG Bad Oeynhausen _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

----- Original Message -----
From: "Yair Zaslavsky" <yzaslavs@redhat.com> To: "Sven Kieske" <s.kieske@mittwald.de> Cc: devel@ovirt.org Sent: Wednesday, November 5, 2014 9:34:20 PM Subject: Re: [ovirt-devel] Thoughts on modularization
----- Original Message -----
From: "Sven Kieske" <s.kieske@mittwald.de> To: devel@ovirt.org Sent: Wednesday, November 5, 2014 6:36:39 PM Subject: Re: [ovirt-devel] Thoughts on modularization
On 05/11/14 17:07, Vojtech Szocs wrote:
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 :)
Welcome to dependency hell or circular dependencies etc.
would you like to code your own dependency resolver?
I assume dependency resolving can be based on Topological sorting of Graph theory. I assume the extensions that will participate as nodes in the graph will be those who are enabled in their configuration
Exactly :)
I like modularization, but you can overengineer everything.
-- Mit freundlichen Grüßen / Regards
Sven Kieske
Systemadministrator Mittwald CM Service GmbH & Co. KG Königsberger Straße 6 32339 Espelkamp T: +49-5772-293-100 F: +49-5772-293-333 https://www.mittwald.de Geschäftsführer: Robert Meyer St.Nr.: 331/5721/1033, USt-IdNr.: DE814773217, HRA 6640, AG Bad Oeynhausen Komplementärin: Robert Meyer Verwaltungs GmbH, HRB 13260, AG Bad Oeynhausen _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel
_______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel

----- Original Message -----
From: "Sven Kieske" <s.kieske@mittwald.de> To: devel@ovirt.org Sent: Wednesday, November 5, 2014 5:36:39 PM Subject: Re: [ovirt-devel] Thoughts on modularization
On 05/11/14 17:07, Vojtech Szocs wrote:
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 :)
Welcome to dependency hell or circular dependencies etc.
Just because the problem of circular dependencies exists, doesn't mean we shouldn't try to build systems utilizing dependencies. It can be solved/addressed. "Division by zero" is a known problem in integral arithmetic, but it doesn't prevent calculator manufacturers from producing simple calculators, right?
would you like to code your own dependency resolver?
No, I'd like to use what's already available. http://requirejs.org/ http://www.2ality.com/2014/09/es6-modules-final.html
I like modularization, but you can overengineer everything.
I don't consider modular architecture as over-engineering. If we define modules on reasonable level of granularity, the end result might be better than one big monolithic GWT application.
-- Mit freundlichen Grüßen / Regards
Sven Kieske
Systemadministrator Mittwald CM Service GmbH & Co. KG Königsberger Straße 6 32339 Espelkamp T: +49-5772-293-100 F: +49-5772-293-333 https://www.mittwald.de Geschäftsführer: Robert Meyer St.Nr.: 331/5721/1033, USt-IdNr.: DE814773217, HRA 6640, AG Bad Oeynhausen Komplementärin: Robert Meyer Verwaltungs GmbH, HRB 13260, AG Bad Oeynhausen _______________________________________________ Devel mailing list Devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/devel
participants (6)
-
Alon Bar-Lev
-
Mark Proctor
-
Roy Golan
-
Sven Kieske
-
Vojtech Szocs
-
Yair Zaslavsky