You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by Christian Schneider <ch...@die-schneider.net> on 2014/11/10 11:40:34 UTC

Make DependencyManager API more fluent?

I wonder if the DependencyManager API could be made a bit more fluent. 
Technically it already uses the fluent builder pattern
but all the builder verbs still look a lot like traditional setters.

I know what I propose is mostly syntactic sugar but I think the result 
looks more readable and crisp. See below for some ideas.

Christian

----

This is from samples.dependonservice:
     public void init(BundleContext context, DependencyManager manager) 
throws Exception {
         manager.add(createComponent()
             .setImplementation(DataGenerator.class)
             .add(createServiceDependency()
                 .setService(Store.class)
                 .setRequired(true)
             )
             .add(createServiceDependency()
                 .setService(LogService.class)
                 .setRequired(false)
             )
         );
     }

Why not make it look like this:
     public void init(BundleContext context, DependencyManager manager) 
throws Exception {
         component()
             .implementation(DataGenerator.class)
             .add(serviceDependency(Store.class).required())
             .add(serviceDependency(LogService.class))
             );
         );
     }

component() could create and add the component.

Or for configuration:
     public void init(BundleContext context, DependencyManager manager) 
throws Exception {
         manager.add(createComponent()
             .setImplementation(Task.class)
             .add(createConfigurationDependency()
                 .setPid("config.pid")
                 // The following is optional and allows to display our 
configuration from webconsole
                 .setHeading("Task Configuration")
                 .setDescription("Configuration for the Task Service")
                 .add(createPropertyMetaData()
                      .setCardinality(0)
                      .setType(String.class)
                      .setHeading("Task Interval")
                      .setDescription("Declare here the interval used to 
trigger the Task")
                      .setDefaults(new String[] {"10"})
                      .setId("interval"))));
     }

could be:
     public void init(BundleContext context, DependencyManager manager) 
throws Exception {
         component().implementation(Task.class)
             .configuration("config.pid")
                 .add(meta("Task Configuration)
                     .description("Configuration for the Task Service")
                     .add(property("interval")
                             .cardinality(0)
                             .type(String.class)
                             .heading("Task Interval")
                             .description("Declare here the interval 
used to trigger the Task")
                             .default("10"))
     }

-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
http://www.talend.com


Re: Make DependencyManager API more fluent?

Posted by Marcel Offermans <ma...@luminis.eu>.
Hello Christian,

> On 11 Nov 2014, at 9:22 am, Christian Schneider <ch...@die-schneider.net> wrote:
> 
> About auto adding. How about this:
> Inside component() we add the component to a separate list of pending components in dependency manager.
> Then after init we call a method in the manager to finally add all pending components into the active structure.
> In that method we could then also convert from the class with the new syntax to the existing class. So the changes for the new syntax would have
> minimal impact to the rest of the code.

The problem with this approach is that the API can be used outside of the init method as well, so I don’t like adding code that only works in a specific scenario.

Greetings, Marcel
  

Re: Make DependencyManager API more fluent?

Posted by Christian Schneider <ch...@die-schneider.net>.
Sounds good to me. For me it is not time critical so I can wait till you 
signal me that the code is in good shape.

Christian


On 12.11.2014 09:14, Pierre De Rop wrote:
> Hello Christian,
>
> We could indeed deprecate all the setters methods, and introduce your
> proposed builder methods. And I do agree that we could also manage to let
> the new DependencyActivatorBase.component() method maintain the list of
> created components, and we could then auto-add all the created components
> in the DependencyManager object once the DependencyActivatorBase.init()
> method returns.
>
> So, let's continue to discuss with Marcel about all of this in the jira
> issue you have created, and we also have to think about what Paul is
> proposing.
>
> For your information, the code from felix-trunk/dependencymanager is out
> dated, and I'm working since several months on a new DM 4.0.0 version,
> which is currently in [1].
> We are using a new thread model which is described in [2] and in the
> presentation I recently added in [3] (see the "what's new in DM 4.0"
> section at the end of the presentation)
>
> For now the code is still unstable and I need some more time to finalize
> the API (one week I think).
> And then once finalized (I will email), then you could try to attach a
> patch in the jira issue (but on the sandbox codebase). This will help
> Marcel to decide.
>
> Cheers;
> /Pierre
>

-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
http://www.talend.com


Re: Make DependencyManager API more fluent?

Posted by Pierre De Rop <pi...@gmail.com>.
Hello Christian,

We could indeed deprecate all the setters methods, and introduce your
proposed builder methods. And I do agree that we could also manage to let
the new DependencyActivatorBase.component() method maintain the list of
created components, and we could then auto-add all the created components
in the DependencyManager object once the DependencyActivatorBase.init()
method returns.

So, let's continue to discuss with Marcel about all of this in the jira
issue you have created, and we also have to think about what Paul is
proposing.

For your information, the code from felix-trunk/dependencymanager is out
dated, and I'm working since several months on a new DM 4.0.0 version,
which is currently in [1].
We are using a new thread model which is described in [2] and in the
presentation I recently added in [3] (see the "what's new in DM 4.0"
section at the end of the presentation)

For now the code is still unstable and I need some more time to finalize
the API (one week I think).
And then once finalized (I will email), then you could try to attach a
patch in the jira issue (but on the sandbox codebase). This will help
Marcel to decide.

Cheers;
/Pierre

[1]
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/
[2]
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/design.txt
[3]
http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/doc/A_Glance_At_DependencyManager.odp

On Tue, Nov 11, 2014 at 9:22 AM, Christian Schneider <
chris@die-schneider.net> wrote:

> Hi Pierre,
>
> I think we can and should do this without a major version bump.
> We could simply add the new builders and keep the old ones in parallel in
> deprecated status.
> This would allow people some time to switch to the new syntax. For the
> major version we can then later remove the deprecated syntax.
>
> About auto adding. How about this:
> Inside component() we add the component to a separate list of pending
> components in dependency manager.
> Then after init we call a method in the manager to finally add all pending
> components into the active structure.
> In that method we could then also convert from the class with the new
> syntax to the existing class. So the changes for the new syntax would have
> minimal impact to the rest of the code.
>
> I created an issue for this:
> https://issues.apache.org/jira/browse/FELIX-4689
>
> As I would like to work on becoming a felix committer in the long term I
> would ideally like to work this out and create a patch for the issue. If
> you prefer to do it yourself I am also fine of course. In any case I agree
> that we should first wait for feedback from Marcel.
>
> Christian
>
>
> On 11.11.2014 00:39, Pierre De Rop wrote:
>
>> Hello Christian;
>>
>> The improvements you are proposing would require a major version bump
>> since
>> it's an incompatible API change. But I personally like what you are
>> suggesting, and I could quickly do it in the upcoming Dependency Manager
>> 4.0.0, which is a new major version.
>>
>> But before, I need to know if Marcel is agree to go ahead with all this;
>> so
>> for the moment, may be you can just create a Jira issue, and let's wait
>> for
>> Marcel to see if he's OK.
>>
>> Just one remark: the setters can be easily removed, however I think we
>> can't manage to make the "component()" method automatically add the
>> Component to the DependencyManager, because technically; when you add a
>> Component to a DependencyManager, the Component is actually *activated*,
>> and at this point, all the necessary dependencies have to be already in
>> place.
>>
>> So, the only possible improvement I'm thinking about for now could have
>> the
>> form of this:
>>
>>      public void init(BundleContext context, DependencyManager manager)
>> throws Exception {
>>          component()
>>              .implementation(DataGenerator.class)
>>              .add(serviceDependency(Store.class).required())
>>              .add(serviceDependency(LogService.class))
>>              .addTo(manager);
>>      }
>>
>> (notice the addTo method at the end of the sample above, which could just
>> add the fully built component to the DependencyManager "manager" object).
>>
>> but I propose you first create the Jira issue and see what Marcel thinks.
>>
>> I will possible add more suggestions in your Jira issue once you will have
>> created it (like also using a builder pattern for the aspects/adapters:
>> this would allow to reduce the number of method signatures for the
>> createAdapter/createAspect methods).
>>
>> kind regards (and thanks for proposing to improve Dependency Manager :-))
>>
>> /Pierre
>>
>> On Mon, Nov 10, 2014 at 11:40 AM, Christian Schneider <
>> chris@die-schneider.net> wrote:
>>
>>  I wonder if the DependencyManager API could be made a bit more fluent.
>>> Technically it already uses the fluent builder pattern
>>> but all the builder verbs still look a lot like traditional setters.
>>>
>>> I know what I propose is mostly syntactic sugar but I think the result
>>> looks more readable and crisp. See below for some ideas.
>>>
>>> Christian
>>>
>>> ----
>>>
>>> This is from samples.dependonservice:
>>>      public void init(BundleContext context, DependencyManager manager)
>>> throws Exception {
>>>          manager.add(createComponent()
>>>              .setImplementation(DataGenerator.class)
>>>              .add(createServiceDependency()
>>>                  .setService(Store.class)
>>>                  .setRequired(true)
>>>              )
>>>              .add(createServiceDependency()
>>>                  .setService(LogService.class)
>>>                  .setRequired(false)
>>>              )
>>>          );
>>>      }
>>>
>>> Why not make it look like this:
>>>      public void init(BundleContext context, DependencyManager manager)
>>> throws Exception {
>>>          component()
>>>              .implementation(DataGenerator.class)
>>>              .add(serviceDependency(Store.class).required())
>>>              .add(serviceDependency(LogService.class))
>>>              );
>>>          );
>>>      }
>>>
>>> component() could create and add the component.
>>>
>>> Or for configuration:
>>>      public void init(BundleContext context, DependencyManager manager)
>>> throws Exception {
>>>          manager.add(createComponent()
>>>              .setImplementation(Task.class)
>>>              .add(createConfigurationDependency()
>>>                  .setPid("config.pid")
>>>                  // The following is optional and allows to display our
>>> configuration from webconsole
>>>                  .setHeading("Task Configuration")
>>>                  .setDescription("Configuration for the Task Service")
>>>                  .add(createPropertyMetaData()
>>>                       .setCardinality(0)
>>>                       .setType(String.class)
>>>                       .setHeading("Task Interval")
>>>                       .setDescription("Declare here the interval used to
>>> trigger the Task")
>>>                       .setDefaults(new String[] {"10"})
>>>                       .setId("interval"))));
>>>      }
>>>
>>> could be:
>>>      public void init(BundleContext context, DependencyManager manager)
>>> throws Exception {
>>>          component().implementation(Task.class)
>>>              .configuration("config.pid")
>>>                  .add(meta("Task Configuration)
>>>                      .description("Configuration for the Task Service")
>>>                      .add(property("interval")
>>>                              .cardinality(0)
>>>                              .type(String.class)
>>>                              .heading("Task Interval")
>>>                              .description("Declare here the interval used
>>> to trigger the Task")
>>>                              .default("10"))
>>>      }
>>>
>>> --
>>> Christian Schneider
>>> http://www.liquid-reality.de
>>>
>>> Open Source Architect
>>> http://www.talend.com
>>>
>>>
>>>
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> http://www.talend.com
>
>

Re: Make DependencyManager API more fluent?

Posted by Christian Schneider <ch...@die-schneider.net>.
Hi Pierre,

I think we can and should do this without a major version bump.
We could simply add the new builders and keep the old ones in parallel 
in deprecated status.
This would allow people some time to switch to the new syntax. For the 
major version we can then later remove the deprecated syntax.

About auto adding. How about this:
Inside component() we add the component to a separate list of pending 
components in dependency manager.
Then after init we call a method in the manager to finally add all 
pending components into the active structure.
In that method we could then also convert from the class with the new 
syntax to the existing class. So the changes for the new syntax would have
minimal impact to the rest of the code.

I created an issue for this:
https://issues.apache.org/jira/browse/FELIX-4689

As I would like to work on becoming a felix committer in the long term I 
would ideally like to work this out and create a patch for the issue. If 
you prefer to do it yourself I am also fine of course. In any case I 
agree that we should first wait for feedback from Marcel.

Christian

On 11.11.2014 00:39, Pierre De Rop wrote:
> Hello Christian;
>
> The improvements you are proposing would require a major version bump since
> it's an incompatible API change. But I personally like what you are
> suggesting, and I could quickly do it in the upcoming Dependency Manager
> 4.0.0, which is a new major version.
>
> But before, I need to know if Marcel is agree to go ahead with all this; so
> for the moment, may be you can just create a Jira issue, and let's wait for
> Marcel to see if he's OK.
>
> Just one remark: the setters can be easily removed, however I think we
> can't manage to make the "component()" method automatically add the
> Component to the DependencyManager, because technically; when you add a
> Component to a DependencyManager, the Component is actually *activated*,
> and at this point, all the necessary dependencies have to be already in
> place.
>
> So, the only possible improvement I'm thinking about for now could have the
> form of this:
>
>      public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>          component()
>              .implementation(DataGenerator.class)
>              .add(serviceDependency(Store.class).required())
>              .add(serviceDependency(LogService.class))
>              .addTo(manager);
>      }
>
> (notice the addTo method at the end of the sample above, which could just
> add the fully built component to the DependencyManager "manager" object).
>
> but I propose you first create the Jira issue and see what Marcel thinks.
>
> I will possible add more suggestions in your Jira issue once you will have
> created it (like also using a builder pattern for the aspects/adapters:
> this would allow to reduce the number of method signatures for the
> createAdapter/createAspect methods).
>
> kind regards (and thanks for proposing to improve Dependency Manager :-))
>
> /Pierre
>
> On Mon, Nov 10, 2014 at 11:40 AM, Christian Schneider <
> chris@die-schneider.net> wrote:
>
>> I wonder if the DependencyManager API could be made a bit more fluent.
>> Technically it already uses the fluent builder pattern
>> but all the builder verbs still look a lot like traditional setters.
>>
>> I know what I propose is mostly syntactic sugar but I think the result
>> looks more readable and crisp. See below for some ideas.
>>
>> Christian
>>
>> ----
>>
>> This is from samples.dependonservice:
>>      public void init(BundleContext context, DependencyManager manager)
>> throws Exception {
>>          manager.add(createComponent()
>>              .setImplementation(DataGenerator.class)
>>              .add(createServiceDependency()
>>                  .setService(Store.class)
>>                  .setRequired(true)
>>              )
>>              .add(createServiceDependency()
>>                  .setService(LogService.class)
>>                  .setRequired(false)
>>              )
>>          );
>>      }
>>
>> Why not make it look like this:
>>      public void init(BundleContext context, DependencyManager manager)
>> throws Exception {
>>          component()
>>              .implementation(DataGenerator.class)
>>              .add(serviceDependency(Store.class).required())
>>              .add(serviceDependency(LogService.class))
>>              );
>>          );
>>      }
>>
>> component() could create and add the component.
>>
>> Or for configuration:
>>      public void init(BundleContext context, DependencyManager manager)
>> throws Exception {
>>          manager.add(createComponent()
>>              .setImplementation(Task.class)
>>              .add(createConfigurationDependency()
>>                  .setPid("config.pid")
>>                  // The following is optional and allows to display our
>> configuration from webconsole
>>                  .setHeading("Task Configuration")
>>                  .setDescription("Configuration for the Task Service")
>>                  .add(createPropertyMetaData()
>>                       .setCardinality(0)
>>                       .setType(String.class)
>>                       .setHeading("Task Interval")
>>                       .setDescription("Declare here the interval used to
>> trigger the Task")
>>                       .setDefaults(new String[] {"10"})
>>                       .setId("interval"))));
>>      }
>>
>> could be:
>>      public void init(BundleContext context, DependencyManager manager)
>> throws Exception {
>>          component().implementation(Task.class)
>>              .configuration("config.pid")
>>                  .add(meta("Task Configuration)
>>                      .description("Configuration for the Task Service")
>>                      .add(property("interval")
>>                              .cardinality(0)
>>                              .type(String.class)
>>                              .heading("Task Interval")
>>                              .description("Declare here the interval used
>> to trigger the Task")
>>                              .default("10"))
>>      }
>>
>> --
>> Christian Schneider
>> http://www.liquid-reality.de
>>
>> Open Source Architect
>> http://www.talend.com
>>
>>


-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
http://www.talend.com


Re: Make DependencyManager API more fluent?

Posted by Marcel Offermans <ma...@luminis.nl>.
Hello Christian,

On 13 Nov 2014 at 14:16:01 , Christian Schneider (chris@die-schneider.net) wrote:

I very much like the idea of a separate builder class. It will make the 
transition very smooth. We can also package it in an extra bundle but I 
do not think there is a technical need for it. So I propose to simply 
add the new syntax in a separate package.
I agree there is no need for it, but in general we do so to keep things modular. :) That’s why, for example, we’ve also separated the runtime (that acts on annotations after they have been processed and converted into json metadata) and some of the other components. So I do have a slight preference to keep things separate, but it’s not a decision we need to make upfront so let’s first make sure we have a good implementation!

if we want to remove the old syntax at some point then we have to do 
this in a major version. So as 4.0 is quite near we might aim at this 
for 5.0.
Agreed, for now the focus is on getting ready for 4.0, and new builders (and some other ideas we have now) can be done as minor updates.

We do not need to introduce the new API (if we keep the old one 
unchanged) in a major version. It is not a breaking change so I think it 
can be introduced in any minor version. Of course we can do it in 
version 4.0 but there is no technical need for it.
Agreed.

Btw. I am at apachecon next week. Would be great if we could take the 
chance to meet in person. 
That’s an excellent idea!

Greetings, Marcel




Re: Make DependencyManager API more fluent?

Posted by Pierre De Rop <pi...@gmail.com>.
Hello Christian;

Just to say that if you start to work on the new API, I would like to avoid
to commit anything in the old 3.2 codebase (felix-trunk/dependencymanager)
because it will be overriden very soon by the new 4.0.0 major version,
which is currently in my sandbox (everything has changed).

but, as explained previously, I still need to fix some stuff in the API, so
the API is still unstable but I plan to commit this WE.
I will email when the API will become stable.

kind regards;
/Pierre

On Thu, Nov 13, 2014 at 8:57 AM, Christian Schneider <
chris@die-schneider.net> wrote:

> Hi Marcel,
>
> I very much like the idea of a separate builder class. It will make the
> transition very smooth. We can also package it in an extra bundle but I do
> not think there is a technical need for it. So I propose to simply add the
> new syntax in a separate package.
>
> if we want to remove the old syntax at some point then we have to do this
> in a major version. So as 4.0 is quite near we might aim at this for 5.0.
>
> We do not need to introduce the new API (if we keep the old one unchanged)
> in a major version. It is not a breaking change so I think it can be
> introduced in any minor version. Of course we can do it in version 4.0 but
> there is no technical need for it.
>
> Btw. I am at apachecon next week. Would be great if we could take the
> chance to meet in person.
>
> Christian
>
>
>
>
> On 12.11.2014 23:15, Marcel Offermans wrote:
>
>> Hey all,
>>
>>  On 11 Nov 2014, at 0:39 am, Pierre De Rop <pi...@gmail.com>
>>> wrote:
>>>
>>> The improvements you are proposing would require a major version bump
>>> since
>>> it's an incompatible API change. But I personally like what you are
>>> suggesting, and I could quickly do it in the upcoming Dependency Manager
>>> 4.0.0, which is a new major version.
>>>
>> Agreed, we cannot introduce something like this any sooner than in
>> version 4. However, it is probably not too hard to implement this yourself
>> on top of the current release either, since 80% of what Christian is
>> proposing is just renaming existing methods:
>>
>> If you create your own version of DependencyManagerBase and also wrap
>> classes like Component and ServiceDependency/ConfigurationDependency it
>> is quite straightforward to delegate from your new set of methods to the
>> existing ones.
>>
>> This goes in the direction that Paul proposes as well with the builder
>> class.
>>
>>  But before, I need to know if Marcel is agree to go ahead with all this;
>>> so
>>> for the moment, may be you can just create a Jira issue, and let's wait
>>> for
>>> Marcel to see if he's OK.
>>>
>> I am fairly neutral on this.
>>
>> Yes, the proposed methods are better aligned with most fluent APIs.
>> However, two downsides I see is that it does break the existing API, making
>> it harder for people to migrate to version 4 (and, for various reasons,
>> they should do that). Also, you are not required to use the fluent style,
>> in some cases you end up invoking individual setter methods on DM
>> components and in those cases, the fluent style methods might look a bit
>> strange.
>>
>> Because of this, maybe we should explore the separate builder class that
>> Paul suggested!?
>>
>>  Just one remark: the setters can be easily removed, however I think we
>>> can't manage to make the "component()" method automatically add the
>>> Component to the DependencyManager, because technically; when you add a
>>> Component to a DependencyManager, the Component is actually *activated*,
>>> and at this point, all the necessary dependencies have to be already in
>>> place.
>>>
>> Yes, and there are a few other scenarios as well where you don’t want to
>> combine creating and adding a component, so I think we should leave that
>> part alone.
>>
>>  So, the only possible improvement I'm thinking about for now could have
>>> the
>>> form of this:
>>>
>>>     public void init(BundleContext context, DependencyManager manager)
>>> throws Exception {
>>>         component()
>>>             .implementation(DataGenerator.class)
>>>             .add(serviceDependency(Store.class).required())
>>>             .add(serviceDependency(LogService.class))
>>>             .addTo(manager);
>>>     }
>>>
>>> (notice the addTo method at the end of the sample above, which could just
>>> add the fully built component to the DependencyManager "manager" object).
>>>
>> I don’t think that makes the code better. You still have two calls (one
>> to create, one to add) and if you forget the addTo(…) it will probably
>> still be hard to spot that that was the “bug”.
>>
>>  but I propose you first create the Jira issue and see what Marcel thinks.
>>>
>>> I will possible add more suggestions in your Jira issue once you will
>>> have
>>> created it (like also using a builder pattern for the aspects/adapters:
>>> this would allow to reduce the number of method signatures for the
>>> createAdapter/createAspect methods).
>>>
>>> kind regards (and thanks for proposing to improve Dependency Manager :-))
>>>
>> Agreed, this is a good discussion, thanks for the input!
>>
>> Greetings, Marcel
>>
>
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> http://www.talend.com
>
>

Re: Make DependencyManager API more fluent?

Posted by Christian Schneider <ch...@die-schneider.net>.
Hi Marcel,

I very much like the idea of a separate builder class. It will make the 
transition very smooth. We can also package it in an extra bundle but I 
do not think there is a technical need for it. So I propose to simply 
add the new syntax in a separate package.

if we want to remove the old syntax at some point then we have to do 
this in a major version. So as 4.0 is quite near we might aim at this 
for 5.0.

We do not need to introduce the new API (if we keep the old one 
unchanged) in a major version. It is not a breaking change so I think it 
can be introduced in any minor version. Of course we can do it in 
version 4.0 but there is no technical need for it.

Btw. I am at apachecon next week. Would be great if we could take the 
chance to meet in person.

Christian



On 12.11.2014 23:15, Marcel Offermans wrote:
> Hey all,
>
>> On 11 Nov 2014, at 0:39 am, Pierre De Rop <pi...@gmail.com> wrote:
>>
>> The improvements you are proposing would require a major version bump since
>> it's an incompatible API change. But I personally like what you are
>> suggesting, and I could quickly do it in the upcoming Dependency Manager
>> 4.0.0, which is a new major version.
> Agreed, we cannot introduce something like this any sooner than in version 4. However, it is probably not too hard to implement this yourself on top of the current release either, since 80% of what Christian is proposing is just renaming existing methods:
>
> If you create your own version of DependencyManagerBase and also wrap classes like Component and ServiceDependency/ConfigurationDependency it is quite straightforward to delegate from your new set of methods to the existing ones.
>
> This goes in the direction that Paul proposes as well with the builder class.
>
>> But before, I need to know if Marcel is agree to go ahead with all this; so
>> for the moment, may be you can just create a Jira issue, and let's wait for
>> Marcel to see if he's OK.
> I am fairly neutral on this.
>
> Yes, the proposed methods are better aligned with most fluent APIs. However, two downsides I see is that it does break the existing API, making it harder for people to migrate to version 4 (and, for various reasons, they should do that). Also, you are not required to use the fluent style, in some cases you end up invoking individual setter methods on DM components and in those cases, the fluent style methods might look a bit strange.
>
> Because of this, maybe we should explore the separate builder class that Paul suggested!?
>
>> Just one remark: the setters can be easily removed, however I think we
>> can't manage to make the "component()" method automatically add the
>> Component to the DependencyManager, because technically; when you add a
>> Component to a DependencyManager, the Component is actually *activated*,
>> and at this point, all the necessary dependencies have to be already in
>> place.
> Yes, and there are a few other scenarios as well where you don’t want to combine creating and adding a component, so I think we should leave that part alone.
>
>> So, the only possible improvement I'm thinking about for now could have the
>> form of this:
>>
>>     public void init(BundleContext context, DependencyManager manager)
>> throws Exception {
>>         component()
>>             .implementation(DataGenerator.class)
>>             .add(serviceDependency(Store.class).required())
>>             .add(serviceDependency(LogService.class))
>>             .addTo(manager);
>>     }
>>
>> (notice the addTo method at the end of the sample above, which could just
>> add the fully built component to the DependencyManager "manager" object).
> I don’t think that makes the code better. You still have two calls (one to create, one to add) and if you forget the addTo(…) it will probably still be hard to spot that that was the “bug”.
>
>> but I propose you first create the Jira issue and see what Marcel thinks.
>>
>> I will possible add more suggestions in your Jira issue once you will have
>> created it (like also using a builder pattern for the aspects/adapters:
>> this would allow to reduce the number of method signatures for the
>> createAdapter/createAspect methods).
>>
>> kind regards (and thanks for proposing to improve Dependency Manager :-))
> Agreed, this is a good discussion, thanks for the input!
>
> Greetings, Marcel


-- 
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
http://www.talend.com


Re: Make DependencyManager API more fluent?

Posted by Marcel Offermans <ma...@luminis.eu>.
Hey all,

> On 11 Nov 2014, at 0:39 am, Pierre De Rop <pi...@gmail.com> wrote:
> 
> The improvements you are proposing would require a major version bump since
> it's an incompatible API change. But I personally like what you are
> suggesting, and I could quickly do it in the upcoming Dependency Manager
> 4.0.0, which is a new major version.

Agreed, we cannot introduce something like this any sooner than in version 4. However, it is probably not too hard to implement this yourself on top of the current release either, since 80% of what Christian is proposing is just renaming existing methods:

If you create your own version of DependencyManagerBase and also wrap classes like Component and ServiceDependency/ConfigurationDependency it is quite straightforward to delegate from your new set of methods to the existing ones.

This goes in the direction that Paul proposes as well with the builder class.

> But before, I need to know if Marcel is agree to go ahead with all this; so
> for the moment, may be you can just create a Jira issue, and let's wait for
> Marcel to see if he's OK.

I am fairly neutral on this.

Yes, the proposed methods are better aligned with most fluent APIs. However, two downsides I see is that it does break the existing API, making it harder for people to migrate to version 4 (and, for various reasons, they should do that). Also, you are not required to use the fluent style, in some cases you end up invoking individual setter methods on DM components and in those cases, the fluent style methods might look a bit strange.

Because of this, maybe we should explore the separate builder class that Paul suggested!?

> Just one remark: the setters can be easily removed, however I think we
> can't manage to make the "component()" method automatically add the
> Component to the DependencyManager, because technically; when you add a
> Component to a DependencyManager, the Component is actually *activated*,
> and at this point, all the necessary dependencies have to be already in
> place.

Yes, and there are a few other scenarios as well where you don’t want to combine creating and adding a component, so I think we should leave that part alone. 

> So, the only possible improvement I'm thinking about for now could have the
> form of this:
> 
>    public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>        component()
>            .implementation(DataGenerator.class)
>            .add(serviceDependency(Store.class).required())
>            .add(serviceDependency(LogService.class))
>            .addTo(manager);
>    }
> 
> (notice the addTo method at the end of the sample above, which could just
> add the fully built component to the DependencyManager "manager" object).

I don’t think that makes the code better. You still have two calls (one to create, one to add) and if you forget the addTo(…) it will probably still be hard to spot that that was the “bug”. 

> but I propose you first create the Jira issue and see what Marcel thinks.
> 
> I will possible add more suggestions in your Jira issue once you will have
> created it (like also using a builder pattern for the aspects/adapters:
> this would allow to reduce the number of method signatures for the
> createAdapter/createAspect methods).
> 
> kind regards (and thanks for proposing to improve Dependency Manager :-))

Agreed, this is a good discussion, thanks for the input!

Greetings, Marcel

Re: Make DependencyManager API more fluent?

Posted by Marcel Offermans <ma...@luminis.eu>.
Hey Paul,

> On 11 Nov 2014, at 8:55 am, Paul Bakker <pa...@luminis.eu> wrote:
> 
> One thing to consider is that although DM 4 is a major version bump, it so
> far seems to be very close to a drop-in replacement of DM 3. Changing the
> API itself would break all existing code. This is technically ok for a
> major version, but will make adoption of the new version a lot slower.

So far our approach has been to fix the things we really wanted to fix but leave everything we don’t need to change as is, exactly because of the reason you mention. We want people to move to the new release as painless as possible.  

> On the other hand, I do like the proposal :-) Maybe it's possible to add a
> new API, while keeping the existing one. E.g. introduce a builder class
> specifically for this reason, user can than gradually move towards the new
> API. Potentially there could even be builders for multiple JVM languages,
> leveraging the DSL functionality of language Groovy etc.

I like this suggestion, like I stated in my previous mail it might require wrapping a few classes but it’s definitely doable and probably a good way to get some experience under our belts with this approach.

Greetings, Marcel
 

Re: Make DependencyManager API more fluent?

Posted by Paul Bakker <pa...@luminis.eu>.
Hi Pierre,

Don't worry, I don't think it's a problem at all if some things changed.
It's a huge new release after all! I was only suggesting that we shouldn't
get rid of the component registration API completely in favour of a better
API. For the methods that don't longer exist etc. I don't see much problem,
this are more special cases anyway.

I know about the new threading mechanism btw, very good stuff :-)

Cheers,

Paul

On Wed, Nov 12, 2014 at 9:13 AM, Pierre De Rop <pi...@gmail.com>
wrote:

> Hello Paul,
>
> indeed, the DM4 code is very close to the old 3.2 API, and it would be
> unfortunate if breaking the API too much would make slower the adoption of
> the new version.
> I gave immense effort to bring to life the new thread model introduced by
> Marcel and Xander, and now we also have a nice actor thread model allowing
> concurrent activation of Components while staying "single threaded"
> internally ...
> so I will check what has changed in the new 4.0 API and will manage to make
> it closer to the old 3.2 API as much as possible (but some methods have
> been removed, like the setInstanceBound method, for example).
>
> Regarding your suggestion, adding specific builder classes could also be an
> interesting way to go.
> I would even consider to make some specific API bundles, like:
>
> org.apache.felix.dependencymanager -> the current 4.0 API, and it should be
> close to the old 3.2 API as much as possible (Marcel, what is your opinion
> ?)
> org.apache.felix.dependencymanager.scala -> we could leverage DM API to
> scala
> org.apache.felix.dependencymanager.groovy -> same for groovy
> etc ...
>
> All this could be discussed with more details in the jira issue that
> Christian created.
>
> kind regards
> /Pierre
>
>
> On Tue, Nov 11, 2014 at 8:55 AM, Paul Bakker <pa...@luminis.eu>
> wrote:
>
> > One thing to consider is that although DM 4 is a major version bump, it
> so
> > far seems to be very close to a drop-in replacement of DM 3. Changing the
> > API itself would break all existing code. This is technically ok for a
> > major version, but will make adoption of the new version a lot slower.
> >
> > On the other hand, I do like the proposal :-) Maybe it's possible to add
> a
> > new API, while keeping the existing one. E.g. introduce a builder class
> > specifically for this reason, user can than gradually move towards the
> new
> > API. Potentially there could even be builders for multiple JVM languages,
> > leveraging the DSL functionality of language Groovy etc.
> >
> > Cheers,
> >
> > Paul
> >
> > On Tue, Nov 11, 2014 at 12:39 AM, Pierre De Rop <pi...@gmail.com>
> > wrote:
> >
> > > Hello Christian;
> > >
> > > The improvements you are proposing would require a major version bump
> > since
> > > it's an incompatible API change. But I personally like what you are
> > > suggesting, and I could quickly do it in the upcoming Dependency
> Manager
> > > 4.0.0, which is a new major version.
> > >
> > > But before, I need to know if Marcel is agree to go ahead with all
> this;
> > so
> > > for the moment, may be you can just create a Jira issue, and let's wait
> > for
> > > Marcel to see if he's OK.
> > >
> > > Just one remark: the setters can be easily removed, however I think we
> > > can't manage to make the "component()" method automatically add the
> > > Component to the DependencyManager, because technically; when you add a
> > > Component to a DependencyManager, the Component is actually
> *activated*,
> > > and at this point, all the necessary dependencies have to be already in
> > > place.
> > >
> > > So, the only possible improvement I'm thinking about for now could have
> > the
> > > form of this:
> > >
> > >     public void init(BundleContext context, DependencyManager manager)
> > > throws Exception {
> > >         component()
> > >             .implementation(DataGenerator.class)
> > >             .add(serviceDependency(Store.class).required())
> > >             .add(serviceDependency(LogService.class))
> > >             .addTo(manager);
> > >     }
> > >
> > > (notice the addTo method at the end of the sample above, which could
> just
> > > add the fully built component to the DependencyManager "manager"
> object).
> > >
> > > but I propose you first create the Jira issue and see what Marcel
> thinks.
> > >
> > > I will possible add more suggestions in your Jira issue once you will
> > have
> > > created it (like also using a builder pattern for the aspects/adapters:
> > > this would allow to reduce the number of method signatures for the
> > > createAdapter/createAspect methods).
> > >
> > > kind regards (and thanks for proposing to improve Dependency Manager
> :-))
> > >
> > > /Pierre
> > >
> > > On Mon, Nov 10, 2014 at 11:40 AM, Christian Schneider <
> > > chris@die-schneider.net> wrote:
> > >
> > > > I wonder if the DependencyManager API could be made a bit more
> fluent.
> > > > Technically it already uses the fluent builder pattern
> > > > but all the builder verbs still look a lot like traditional setters.
> > > >
> > > > I know what I propose is mostly syntactic sugar but I think the
> result
> > > > looks more readable and crisp. See below for some ideas.
> > > >
> > > > Christian
> > > >
> > > > ----
> > > >
> > > > This is from samples.dependonservice:
> > > >     public void init(BundleContext context, DependencyManager
> manager)
> > > > throws Exception {
> > > >         manager.add(createComponent()
> > > >             .setImplementation(DataGenerator.class)
> > > >             .add(createServiceDependency()
> > > >                 .setService(Store.class)
> > > >                 .setRequired(true)
> > > >             )
> > > >             .add(createServiceDependency()
> > > >                 .setService(LogService.class)
> > > >                 .setRequired(false)
> > > >             )
> > > >         );
> > > >     }
> > > >
> > > > Why not make it look like this:
> > > >     public void init(BundleContext context, DependencyManager
> manager)
> > > > throws Exception {
> > > >         component()
> > > >             .implementation(DataGenerator.class)
> > > >             .add(serviceDependency(Store.class).required())
> > > >             .add(serviceDependency(LogService.class))
> > > >             );
> > > >         );
> > > >     }
> > > >
> > > > component() could create and add the component.
> > > >
> > > > Or for configuration:
> > > >     public void init(BundleContext context, DependencyManager
> manager)
> > > > throws Exception {
> > > >         manager.add(createComponent()
> > > >             .setImplementation(Task.class)
> > > >             .add(createConfigurationDependency()
> > > >                 .setPid("config.pid")
> > > >                 // The following is optional and allows to display
> our
> > > > configuration from webconsole
> > > >                 .setHeading("Task Configuration")
> > > >                 .setDescription("Configuration for the Task Service")
> > > >                 .add(createPropertyMetaData()
> > > >                      .setCardinality(0)
> > > >                      .setType(String.class)
> > > >                      .setHeading("Task Interval")
> > > >                      .setDescription("Declare here the interval used
> to
> > > > trigger the Task")
> > > >                      .setDefaults(new String[] {"10"})
> > > >                      .setId("interval"))));
> > > >     }
> > > >
> > > > could be:
> > > >     public void init(BundleContext context, DependencyManager
> manager)
> > > > throws Exception {
> > > >         component().implementation(Task.class)
> > > >             .configuration("config.pid")
> > > >                 .add(meta("Task Configuration)
> > > >                     .description("Configuration for the Task
> Service")
> > > >                     .add(property("interval")
> > > >                             .cardinality(0)
> > > >                             .type(String.class)
> > > >                             .heading("Task Interval")
> > > >                             .description("Declare here the interval
> > used
> > > > to trigger the Task")
> > > >                             .default("10"))
> > > >     }
> > > >
> > > > --
> > > > Christian Schneider
> > > > http://www.liquid-reality.de
> > > >
> > > > Open Source Architect
> > > > http://www.talend.com
> > > >
> > > >
> > >
> >
>

Re: Make DependencyManager API more fluent?

Posted by Marcel Offermans <ma...@luminis.eu>.
Hello Pierre,

> On 12 Nov 2014, at 9:13 am, Pierre De Rop <pi...@gmail.com> wrote:
> 
> Regarding your suggestion, adding specific builder classes could also be an
> interesting way to go.
> I would even consider to make some specific API bundles, like:
> 
> org.apache.felix.dependencymanager -> the current 4.0 API, and it should be
> close to the old 3.2 API as much as possible (Marcel, what is your opinion
> ?)

Yes, we can keep this as close to the existing API to ease migration.

> org.apache.felix.dependencymanager.scala -> we could leverage DM API to
> scala
> org.apache.felix.dependencymanager.groovy -> same for groovy
> etc …
> 
> All this could be discussed with more details in the jira issue that
> Christian created.

Makes sense, and we could introduce a .java package (and bundle) for the API that Christian proposed. That fits nicely in our plans (just like we have the .runtime and annotations if you like that style) and possibly also our future support for the declarative services API.

Greetings, Marcel


Re: Make DependencyManager API more fluent?

Posted by Pierre De Rop <pi...@gmail.com>.
Hello Paul,

indeed, the DM4 code is very close to the old 3.2 API, and it would be
unfortunate if breaking the API too much would make slower the adoption of
the new version.
I gave immense effort to bring to life the new thread model introduced by
Marcel and Xander, and now we also have a nice actor thread model allowing
concurrent activation of Components while staying "single threaded"
internally ...
so I will check what has changed in the new 4.0 API and will manage to make
it closer to the old 3.2 API as much as possible (but some methods have
been removed, like the setInstanceBound method, for example).

Regarding your suggestion, adding specific builder classes could also be an
interesting way to go.
I would even consider to make some specific API bundles, like:

org.apache.felix.dependencymanager -> the current 4.0 API, and it should be
close to the old 3.2 API as much as possible (Marcel, what is your opinion
?)
org.apache.felix.dependencymanager.scala -> we could leverage DM API to
scala
org.apache.felix.dependencymanager.groovy -> same for groovy
etc ...

All this could be discussed with more details in the jira issue that
Christian created.

kind regards
/Pierre


On Tue, Nov 11, 2014 at 8:55 AM, Paul Bakker <pa...@luminis.eu> wrote:

> One thing to consider is that although DM 4 is a major version bump, it so
> far seems to be very close to a drop-in replacement of DM 3. Changing the
> API itself would break all existing code. This is technically ok for a
> major version, but will make adoption of the new version a lot slower.
>
> On the other hand, I do like the proposal :-) Maybe it's possible to add a
> new API, while keeping the existing one. E.g. introduce a builder class
> specifically for this reason, user can than gradually move towards the new
> API. Potentially there could even be builders for multiple JVM languages,
> leveraging the DSL functionality of language Groovy etc.
>
> Cheers,
>
> Paul
>
> On Tue, Nov 11, 2014 at 12:39 AM, Pierre De Rop <pi...@gmail.com>
> wrote:
>
> > Hello Christian;
> >
> > The improvements you are proposing would require a major version bump
> since
> > it's an incompatible API change. But I personally like what you are
> > suggesting, and I could quickly do it in the upcoming Dependency Manager
> > 4.0.0, which is a new major version.
> >
> > But before, I need to know if Marcel is agree to go ahead with all this;
> so
> > for the moment, may be you can just create a Jira issue, and let's wait
> for
> > Marcel to see if he's OK.
> >
> > Just one remark: the setters can be easily removed, however I think we
> > can't manage to make the "component()" method automatically add the
> > Component to the DependencyManager, because technically; when you add a
> > Component to a DependencyManager, the Component is actually *activated*,
> > and at this point, all the necessary dependencies have to be already in
> > place.
> >
> > So, the only possible improvement I'm thinking about for now could have
> the
> > form of this:
> >
> >     public void init(BundleContext context, DependencyManager manager)
> > throws Exception {
> >         component()
> >             .implementation(DataGenerator.class)
> >             .add(serviceDependency(Store.class).required())
> >             .add(serviceDependency(LogService.class))
> >             .addTo(manager);
> >     }
> >
> > (notice the addTo method at the end of the sample above, which could just
> > add the fully built component to the DependencyManager "manager" object).
> >
> > but I propose you first create the Jira issue and see what Marcel thinks.
> >
> > I will possible add more suggestions in your Jira issue once you will
> have
> > created it (like also using a builder pattern for the aspects/adapters:
> > this would allow to reduce the number of method signatures for the
> > createAdapter/createAspect methods).
> >
> > kind regards (and thanks for proposing to improve Dependency Manager :-))
> >
> > /Pierre
> >
> > On Mon, Nov 10, 2014 at 11:40 AM, Christian Schneider <
> > chris@die-schneider.net> wrote:
> >
> > > I wonder if the DependencyManager API could be made a bit more fluent.
> > > Technically it already uses the fluent builder pattern
> > > but all the builder verbs still look a lot like traditional setters.
> > >
> > > I know what I propose is mostly syntactic sugar but I think the result
> > > looks more readable and crisp. See below for some ideas.
> > >
> > > Christian
> > >
> > > ----
> > >
> > > This is from samples.dependonservice:
> > >     public void init(BundleContext context, DependencyManager manager)
> > > throws Exception {
> > >         manager.add(createComponent()
> > >             .setImplementation(DataGenerator.class)
> > >             .add(createServiceDependency()
> > >                 .setService(Store.class)
> > >                 .setRequired(true)
> > >             )
> > >             .add(createServiceDependency()
> > >                 .setService(LogService.class)
> > >                 .setRequired(false)
> > >             )
> > >         );
> > >     }
> > >
> > > Why not make it look like this:
> > >     public void init(BundleContext context, DependencyManager manager)
> > > throws Exception {
> > >         component()
> > >             .implementation(DataGenerator.class)
> > >             .add(serviceDependency(Store.class).required())
> > >             .add(serviceDependency(LogService.class))
> > >             );
> > >         );
> > >     }
> > >
> > > component() could create and add the component.
> > >
> > > Or for configuration:
> > >     public void init(BundleContext context, DependencyManager manager)
> > > throws Exception {
> > >         manager.add(createComponent()
> > >             .setImplementation(Task.class)
> > >             .add(createConfigurationDependency()
> > >                 .setPid("config.pid")
> > >                 // The following is optional and allows to display our
> > > configuration from webconsole
> > >                 .setHeading("Task Configuration")
> > >                 .setDescription("Configuration for the Task Service")
> > >                 .add(createPropertyMetaData()
> > >                      .setCardinality(0)
> > >                      .setType(String.class)
> > >                      .setHeading("Task Interval")
> > >                      .setDescription("Declare here the interval used to
> > > trigger the Task")
> > >                      .setDefaults(new String[] {"10"})
> > >                      .setId("interval"))));
> > >     }
> > >
> > > could be:
> > >     public void init(BundleContext context, DependencyManager manager)
> > > throws Exception {
> > >         component().implementation(Task.class)
> > >             .configuration("config.pid")
> > >                 .add(meta("Task Configuration)
> > >                     .description("Configuration for the Task Service")
> > >                     .add(property("interval")
> > >                             .cardinality(0)
> > >                             .type(String.class)
> > >                             .heading("Task Interval")
> > >                             .description("Declare here the interval
> used
> > > to trigger the Task")
> > >                             .default("10"))
> > >     }
> > >
> > > --
> > > Christian Schneider
> > > http://www.liquid-reality.de
> > >
> > > Open Source Architect
> > > http://www.talend.com
> > >
> > >
> >
>

Re: Make DependencyManager API more fluent?

Posted by Paul Bakker <pa...@luminis.eu>.
One thing to consider is that although DM 4 is a major version bump, it so
far seems to be very close to a drop-in replacement of DM 3. Changing the
API itself would break all existing code. This is technically ok for a
major version, but will make adoption of the new version a lot slower.

On the other hand, I do like the proposal :-) Maybe it's possible to add a
new API, while keeping the existing one. E.g. introduce a builder class
specifically for this reason, user can than gradually move towards the new
API. Potentially there could even be builders for multiple JVM languages,
leveraging the DSL functionality of language Groovy etc.

Cheers,

Paul

On Tue, Nov 11, 2014 at 12:39 AM, Pierre De Rop <pi...@gmail.com>
wrote:

> Hello Christian;
>
> The improvements you are proposing would require a major version bump since
> it's an incompatible API change. But I personally like what you are
> suggesting, and I could quickly do it in the upcoming Dependency Manager
> 4.0.0, which is a new major version.
>
> But before, I need to know if Marcel is agree to go ahead with all this; so
> for the moment, may be you can just create a Jira issue, and let's wait for
> Marcel to see if he's OK.
>
> Just one remark: the setters can be easily removed, however I think we
> can't manage to make the "component()" method automatically add the
> Component to the DependencyManager, because technically; when you add a
> Component to a DependencyManager, the Component is actually *activated*,
> and at this point, all the necessary dependencies have to be already in
> place.
>
> So, the only possible improvement I'm thinking about for now could have the
> form of this:
>
>     public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>         component()
>             .implementation(DataGenerator.class)
>             .add(serviceDependency(Store.class).required())
>             .add(serviceDependency(LogService.class))
>             .addTo(manager);
>     }
>
> (notice the addTo method at the end of the sample above, which could just
> add the fully built component to the DependencyManager "manager" object).
>
> but I propose you first create the Jira issue and see what Marcel thinks.
>
> I will possible add more suggestions in your Jira issue once you will have
> created it (like also using a builder pattern for the aspects/adapters:
> this would allow to reduce the number of method signatures for the
> createAdapter/createAspect methods).
>
> kind regards (and thanks for proposing to improve Dependency Manager :-))
>
> /Pierre
>
> On Mon, Nov 10, 2014 at 11:40 AM, Christian Schneider <
> chris@die-schneider.net> wrote:
>
> > I wonder if the DependencyManager API could be made a bit more fluent.
> > Technically it already uses the fluent builder pattern
> > but all the builder verbs still look a lot like traditional setters.
> >
> > I know what I propose is mostly syntactic sugar but I think the result
> > looks more readable and crisp. See below for some ideas.
> >
> > Christian
> >
> > ----
> >
> > This is from samples.dependonservice:
> >     public void init(BundleContext context, DependencyManager manager)
> > throws Exception {
> >         manager.add(createComponent()
> >             .setImplementation(DataGenerator.class)
> >             .add(createServiceDependency()
> >                 .setService(Store.class)
> >                 .setRequired(true)
> >             )
> >             .add(createServiceDependency()
> >                 .setService(LogService.class)
> >                 .setRequired(false)
> >             )
> >         );
> >     }
> >
> > Why not make it look like this:
> >     public void init(BundleContext context, DependencyManager manager)
> > throws Exception {
> >         component()
> >             .implementation(DataGenerator.class)
> >             .add(serviceDependency(Store.class).required())
> >             .add(serviceDependency(LogService.class))
> >             );
> >         );
> >     }
> >
> > component() could create and add the component.
> >
> > Or for configuration:
> >     public void init(BundleContext context, DependencyManager manager)
> > throws Exception {
> >         manager.add(createComponent()
> >             .setImplementation(Task.class)
> >             .add(createConfigurationDependency()
> >                 .setPid("config.pid")
> >                 // The following is optional and allows to display our
> > configuration from webconsole
> >                 .setHeading("Task Configuration")
> >                 .setDescription("Configuration for the Task Service")
> >                 .add(createPropertyMetaData()
> >                      .setCardinality(0)
> >                      .setType(String.class)
> >                      .setHeading("Task Interval")
> >                      .setDescription("Declare here the interval used to
> > trigger the Task")
> >                      .setDefaults(new String[] {"10"})
> >                      .setId("interval"))));
> >     }
> >
> > could be:
> >     public void init(BundleContext context, DependencyManager manager)
> > throws Exception {
> >         component().implementation(Task.class)
> >             .configuration("config.pid")
> >                 .add(meta("Task Configuration)
> >                     .description("Configuration for the Task Service")
> >                     .add(property("interval")
> >                             .cardinality(0)
> >                             .type(String.class)
> >                             .heading("Task Interval")
> >                             .description("Declare here the interval used
> > to trigger the Task")
> >                             .default("10"))
> >     }
> >
> > --
> > Christian Schneider
> > http://www.liquid-reality.de
> >
> > Open Source Architect
> > http://www.talend.com
> >
> >
>

Re: Make DependencyManager API more fluent?

Posted by Pierre De Rop <pi...@gmail.com>.
Hello Christian;

The improvements you are proposing would require a major version bump since
it's an incompatible API change. But I personally like what you are
suggesting, and I could quickly do it in the upcoming Dependency Manager
4.0.0, which is a new major version.

But before, I need to know if Marcel is agree to go ahead with all this; so
for the moment, may be you can just create a Jira issue, and let's wait for
Marcel to see if he's OK.

Just one remark: the setters can be easily removed, however I think we
can't manage to make the "component()" method automatically add the
Component to the DependencyManager, because technically; when you add a
Component to a DependencyManager, the Component is actually *activated*,
and at this point, all the necessary dependencies have to be already in
place.

So, the only possible improvement I'm thinking about for now could have the
form of this:

    public void init(BundleContext context, DependencyManager manager)
throws Exception {
        component()
            .implementation(DataGenerator.class)
            .add(serviceDependency(Store.class).required())
            .add(serviceDependency(LogService.class))
            .addTo(manager);
    }

(notice the addTo method at the end of the sample above, which could just
add the fully built component to the DependencyManager "manager" object).

but I propose you first create the Jira issue and see what Marcel thinks.

I will possible add more suggestions in your Jira issue once you will have
created it (like also using a builder pattern for the aspects/adapters:
this would allow to reduce the number of method signatures for the
createAdapter/createAspect methods).

kind regards (and thanks for proposing to improve Dependency Manager :-))

/Pierre

On Mon, Nov 10, 2014 at 11:40 AM, Christian Schneider <
chris@die-schneider.net> wrote:

> I wonder if the DependencyManager API could be made a bit more fluent.
> Technically it already uses the fluent builder pattern
> but all the builder verbs still look a lot like traditional setters.
>
> I know what I propose is mostly syntactic sugar but I think the result
> looks more readable and crisp. See below for some ideas.
>
> Christian
>
> ----
>
> This is from samples.dependonservice:
>     public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>         manager.add(createComponent()
>             .setImplementation(DataGenerator.class)
>             .add(createServiceDependency()
>                 .setService(Store.class)
>                 .setRequired(true)
>             )
>             .add(createServiceDependency()
>                 .setService(LogService.class)
>                 .setRequired(false)
>             )
>         );
>     }
>
> Why not make it look like this:
>     public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>         component()
>             .implementation(DataGenerator.class)
>             .add(serviceDependency(Store.class).required())
>             .add(serviceDependency(LogService.class))
>             );
>         );
>     }
>
> component() could create and add the component.
>
> Or for configuration:
>     public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>         manager.add(createComponent()
>             .setImplementation(Task.class)
>             .add(createConfigurationDependency()
>                 .setPid("config.pid")
>                 // The following is optional and allows to display our
> configuration from webconsole
>                 .setHeading("Task Configuration")
>                 .setDescription("Configuration for the Task Service")
>                 .add(createPropertyMetaData()
>                      .setCardinality(0)
>                      .setType(String.class)
>                      .setHeading("Task Interval")
>                      .setDescription("Declare here the interval used to
> trigger the Task")
>                      .setDefaults(new String[] {"10"})
>                      .setId("interval"))));
>     }
>
> could be:
>     public void init(BundleContext context, DependencyManager manager)
> throws Exception {
>         component().implementation(Task.class)
>             .configuration("config.pid")
>                 .add(meta("Task Configuration)
>                     .description("Configuration for the Task Service")
>                     .add(property("interval")
>                             .cardinality(0)
>                             .type(String.class)
>                             .heading("Task Interval")
>                             .description("Declare here the interval used
> to trigger the Task")
>                             .default("10"))
>     }
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> http://www.talend.com
>
>