Quantcast

Unified API

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Unified API

Benoît Durand
Hello everyone,

I follow the discussion about a unified API for broker/plugin method  
in the thread around Dojo.

I have a question in the same way about configuration. What we do for  
configuration? Do we use the word of options/setOptions or config/
setConfig? I see that both are used in various components. I think  
it's more simple to have always the same method name to configure an  
object.
If we have an interface for methods' broker, do we need an interface  
for the configuration method?

Remember the proposal on this subject :
     http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau

Greetings.
--
Benoît Durand
--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

ramonornela
This post has NOT been accepted by the mailing list yet.
Hi Benoît Durand,
Here a prototype done by  Renan de Lima (renanbr).

Greetings
Ramon Henrique Ornelas

On Tue, Aug 9, 2011 at 4:07 PM, Benoît Durand [via Zend Framework Community] <[hidden email]> wrote:
Hello everyone,

I follow the discussion about a unified API for broker/plugin method  
in the thread around Dojo.

I have a question in the same way about configuration. What we do for  
configuration? Do we use the word of options/setOptions or config/
setConfig? I see that both are used in various components. I think  
it's more simple to have always the same method name to configure an  
object.
If we have an interface for methods' broker, do we need an interface  
for the configuration method?

Remember the proposal on this subject :
     http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau

Greetings.
--
Benoît Durand
--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]





If you reply to this email, your message will be added to the discussion below:
http://zend-framework-community.634137.n4.nabble.com/Unified-API-tp3730937p3730937.html
To start a new topic under ZF Contributor, email [hidden email]
To unsubscribe from ZF Contributor, click here.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

weierophinney
Administrator
In reply to this post by Benoît Durand
-- Benoît Durand <[hidden email]> wrote
(on Tuesday, 09 August 2011, 09:05 PM +0200):

> I follow the discussion about a unified API for broker/plugin method
> in the thread around Dojo.
>
> I have a question in the same way about configuration. What we do
> for configuration? Do we use the word of options/setOptions or
> config/setConfig? I see that both are used in various components. I
> think it's more simple to have always the same method name to
> configure an object.
> If we have an interface for methods' broker, do we need an interface
> for the configuration method?
>
> Remember the proposal on this subject :
>     http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau

In working on the DI solution, Ralph and I stumbled upon/played with a
few different configuration patterns. One thing we're discovering is
that it kind of sucks to have configuration of an object _within_ the
object. There's a bunch of boilerplate that happens that's not really
the responsibility of the object itself -- it just wants values.

One thing we looked at was having discrete configuration classes
per-component. We could then support a couple different use cases:

    $client     = new HttpClient();
    $httpConfig = new HttpConfiguration($zendConfig->http);

    // Have the configuration object configure the client:
    $httpConfig->configure($client);

    // Or pass configuration to the client:
    $client->configure($httpConfig);

    // potentially at instantiation:
    $client = new HttpClient($httpConfig);

There are a few benefits to these approaches. One is that we can very
easily store default values in these configuration objects. Another is
that we can typehint the configuration -- we know that the only
configuration object that a given class can receive must derive from a
specific type. Also, this style plays well with DI -- you can either
pass configurable values to the configuration object, and then inject
that object into desired classes, or extend the configuration and simply
specify your alternate class. Finally, having configuration classes
makes it trivially easy to document available options both at the API
level as well as generating end-user docs.

Regardless, we'd like to have a _consistent_ story for configuration
across the board; there are too many patterns currently within the
framework, making it very difficult to know what patterns will work with
a given component without first introspecting the code and/or
documentation.

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

padraicb
Passing the configuration object into the constructor or a setter would be preferable. There are certain cases, some pretty hairy, when you need to pass configuration around between a few classes. Having a ready made parameter object to throw about, and which encompasses the configuration processing logic, would keep the resulting duplication (of a crazy number of setters/getters) to a minimum.Of course, adopting a standard approach that isn't an array will require a few extra features (merging, cloning, etc.). I could see that working however.

The obvious complaint likely:

$foo = new Zend\Foo(new Zend\Foo\Configuration($config));

It's more verbose than passing in the $config variable alone, and it would depend on Zend\Config (optionally) bringing in another layer. Zend\Di can hide this quite well, but a DIC won't cover up the slightly more complex starting situation for most components. The benefits seem worth it however.

If I could hazard a guess, someone will end up proposing a Zend\Config that can automatically link configuration sections to the most suitable Configuration container.


Paddy

 
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team



>________________________________
>From: Matthew Weier O'Phinney <[hidden email]>
>To: [hidden email]
>Sent: Tuesday, August 9, 2011 8:52 PM
>Subject: Re: [zf-contributors] Unified API
>
>-- Benoît Durand <[hidden email]> wrote
>(on Tuesday, 09 August 2011, 09:05 PM +0200):
>> I follow the discussion about a unified API for broker/plugin method
>> in the thread around Dojo.
>>
>> I have a question in the same way about configuration. What we do
>> for configuration? Do we use the word of options/setOptions or
>> config/setConfig? I see that both are used in various components. I
>> think it's more simple to have always the same method name to
>> configure an object.
>> If we have an interface for methods' broker, do we need an interface
>> for the configuration method?
>>
>> Remember the proposal on this subject :
>>    http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
>
>In working on the DI solution, Ralph and I stumbled upon/played with a
>few different configuration patterns. One thing we're discovering is
>that it kind of sucks to have configuration of an object _within_ the
>object. There's a bunch of boilerplate that happens that's not really
>the responsibility of the object itself -- it just wants values.
>
>One thing we looked at was having discrete configuration classes
>per-component. We could then support a couple different use cases:
>
>    $client     = new HttpClient();
>    $httpConfig = new HttpConfiguration($zendConfig->http);
>
>    // Have the configuration object configure the client:
>    $httpConfig->configure($client);
>
>    // Or pass configuration to the client:
>    $client->configure($httpConfig);
>
>    // potentially at instantiation:
>    $client = new HttpClient($httpConfig);
>
>There are a few benefits to these approaches. One is that we can very
>easily store default values in these configuration objects. Another is
>that we can typehint the configuration -- we know that the only
>configuration object that a given class can receive must derive from a
>specific type. Also, this style plays well with DI -- you can either
>pass configurable values to the configuration object, and then inject
>that object into desired classes, or extend the configuration and simply
>specify your alternate class. Finally, having configuration classes
>makes it trivially easy to document available options both at the API
>level as well as generating end-user docs.
>
>Regardless, we'd like to have a _consistent_ story for configuration
>across the board; there are too many patterns currently within the
>framework, making it very difficult to know what patterns will work with
>a given component without first introspecting the code and/or
>documentation.
>
>--
>Matthew Weier O'Phinney
>Project Lead            | [hidden email]
>Zend Framework          | http://framework.zend.com/
>PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>
>--
>List: [hidden email]
>Info: http://framework.zend.com/archives
>Unsubscribe: [hidden email]
>
>
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Tomáš Fejfar
In reply to this post by weierophinney
The question is: will it be consistent all across the components? Won't
developers be angry, that they need to create another class just for few
options? Imagine you'll end up loading 20 classes, just for config purposes.


Isn't it too much overhead (class with 3 setters/getters vs. 3item array)? I
can see the benefits, but I don't think it's worth.

On Tue, Aug 9, 2011 at 9:52 PM, Matthew Weier O'Phinney <[hidden email]>wrote:

> -- Benoît Durand <[hidden email]> wrote
> (on Tuesday, 09 August 2011, 09:05 PM +0200):
> > I follow the discussion about a unified API for broker/plugin method
> > in the thread around Dojo.
> >
> > I have a question in the same way about configuration. What we do
> > for configuration? Do we use the word of options/setOptions or
> > config/setConfig? I see that both are used in various components. I
> > think it's more simple to have always the same method name to
> > configure an object.
> > If we have an interface for methods' broker, do we need an interface
> > for the configuration method?
> >
> > Remember the proposal on this subject :
> >
> http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
>
> In working on the DI solution, Ralph and I stumbled upon/played with a
> few different configuration patterns. One thing we're discovering is
> that it kind of sucks to have configuration of an object _within_ the
> object. There's a bunch of boilerplate that happens that's not really
> the responsibility of the object itself -- it just wants values.
>
> One thing we looked at was having discrete configuration classes
> per-component. We could then support a couple different use cases:
>
>    $client     = new HttpClient();
>    $httpConfig = new HttpConfiguration($zendConfig->http);
>
>    // Have the configuration object configure the client:
>    $httpConfig->configure($client);
>
>    // Or pass configuration to the client:
>    $client->configure($httpConfig);
>
>    // potentially at instantiation:
>    $client = new HttpClient($httpConfig);
>
> There are a few benefits to these approaches. One is that we can very
> easily store default values in these configuration objects. Another is
> that we can typehint the configuration -- we know that the only
> configuration object that a given class can receive must derive from a
> specific type. Also, this style plays well with DI -- you can either
> pass configurable values to the configuration object, and then inject
> that object into desired classes, or extend the configuration and simply
> specify your alternate class. Finally, having configuration classes
> makes it trivially easy to document available options both at the API
> level as well as generating end-user docs.
>
> Regardless, we'd like to have a _consistent_ story for configuration
> across the board; there are too many patterns currently within the
> framework, making it very difficult to know what patterns will work with
> a given component without first introspecting the code and/or
> documentation.
>
> --
> Matthew Weier O'Phinney
> Project Lead            | [hidden email]
> Zend Framework          | http://framework.zend.com/
> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>
> --
> List: [hidden email]
> Info: http://framework.zend.com/archives
> Unsubscribe: [hidden email]
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Tomáš Fejfar
In reply to this post by padraicb
Why do we care about number of set/get methods? It makes the ZF code less
readable, but who cares (except the FW developers)... "end developer"
doesn't. He cares whether the FW is fast and has small memory footprint. You
see much complex stuff being done in setters, that can be reused? It's
mostly class/interface check (in method parameter) and than assigning to
member variable, isn't it?

$el = $form->addElement(new Zend_Form_Element_Text(array(
    'name' => 'my_el',
    'validators' => array('Int'),
)));

vs.

$el = $form->addElement(new Zend_Form_Element_Text(new
Zend_Form_Element_Configuration(array(
    'name' => 'my_el'
    'validators' => array('Int'),
))));

What's the difference? If you will instantiate the Configuration and then
pass it around, there is no added value over array, is it?

And also: will there be one level of configuration for one part of
framework? Will it be Zend_Form_Configuration,
Zend_Form_Element_Configuration, Zend_Form_Element_Text_Configuration,
Zend_Form_Element_Multi_Configuration, with extending? It would load
ZFE_Configuration, ZFE_Xhtml_Configuation, ZFE_Multi_Configuration and
finally ZFE_MultiCheckbox_Configuration. You just loaded 4 classes, that
could have been swapped for array :)

On Tue, Aug 9, 2011 at 10:19 PM, Pádraic Brady <[hidden email]>wrote:

> Passing the configuration object into the constructor or a setter would be
> preferable. There are certain cases, some pretty hairy, when you need to
> pass configuration around between a few classes. Having a ready made
> parameter object to throw about, and which encompasses the configuration
> processing logic, would keep the resulting duplication (of a crazy number of
> setters/getters) to a minimum.Of course, adopting a standard approach that
> isn't an array will require a few extra features (merging, cloning, etc.). I
> could see that working however.
>
> The obvious complaint likely:
>
> $foo = new Zend\Foo(new Zend\Foo\Configuration($config));
>
> It's more verbose than passing in the $config variable alone, and it would
> depend on Zend\Config (optionally) bringing in another layer. Zend\Di can
> hide this quite well, but a DIC won't cover up the slightly more complex
> starting situation for most components. The benefits seem worth it however.
>
> If I could hazard a guess, someone will end up proposing a Zend\Config that
> can automatically link configuration sections to the most suitable
> Configuration container.
>
>
> Paddy
>
>
> Pádraic Brady
>
> http://blog.astrumfutura.com
> http://www.survivethedeepend.com
> Zend Framework Community Review Team
>
>
>
> >________________________________
> >From: Matthew Weier O'Phinney <[hidden email]>
> >To: [hidden email]
> >Sent: Tuesday, August 9, 2011 8:52 PM
> >Subject: Re: [zf-contributors] Unified API
> >
> >-- Benoît Durand <[hidden email]> wrote
> >(on Tuesday, 09 August 2011, 09:05 PM +0200):
> >> I follow the discussion about a unified API for broker/plugin method
> >> in the thread around Dojo.
> >>
> >> I have a question in the same way about configuration. What we do
> >> for configuration? Do we use the word of options/setOptions or
> >> config/setConfig? I see that both are used in various components. I
> >> think it's more simple to have always the same method name to
> >> configure an object.
> >> If we have an interface for methods' broker, do we need an interface
> >> for the configuration method?
> >>
> >> Remember the proposal on this subject :
> >>
> http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
> >
> >In working on the DI solution, Ralph and I stumbled upon/played with a
> >few different configuration patterns. One thing we're discovering is
> >that it kind of sucks to have configuration of an object _within_ the
> >object. There's a bunch of boilerplate that happens that's not really
> >the responsibility of the object itself -- it just wants values.
> >
> >One thing we looked at was having discrete configuration classes
> >per-component. We could then support a couple different use cases:
> >
> >    $client     = new HttpClient();
> >    $httpConfig = new HttpConfiguration($zendConfig->http);
> >
> >    // Have the configuration object configure the client:
> >    $httpConfig->configure($client);
> >
> >    // Or pass configuration to the client:
> >    $client->configure($httpConfig);
> >
> >    // potentially at instantiation:
> >    $client = new HttpClient($httpConfig);
> >
> >There are a few benefits to these approaches. One is that we can very
> >easily store default values in these configuration objects. Another is
> >that we can typehint the configuration -- we know that the only
> >configuration object that a given class can receive must derive from a
> >specific type. Also, this style plays well with DI -- you can either
> >pass configurable values to the configuration object, and then inject
> >that object into desired classes, or extend the configuration and simply
> >specify your alternate class. Finally, having configuration classes
> >makes it trivially easy to document available options both at the API
> >level as well as generating end-user docs.
> >
> >Regardless, we'd like to have a _consistent_ story for configuration
> >across the board; there are too many patterns currently within the
> >framework, making it very difficult to know what patterns will work with
> >a given component without first introspecting the code and/or
> >documentation.
> >
> >--
> >Matthew Weier O'Phinney
> >Project Lead            | [hidden email]
> >Zend Framework          | http://framework.zend.com/
> >PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
> >
> >--
> >List: [hidden email]
> >Info: http://framework.zend.com/archives
> >Unsubscribe: [hidden email]
> >
> >
> >
> >
> >
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

padraicb
In reply to this post by Tomáš Fejfar
Thing is, depending on the component, you could be loading extra classes anyway. Configuration needs to be pushed through any system, and using a container object makes the most sense where that needs to happen. One of the not-so-clean designs I know that I use far too much is pushing the parent object (which contains the initial configuration) around everywhere even when it's not a container for that purpose - that has led me down some garden paths before ;). The other point is that it's not unusual to find this in standalone libraries where objects are pushed in rather than created internally (the first being better DI). Zend Framework's convention of using an array passed to the constructor isn't necessarily what all users should expect. It largely came about because we standardised on Zend_Config and then, because that's not always available or used, we dropped a level to a simple array. Selecting an array was a matter of convenience over good design.

Paddy

 
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team



>________________________________
>From: Tomáš Fejfar <[hidden email]>
>To: [hidden email]
>Sent: Tuesday, August 9, 2011 9:58 PM
>Subject: Re: [zf-contributors] Unified API
>
>The question is: will it be consistent all across the components? Won't
>developers be angry, that they need to create another class just for few
>options? Imagine you'll end up loading 20 classes, just for config purposes.
>
>
>Isn't it too much overhead (class with 3 setters/getters vs. 3item array)? I
>can see the benefits, but I don't think it's worth.
>
>On Tue, Aug 9, 2011 at 9:52 PM, Matthew Weier O'Phinney <[hidden email]>wrote:
>
>> -- Benoît Durand <[hidden email]> wrote
>> (on Tuesday, 09 August 2011, 09:05 PM +0200):
>> > I follow the discussion about a unified API for broker/plugin method
>> > in the thread around Dojo.
>> >
>> > I have a question in the same way about configuration. What we do
>> > for configuration? Do we use the word of options/setOptions or
>> > config/setConfig? I see that both are used in various components. I
>> > think it's more simple to have always the same method name to
>> > configure an object.
>> > If we have an interface for methods' broker, do we need an interface
>> > for the configuration method?
>> >
>> > Remember the proposal on this subject :
>> >
>> http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
>>
>> In working on the DI solution, Ralph and I stumbled upon/played with a
>> few different configuration patterns. One thing we're discovering is
>> that it kind of sucks to have configuration of an object _within_ the
>> object. There's a bunch of boilerplate that happens that's not really
>> the responsibility of the object itself -- it just wants values.
>>
>> One thing we looked at was having discrete configuration classes
>> per-component. We could then support a couple different use cases:
>>
>>    $client     = new HttpClient();
>>    $httpConfig = new HttpConfiguration($zendConfig->http);
>>
>>    // Have the configuration object configure the client:
>>    $httpConfig->configure($client);
>>
>>    // Or pass configuration to the client:
>>    $client->configure($httpConfig);
>>
>>    // potentially at instantiation:
>>    $client = new HttpClient($httpConfig);
>>
>> There are a few benefits to these approaches. One is that we can very
>> easily store default values in these configuration objects. Another is
>> that we can typehint the configuration -- we know that the only
>> configuration object that a given class can receive must derive from a
>> specific type. Also, this style plays well with DI -- you can either
>> pass configurable values to the configuration object, and then inject
>> that object into desired classes, or extend the configuration and simply
>> specify your alternate class. Finally, having configuration classes
>> makes it trivially easy to document available options both at the API
>> level as well as generating end-user docs.
>>
>> Regardless, we'd like to have a _consistent_ story for configuration
>> across the board; there are too many patterns currently within the
>> framework, making it very difficult to know what patterns will work with
>> a given component without first introspecting the code and/or
>> documentation.
>>
>> --
>> Matthew Weier O'Phinney
>> Project Lead            | [hidden email]
>> Zend Framework          | http://framework.zend.com/
>> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>>
>> --
>> List: [hidden email]
>> Info: http://framework.zend.com/archives
>> Unsubscribe: [hidden email]
>>
>>
>>
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

weierophinney
Administrator
-- Pádraic Brady <[hidden email]> wrote
(on Tuesday, 09 August 2011, 02:25 PM -0700):

> Thing is, depending on the component, you could be loading extra
> classes anyway. Configuration needs to be pushed through any system,
> and using a container object makes the most sense where that needs to
> happen. One of the not-so-clean designs I know that I use far too much
> is pushing the parent object (which contains the initial
> configuration) around everywhere even when it's not a container for
> that purpose - that has led me down some garden paths before ;). The
> other point is that it's not unusual to find this in standalone
> libraries where objects are pushed in rather than created internally
> (the first being better DI). Zend Framework's convention of using an
> array passed to the constructor isn't necessarily what all users
> should expect. It largely came about because we standardised on
> Zend_Config and then, because that's not always available or used, we
> dropped a level to a simple array. Selecting an array was a matter of
> convenience over good design.

And to elaborate a little: I've heard plenty of end-users complaining
about having arrays for configuration. Nesting levels can get hairy,
option keys are hard to discover (and often easy to mistype), and it's
not entirely clear what or how that one bit array will affect the object
necessarily.

Yes, the 1:1 mapping of keys to setters _can_ help, but in practice, I
find it often doesn't.


> >________________________________
> >From: Tomáš Fejfar <[hidden email]>
> >To: [hidden email]
> >Sent: Tuesday, August 9, 2011 9:58 PM
> >Subject: Re: [zf-contributors] Unified API
> >
> >The question is: will it be consistent all across the components? Won't
> >developers be angry, that they need to create another class just for few
> >options? Imagine you'll end up loading 20 classes, just for config purposes.
> >
> >
> >Isn't it too much overhead (class with 3 setters/getters vs. 3item array)? I
> >can see the benefits, but I don't think it's worth.
> >
> >On Tue, Aug 9, 2011 at 9:52 PM, Matthew Weier O'Phinney <[hidden email]>wrote:
> >
> >> -- Benoît Durand <[hidden email]> wrote
> >> (on Tuesday, 09 August 2011, 09:05 PM +0200):
> >> > I follow the discussion about a unified API for broker/plugin method
> >> > in the thread around Dojo.
> >> >
> >> > I have a question in the same way about configuration. What we do
> >> > for configuration? Do we use the word of options/setOptions or
> >> > config/setConfig? I see that both are used in various components. I
> >> > think it's more simple to have always the same method name to
> >> > configure an object.
> >> > If we have an interface for methods' broker, do we need an interface
> >> > for the configuration method?
> >> >
> >> > Remember the proposal on this subject :
> >> >
> >> http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
> >>
> >> In working on the DI solution, Ralph and I stumbled upon/played with a
> >> few different configuration patterns. One thing we're discovering is
> >> that it kind of sucks to have configuration of an object _within_ the
> >> object. There's a bunch of boilerplate that happens that's not really
> >> the responsibility of the object itself -- it just wants values.
> >>
> >> One thing we looked at was having discrete configuration classes
> >> per-component. We could then support a couple different use cases:
> >>
> >>    $client     = new HttpClient();
> >>    $httpConfig = new HttpConfiguration($zendConfig->http);
> >>
> >>    // Have the configuration object configure the client:
> >>    $httpConfig->configure($client);
> >>
> >>    // Or pass configuration to the client:
> >>    $client->configure($httpConfig);
> >>
> >>    // potentially at instantiation:
> >>    $client = new HttpClient($httpConfig);
> >>
> >> There are a few benefits to these approaches. One is that we can very
> >> easily store default values in these configuration objects. Another is
> >> that we can typehint the configuration -- we know that the only
> >> configuration object that a given class can receive must derive from a
> >> specific type. Also, this style plays well with DI -- you can either
> >> pass configurable values to the configuration object, and then inject
> >> that object into desired classes, or extend the configuration and simply
> >> specify your alternate class. Finally, having configuration classes
> >> makes it trivially easy to document available options both at the API
> >> level as well as generating end-user docs.
> >>
> >> Regardless, we'd like to have a _consistent_ story for configuration
> >> across the board; there are too many patterns currently within the
> >> framework, making it very difficult to know what patterns will work with
> >> a given component without first introspecting the code and/or
> >> documentation.
> >>
> >> --
> >> Matthew Weier O'Phinney
> >> Project Lead            | [hidden email]
> >> Zend Framework          | http://framework.zend.com/
> >> PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
> >>
> >> --
> >> List: [hidden email]
> >> Info: http://framework.zend.com/archives
> >> Unsubscribe: [hidden email]
> >>
> >>
> >>
> >
> >
> >

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

padraicb
In reply to this post by Tomáš Fejfar
You're right to a point. The point being that an array can't port behaviour from class to class. Where does the error checking on config values go? It ends up being distributed across many classes, or centralised on one class which then needs to follow the configuration array as its babysitter. The second point is that arrays are class members hidden behind an interface of getters and setters. How do they get ported between classes? If a user relies on certain array keys being present on an extracted protected member, and the origin class updates those during a valid refactoring, breakage may occur. You could argue that the array, as a return value, should respect an API - but the main reason a getOptions() method exists as a convention is actually to support unit testing, on a lot of cases, where the author never intended it to be used outside that (otherwise - why bother with a getter/setter method list? That's an equal waste of time if you extend your
 own argument).

As you can see, lot of worms in that can ;).

 
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team



>________________________________
>From: Tomáš Fejfar <[hidden email]>
>To: Pádraic Brady <[hidden email]>
>Cc: Matthew Weier O'Phinney <[hidden email]>; "[hidden email]" <[hidden email]>
>Sent: Tuesday, August 9, 2011 10:12 PM
>Subject: Re: [zf-contributors] Unified API
>
>
>Why do we care about number of set/get methods? It makes the ZF code less readable, but who cares (except the FW developers)... "end developer" doesn't. He cares whether the FW is fast and has small memory footprint. You see much complex stuff being done in setters, that can be reused? It's mostly class/interface check (in method parameter) and than assigning to member variable, isn't it?
>
>$el = $form->addElement(new Zend_Form_Element_Text(array(
>    'name' => 'my_el',
>    'validators' => array('Int'),
>)));
>
>vs.
>
>$el = $form->addElement(new Zend_Form_Element_Text(new Zend_Form_Element_Configuration(array(
>    'name' => 'my_el'
>    'validators' => array('Int'),
>))));
>
>What's the difference? If you will instantiate the Configuration and then pass it around, there is no added value over array, is it?
>
>And also: will there be one level of configuration for one part of framework? Will it be Zend_Form_Configuration, Zend_Form_Element_Configuration, Zend_Form_Element_Text_Configuration, Zend_Form_Element_Multi_Configuration, with extending? It would load ZFE_Configuration, ZFE_Xhtml_Configuation, ZFE_Multi_Configuration and finally ZFE_MultiCheckbox_Configuration. You just loaded 4 classes, that could have been swapped for array :)
>
>
>On Tue, Aug 9, 2011 at 10:19 PM, Pádraic Brady <[hidden email]> wrote:
>
>Passing the configuration object into the constructor or a setter would be preferable. There are certain cases, some pretty hairy, when you need to pass configuration around between a few classes. Having a ready made parameter object to throw about, and which encompasses the configuration processing logic, would keep the resulting duplication (of a crazy number of setters/getters) to a minimum.Of course, adopting a standard approach that isn't an array will require a few extra features (merging, cloning, etc.). I could see that working however.
>>
>>The obvious complaint likely:
>>
>>$foo = new Zend\Foo(new Zend\Foo\Configuration($config));
>>
>>It's more verbose than passing in the $config variable alone, and it would depend on Zend\Config (optionally) bringing in another layer. Zend\Di can hide this quite well, but a DIC won't cover up the slightly more complex starting situation for most components. The benefits seem worth it however.
>>
>>If I could hazard a guess, someone will end up proposing a Zend\Config that can automatically link configuration sections to the most suitable Configuration container.
>>
>>
>>Paddy
>>
>> 
>>Pádraic Brady
>>
>>http://blog.astrumfutura.com
>>http://www.survivethedeepend.com
>>Zend Framework Community Review Team
>>
>>
>>
>>>________________________________
>>>From: Matthew Weier O'Phinney <[hidden email]>
>>>To: [hidden email]
>>>Sent: Tuesday, August 9, 2011 8:52 PM
>>>Subject: Re: [zf-contributors] Unified API
>>
>>>
>>>-- Benoît Durand <[hidden email]> wrote
>>>(on Tuesday, 09 August 2011, 09:05 PM +0200):
>>>> I follow the discussion about a unified API for broker/plugin method
>>>> in the thread around Dojo.
>>>>
>>>> I have a question in the same way about configuration. What we do
>>>> for configuration? Do we use the word of options/setOptions or
>>>> config/setConfig? I see that both are used in various components. I
>>>> think it's more simple to have always the same method name to
>>>> configure an object.
>>>> If we have an interface for methods' broker, do we need an interface
>>>> for the configuration method?
>>>>
>>>> Remember the proposal on this subject :
>>>>    http://framework.zend.com/wiki/display/ZFPROP/Zend_Stdlib_Configurator+-+Vincent+de+Lau
>>>
>>>In working on the DI solution, Ralph and I stumbled upon/played with a
>>>few different configuration patterns. One thing we're discovering is
>>>that it kind of sucks to have configuration of an object _within_ the
>>>object. There's a bunch of boilerplate that happens that's not really
>>>the responsibility of the object itself -- it just wants values.
>>>
>>>One thing we looked at was having discrete configuration classes
>>>per-component. We could then support a couple different use cases:
>>>
>>>    $client     = new HttpClient();
>>>    $httpConfig = new HttpConfiguration($zendConfig->http);
>>>
>>>    // Have the configuration object configure the client:
>>>    $httpConfig->configure($client);
>>>
>>>    // Or pass configuration to the client:
>>>    $client->configure($httpConfig);
>>>
>>>    // potentially at instantiation:
>>>    $client = new HttpClient($httpConfig);
>>>
>>>There are a few benefits to these approaches. One is that we can very
>>>easily store default values in these configuration objects. Another is
>>>that we can typehint the configuration -- we know that the only
>>>configuration object that a given class can receive must derive from a
>>>specific type. Also, this style plays well with DI -- you can either
>>>pass configurable values to the configuration object, and then inject
>>>that object into desired classes, or extend the configuration and simply
>>>specify your alternate class. Finally, having configuration classes
>>>makes it trivially easy to document available options both at the API
>>>level as well as generating end-user docs.
>>>
>>>Regardless, we'd like to have a _consistent_ story for configuration
>>>across the board; there are too many patterns currently within the
>>>framework, making it very difficult to know what patterns will work with
>>>a given component without first introspecting the code and/or
>>>documentation.
>>>
>>>--
>>>Matthew Weier O'Phinney
>>>Project Lead            | [hidden email]
>>>Zend Framework          | http://framework.zend.com/
>>>PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
>>>
>>>--
>>>List: [hidden email]
>>>Info: http://framework.zend.com/archives
>>>Unsubscribe: [hidden email]
>>>
>>>
>>>
>>>
>>>
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Artur Bodera
In reply to this post by weierophinney
On Tue, Aug 9, 2011 at 11:34 PM, Matthew Weier O'Phinney
<[hidden email]>wrote:

> And to elaborate a little: I've heard plenty of end-users complaining
> about having arrays for configuration. Nesting levels can get hairy,
> option keys are hard to discover (and often easy to mistype), and it's
> not entirely clear what or how that one bit array will affect the object
> necessarily.
>

Ramblings ... from developer's perspective.


  $foo = new Service(new ServiceConfig(array()))

This is far from friendly, brings complexity while still needing an array
with
proper key=>val pairs, so we're basically running in circles.

  $config = new ServiceConfig();
  $config->setSomething = 15;
  $foo = new Service($config);

Now this...
I don't believe config classes will bring anything in the usability
department.
Now I have to remember to use the proper class, or else I get an exception
thrown in my face.

Of course config class will throw an exception also if I mistype something
or
try to set up something that should not be set up. But I STILL have to
remember what
I can and can not use with ServiceConfig. Or I get an exception.

On the other hand I see little difference between:

  $config = new ServiceConfig();
  $config->setSomething = 15;
  $foo = new Service($config);

and
  $foo = new Service();
  $foo->setSomething(15);


Which brings me to the "education" part. Other OO languages offer named
parameters
(a goner in PHP 5.3 proposal) for that purpose. Now an assoc. array is an
emulation of named
parameters. If we want a constructor to behave when unknown options are
passed, we can
just dictionary-check all $config array keys - If there is anything odd -
throw BadMethodCall or smth.

ClassConfig structures will not substitute education, just slightly alter my
IDE hints.

I think the object-in-object-configuring-an-object complexity is an overkill
and can potentially
draw people away from ZF. Arrays (aka poor-man's named parameters) are too
common among other php frameworks and libs to force everyone to use unique
SpecialConfigClasses for each and every component. Not mentioning namespace
pollution,
memory footprint, autoloading everything etc.

Skimming through ZF1 code, many constructors have adopted Zend\Config along
with
array, so at least there was a choice between those two.



> Yes, the 1:1 mapping of keys to setters _can_ help, but in practice, I
> find it often doesn't.


Full coverage of options with get/setters IS needed. I'd say it's a measure
of framework's quality.
It's not about if it can help or not, but how many people will just hit the
wall and get angry
when trying to fine-tune their objects with setSomething() method, just to
find out that
particular option has been "forgotten" and has no setter.

I personally use it very rarely, because I prefer explicit configuration at
construction
time with an array. But there are a cases when I have to swap something or
fine-tune
an instance, when those are invaluable.


A.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

padraicb
Just to summarise my points:

1. More than one PHP project uses configuration objects (HTMLPurifier, Doctrine, to name a few)
2. Internal arrays don't constitute an interface, so we need getters and setters wherever referred to (explicit for IDEs/performance reasons)
3. Where configuration is passed between objects, primary classes take on dual responsibility as data container (breaches single responsibility principle)

4. Related to 3, primary objects get passed around like data containers (breaches law of demeter on local recall)
5. Behaviour isn't portable with arrays, it gets duplicated across all classes needed to modify configuration on read/write (code smell)

6. Passing of primary objects complicates unit testing (increases mocking vs scalar setting) (code smell)

In summary, and not to say it's the absolute always-applies situation, using arrays to carry configuration is poor design. Depending on the scenario they break two OOP design principles and generate two code smells.

I think you also missed Matthew's point (unless I also misinterpreted it!). A setter can take an option, process it, and set several new options. The 1:1 mapping can indeed be a nuisance when you are switching between the getter/setter API and the use of base arrays. The two don't necessarily match up well unless by coincidence or deliberate design...cough...sub-arrays.

Paddy

 
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team



>________________________________
>From: Artur Bodera <[hidden email]>
>To: [hidden email]
>Sent: Tuesday, August 9, 2011 11:05 PM
>Subject: Re: [zf-contributors] Unified API
>
>On Tue, Aug 9, 2011 at 11:34 PM, Matthew Weier O'Phinney
><[hidden email]>wrote:
>
>> And to elaborate a little: I've heard plenty of end-users complaining
>> about having arrays for configuration. Nesting levels can get hairy,
>> option keys are hard to discover (and often easy to mistype), and it's
>> not entirely clear what or how that one bit array will affect the object
>> necessarily.
>>
>
>Ramblings ... from developer's perspective.
>
>
>  $foo = new Service(new ServiceConfig(array()))
>
>This is far from friendly, brings complexity while still needing an array
>with
>proper key=>val pairs, so we're basically running in circles.
>
>  $config = new ServiceConfig();
>  $config->setSomething = 15;
>  $foo = new Service($config);
>
>Now this...
>I don't believe config classes will bring anything in the usability
>department.
>Now I have to remember to use the proper class, or else I get an exception
>thrown in my face.
>
>Of course config class will throw an exception also if I mistype something
>or
>try to set up something that should not be set up. But I STILL have to
>remember what
>I can and can not use with ServiceConfig. Or I get an exception.
>
>On the other hand I see little difference between:
>
>  $config = new ServiceConfig();
>  $config->setSomething = 15;
>  $foo = new Service($config);
>
>and
>  $foo = new Service();
>  $foo->setSomething(15);
>
>
>Which brings me to the "education" part. Other OO languages offer named
>parameters
>(a goner in PHP 5.3 proposal) for that purpose. Now an assoc. array is an
>emulation of named
>parameters. If we want a constructor to behave when unknown options are
>passed, we can
>just dictionary-check all $config array keys - If there is anything odd -
>throw BadMethodCall or smth.
>
>ClassConfig structures will not substitute education, just slightly alter my
>IDE hints.
>
>I think the object-in-object-configuring-an-object complexity is an overkill
>and can potentially
>draw people away from ZF. Arrays (aka poor-man's named parameters) are too
>common among other php frameworks and libs to force everyone to use unique
>SpecialConfigClasses for each and every component. Not mentioning namespace
>pollution,
>memory footprint, autoloading everything etc.
>
>Skimming through ZF1 code, many constructors have adopted Zend\Config along
>with
>array, so at least there was a choice between those two.
>
>
>
>> Yes, the 1:1 mapping of keys to setters _can_ help, but in practice, I
>> find it often doesn't.
>
>
>Full coverage of options with get/setters IS needed. I'd say it's a measure
>of framework's quality.
>It's not about if it can help or not, but how many people will just hit the
>wall and get angry
>when trying to fine-tune their objects with setSomething() method, just to
>find out that
>particular option has been "forgotten" and has no setter.
>
>I personally use it very rarely, because I prefer explicit configuration at
>construction
>time with an array. But there are a cases when I have to swap something or
>fine-tune
>an instance, when those are invaluable.
>
>
>A.
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Adam Lundrigan
In reply to this post by Artur Bodera
Big emphatic upvote for a unified configuration API from me, as long as it's
used consistently and used by every component accepting external
configuration.


<snip>

>
> This is far from friendly, brings complexity while still needing an array
> with
> proper key=>val pairs, so we're basically running in circles.
>
>  $config = new ServiceConfig();
>  $config->setSomething = 15;
>  $foo = new Service($config);
>
> <snip>

>  $config = new ServiceConfig();
>  $config->setSomething = 15;
>  $foo = new Service($config);
>
> and
>  $foo = new Service();
>  $foo->setSomething(15);
>
<snip>


Really, I don't see the big complexity difference between using an array

    new Service(array('key'=>'one'))

and using a configuration object which accepts the same array

    new Service(new ServiceConfig(array('key'=>'one')))

Yes, constructing and passing an array is a little more complex than just
passing an array, but the benefits  far outweigh that downside (Paddy and
Matthew have outlined those benefits in their messages, and Gmail tells me
that Paddy has summarized his points since I started writing this message,
so I will (almost) avoid repeating them).  With per-component configuration
objects we separate configuration from functionality, eliminating the
get/set boilerplate clutter (and validation that goes with it) which
distracts from the logic and purpose of the class.  Admittedly, that's not
important in terms of how the code operates, but for someone who spends more
time in the code than in the documentation when learning a framework it
helps substantially.


A possibility I see is a way to connect Zend\Di and Zend\Application into
this unified configuration API to essentially provide configuration
injection.  For example, I see in my mind something like this  ( this is
spilling off the top of my head, so go easy on it :P )

A configurator factory to map application.ini keys and keysets to
configuration classes (I based on Zend\Loader's factory pattern). ie:

        ConfiguratorFactory::factory(array(
            'RuntimeConfigurator'=>array(
                'namespaces'=>array(
                    'app.vehicle'=>'App\Vehicle\Configuration'
                )
            )
        ));

We could cache namespace maps and other performance-improvement things there
as well.

In the application bootstrap or a resource plugin a Configurator would pull
configs from Zend\Application and set up a provided Zend\Di instance with
initialization details for each configuration object.  When an object which
has an injectable method taking a configurator object argument, the DI
container would grab the configuration object and pass it.

Example:

namespace App\Vehicle;

class Vehicle
{
    protected $config;

    public function __construct(Configuration $c)
    {
        $this->config = $c;
    }
}

class Configuration
{
    protected $make;

    public function getMake() { return $this->make; }

    public function setMake($make) {
        $this->make = $make;
        return $this;
    }
}


Configuration validation logic could also be included in the Configuration
object, abstracting that boilerplate code out of every class that would use
that configuration object and centralizing it in one place.

With the above classes, and the DI container configured properly, we could
do something like this:

    $di->get('vehicle');

And get a App\Vehicle\Vehicle instance pre-configured with a
App\Vehicle\Configuration instance which has already been injected with the
application.ini variables from 'app.vehicle' namespace. Of course we could
always override it like this:

    $c = new \App\Vehicle\Configuration();
    $c->setMake('Dodge');
    $di->get('vehicle', $c);



I would find this type of setup very beneficial to the way I use ZF in my
applications.

Thoughts?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Alessandro Pellizzari
In reply to this post by Tomáš Fejfar
On Tue, 09 Aug 2011 23:12:59 +0200, Tomáš Fejfar wrote:

> Why do we care about number of set/get methods? It makes the ZF code
> less readable, but who cares (except the FW developers)... "end
> developer" doesn't. He cares whether the FW is fast and has small memory
> footprint. You see much complex stuff being done in setters, that can be
> reused? It's mostly class/interface check (in method parameter) and than
> assigning to member variable, isn't it?

Maybe mine is a stupid proposal (I am not so much into Design Patterns),
but I think you could hide all implementation details and use DI when
necessary.

For example, you can pass config through the constructor as an array:

$obj = new Zend\MyClass(array('a'=>'A value'))

and set them through a standard function:

$obj->setConfig('a', 'Other A value');
$obj->setConfig(array('b'=>'B value', 'c'=>'C value'));
$obj->setConfig(new Zend\Config(blabla));

Internally the Zend\MyClass could use direct parsing, or instantiate its
own Configuration class, or use a generic Zend\Config or even use a DI-
injected object to do its config management.

This way the end developer would not worry to check what's the name of
the configuration class, or if it exists or is needed, and the MyClass
can swap config class at will.

Bye.



--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Tomáš Fejfar
After reading Paddy's and Matthew's messages I got more insight about the
value of this proposition. I understand what it does and how it helps. But
still...

... I'm worried about bloating of the framework. If it will work as I
outlined in my first post, it will mean literally doubling the class count
and that's really bad IMO. It's doubling the size of autoload map, doubling
the number of autoload calls, doubling the number of IO ops.

Are you really convinced of the benefits vs. performance overhead? I'm not
and I'm still agains - not for the fact that it's slightly more typing, but
because of the bloating.

Tom


On Wed, Aug 10, 2011 at 10:17 AM, Alessandro Pellizzari <[hidden email]>wrote:

> On Tue, 09 Aug 2011 23:12:59 +0200, Tomáš Fejfar wrote:
>
> > Why do we care about number of set/get methods? It makes the ZF code
> > less readable, but who cares (except the FW developers)... "end
> > developer" doesn't. He cares whether the FW is fast and has small memory
> > footprint. You see much complex stuff being done in setters, that can be
> > reused? It's mostly class/interface check (in method parameter) and than
> > assigning to member variable, isn't it?
>
> Maybe mine is a stupid proposal (I am not so much into Design Patterns),
> but I think you could hide all implementation details and use DI when
> necessary.
>
> For example, you can pass config through the constructor as an array:
>
> $obj = new Zend\MyClass(array('a'=>'A value'))
>
> and set them through a standard function:
>
> $obj->setConfig('a', 'Other A value');
> $obj->setConfig(array('b'=>'B value', 'c'=>'C value'));
> $obj->setConfig(new Zend\Config(blabla));
>
> Internally the Zend\MyClass could use direct parsing, or instantiate its
> own Configuration class, or use a generic Zend\Config or even use a DI-
> injected object to do its config management.
>
> This way the end developer would not worry to check what's the name of
> the configuration class, or if it exists or is needed, and the MyClass
> can swap config class at will.
>
> Bye.
>
>
>
> --
> List: [hidden email]
> Info: http://framework.zend.com/archives
> Unsubscribe: [hidden email]
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Artur Bodera
In reply to this post by padraicb
On Wed, Aug 10, 2011 at 12:44 AM, Pádraic Brady <[hidden email]>wrote:

> Just to summarise my points:
>
> 1. More than one PHP project uses configuration objects (HTMLPurifier,
> Doctrine, to name a few)
> 2. Internal arrays don't constitute an interface, so we need getters and
> setters wherever referred to (explicit for IDEs/performance reasons)
> 3. Where configuration is passed between objects, primary classes take on
> dual responsibility as data container (breaches single responsibility
> principle)
> 4. Related to 3, primary objects get passed around like data containers
> (breaches law of demeter on local recall)
> 5. Behaviour isn't portable with arrays, it gets duplicated across all
> classes needed to modify configuration on read/write (code smell)
> 6. Passing of primary objects complicates unit testing (increases mocking
> vs scalar setting) (code smell)
>

I agree on all your points.

Thank you Paddy for summarizing. Because it's a discussion,
I'll summarize my points too:

   1. Array configuration (aka poor-man's named parameters) are more
   common/popular.
   2. To satisfy the requirement of consistency, each (configurable)
   component has to have its own config class - this means +30% class count
   (namespace pollution, performance degradation).
   3. Custom method calls, native function calls and object instantiations
   are very expensive as compared to array() and isset() (performance, memory).
   4. It "increases" learning curve in terms of framework usability,
   developer-side (UX)
   5. It "increases" learning curve in terms of extendability, think custom
   extensions (UX, time-to-market).
   6. It decreases readability, increases code volume.
   7. Because config objects are injected inside parent objects, how do I
   change the config at runtime? $obj->getConfig()->setSomething() ? (as
   opposed to $obj->setSomething(), readability, usability )
   8. Using config object internally, while allowing array() configuration
   as an option, might help with education, but will still decrease
   performance.


Objects are up to twice slower at init and take up to double memory:
https://gist.github.com/1136563

Of course that's without autoloading and only using SPL ArrayObject which
is somewhat
lightweight (compiled-in).


Because I believe my points are also valid, we are now at the point of a
real discussion and
weighting pros and cons of both approaches. I'd also vote for maximum
consistency, so
regardless of which we decide upon, it should be implemented across the
board and stay that
way during the whole ZF2 lifecycle.

I believe in code maturing, I'm against ZF being "component warehouse". I'm
also against
conformism and trying to make PHP something it will never be (think Java
;-), it's 2011 and
still no String class in PHP? ). Also keep in mind that operational
performance can be easily
measured, while development performance (i.e. time for an average developer
to understand
and build something useful) is very hard to assess.


KISS is useful, gradual learning curve is also very valuable for a
framework. In our context that
would mean a compromise, where a beginner developer could start with
something like
    $a = new Adapter();
    $s = new Service();
    $s->setOption('foo','bar');
    $s->setAdapter($s);

... then we could go into application (ini) config, and we get into the
point of :
    $s = new Service(array(
         'foo' => 'bar',
         'adapter' => array(
             'name' => 'adapter',
             'options' => array(  )
         )
    ));

... and then recommend the most appropriate and optimized way:
    $c = new ServiceConfig(array( ... ) );
    $s = new Service($c);

..  and then possibly a more DI way with custom components.

Although as I write these examples, I've got this itching and strange
feeling that if I write docs for
say OAuth or HTTP it kinda looks ok. But with much simpler classes,
requiring 1 or 2 parameters,
config-class-syntax simply looks... obese... or like if someone was speaking
java to me :-)

A.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Tomáš Fejfar
Thanks for addressing the performance issues.

On Wed, Aug 10, 2011 at 1:07 PM, Artur Bodera <[hidden email]> wrote:

> On Wed, Aug 10, 2011 at 12:44 AM, Pádraic Brady <[hidden email]
> >wrote:
>
> > Just to summarise my points:
> >
> > 1. More than one PHP project uses configuration objects (HTMLPurifier,
> > Doctrine, to name a few)
> > 2. Internal arrays don't constitute an interface, so we need getters and
> > setters wherever referred to (explicit for IDEs/performance reasons)
> > 3. Where configuration is passed between objects, primary classes take on
> > dual responsibility as data container (breaches single responsibility
> > principle)
> > 4. Related to 3, primary objects get passed around like data containers
> > (breaches law of demeter on local recall)
> > 5. Behaviour isn't portable with arrays, it gets duplicated across all
> > classes needed to modify configuration on read/write (code smell)
> > 6. Passing of primary objects complicates unit testing (increases mocking
> > vs scalar setting) (code smell)
> >
>
> I agree on all your points.
>
> Thank you Paddy for summarizing. Because it's a discussion,
> I'll summarize my points too:
>
>   1. Array configuration (aka poor-man's named parameters) are more
>   common/popular.
>   2. To satisfy the requirement of consistency, each (configurable)
>   component has to have its own config class - this means +30% class count
>   (namespace pollution, performance degradation).
>   3. Custom method calls, native function calls and object instantiations
>   are very expensive as compared to array() and isset() (performance,
> memory).
>   4. It "increases" learning curve in terms of framework usability,
>   developer-side (UX)
>   5. It "increases" learning curve in terms of extendability, think custom
>   extensions (UX, time-to-market).
>   6. It decreases readability, increases code volume.
>   7. Because config objects are injected inside parent objects, how do I
>   change the config at runtime? $obj->getConfig()->setSomething() ? (as
>   opposed to $obj->setSomething(), readability, usability )
>   8. Using config object internally, while allowing array() configuration
>   as an option, might help with education, but will still decrease
>   performance.
>
>
> Objects are up to twice slower at init and take up to double memory:
> https://gist.github.com/1136563
>
> Of course that's without autoloading and only using SPL ArrayObject which
> is somewhat
> lightweight (compiled-in).
>
>
> Because I believe my points are also valid, we are now at the point of a
> real discussion and
> weighting pros and cons of both approaches. I'd also vote for maximum
> consistency, so
> regardless of which we decide upon, it should be implemented across the
> board and stay that
> way during the whole ZF2 lifecycle.
>
> I believe in code maturing, I'm against ZF being "component warehouse". I'm
> also against
> conformism and trying to make PHP something it will never be (think Java
> ;-), it's 2011 and
> still no String class in PHP? ). Also keep in mind that operational
> performance can be easily
> measured, while development performance (i.e. time for an average developer
> to understand
> and build something useful) is very hard to assess.
>
>
> KISS is useful, gradual learning curve is also very valuable for a
> framework. In our context that
> would mean a compromise, where a beginner developer could start with
> something like
>    $a = new Adapter();
>    $s = new Service();
>    $s->setOption('foo','bar');
>    $s->setAdapter($s);
>
> ... then we could go into application (ini) config, and we get into the
> point of :
>    $s = new Service(array(
>         'foo' => 'bar',
>         'adapter' => array(
>             'name' => 'adapter',
>             'options' => array(  )
>         )
>    ));
>
> ... and then recommend the most appropriate and optimized way:
>    $c = new ServiceConfig(array( ... ) );
>    $s = new Service($c);
>
> ..  and then possibly a more DI way with custom components.
>
> Although as I write these examples, I've got this itching and strange
> feeling that if I write docs for
> say OAuth or HTTP it kinda looks ok. But with much simpler classes,
> requiring 1 or 2 parameters,
> config-class-syntax simply looks... obese... or like if someone was
> speaking
> java to me :-)
>
> A.
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

padraicb
In reply to this post by Tomáš Fejfar
Need to be careful...premature optimisation is the devil ;).


You're assuming a doubling of classes and a performance decrease. Many components have >1 classes so the actual increase is far smaller overall. Secondly, performance is dictated by both design and function. We never really had a culture of performance optimisation in Zend Framework until recently so I'd be willing to bet that optimising function (and improving design) would, in some cases at least, offset the performance penalty of another class/object. Matthew/Ralph have already done a lot of optimisation works that we'll be using in ZF2 of a more global nature if we are benchmarking per request.


That's also speculation on my part though. It's no secret I regularly make fun of framework benchmarks ;). Paul M. Jones put us on the road to optimisation but sometimes we misuse the development movement he helped spawn to proclaim the performance of a framework in unrealistic situations for marketing purposes. Take a peek at Symfony 2's website - it's at the top of their list for why you should use Symfony :P.

In the bigger picture, I'm not convinced that a number of extra classes per request will make that big of a dent. If I'm proven wrong, I of course never said any of this :P.


Paddy



 
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team



>________________________________
>From: Tomáš Fejfar <[hidden email]>
>To: Alessandro Pellizzari <[hidden email]>
>Cc: [hidden email]
>Sent: Wednesday, August 10, 2011 10:42 AM
>Subject: Re: [zf-contributors] Re: Unified API
>
>After reading Paddy's and Matthew's messages I got more insight about the
>value of this proposition. I understand what it does and how it helps. But
>still...
>
>... I'm worried about bloating of the framework. If it will work as I
>outlined in my first post, it will mean literally doubling the class count
>and that's really bad IMO. It's doubling the size of autoload map, doubling
>the number of autoload calls, doubling the number of IO ops.
>
>Are you really convinced of the benefits vs. performance overhead? I'm not
>and I'm still agains - not for the fact that it's slightly more typing, but
>because of the bloating.
>
>Tom
>
>
>On Wed, Aug 10, 2011 at 10:17 AM, Alessandro Pellizzari <[hidden email]>wrote:
>
>> On Tue, 09 Aug 2011 23:12:59 +0200, Tomáš Fejfar wrote:
>>
>> > Why do we care about number of set/get methods? It makes the ZF code
>> > less readable, but who cares (except the FW developers)... "end
>> > developer" doesn't. He cares whether the FW is fast and has small memory
>> > footprint. You see much complex stuff being done in setters, that can be
>> > reused? It's mostly class/interface check (in method parameter) and than
>> > assigning to member variable, isn't it?
>>
>> Maybe mine is a stupid proposal (I am not so much into Design Patterns),
>> but I think you could hide all implementation details and use DI when
>> necessary.
>>
>> For example, you can pass config through the constructor as an array:
>>
>> $obj = new Zend\MyClass(array('a'=>'A value'))
>>
>> and set them through a standard function:
>>
>> $obj->setConfig('a', 'Other A value');
>> $obj->setConfig(array('b'=>'B value', 'c'=>'C value'));
>> $obj->setConfig(new Zend\Config(blabla));
>>
>> Internally the Zend\MyClass could use direct parsing, or instantiate its
>> own Configuration class, or use a generic Zend\Config or even use a DI-
>> injected object to do its config management.
>>
>> This way the end developer would not worry to check what's the name of
>> the configuration class, or if it exists or is needed, and the MyClass
>> can swap config class at will.
>>
>> Bye.
>>
>>
>>
>> --
>> List: [hidden email]
>> Info: http://framework.zend.com/archives
>> Unsubscribe: [hidden email]
>>
>>
>>
>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

weierophinney
Administrator
In reply to this post by Artur Bodera
-- Artur Bodera <[hidden email]> wrote
(on Wednesday, 10 August 2011, 01:07 PM +0200):

> On Wed, Aug 10, 2011 at 12:44 AM, Pádraic Brady <[hidden email]>wrote:
> > Just to summarise my points:
> >
> > 1. More than one PHP project uses configuration objects (HTMLPurifier,
> > Doctrine, to name a few)
> > 2. Internal arrays don't constitute an interface, so we need getters and
> > setters wherever referred to (explicit for IDEs/performance reasons)
> > 3. Where configuration is passed between objects, primary classes take on
> > dual responsibility as data container (breaches single responsibility
> > principle)
> > 4. Related to 3, primary objects get passed around like data containers
> > (breaches law of demeter on local recall)
> > 5. Behaviour isn't portable with arrays, it gets duplicated across all
> > classes needed to modify configuration on read/write (code smell)
> > 6. Passing of primary objects complicates unit testing (increases mocking
> > vs scalar setting) (code smell)
>
> I agree on all your points.
>
> Thank you Paddy for summarizing. Because it's a discussion,
> I'll summarize my points too:
>
>    1. Array configuration (aka poor-man's named parameters) are more
>    common/popular.

Yes, but nobody here is listening to a key argument I made: while
popular, they are:
 
 * they "bloat" the class being configured, as the established pattern
   is a 1:1 relationship between configuration key and setter method
 * easy to mis-type
 * provide no assistance to coding environments (e.g., you can't usually
   get code completion for configuration array keys)

These last two items lead to one really, really important problem:
combined, they make finding and understanding available configuration
options very difficult for end users. Yes, many folks *on* *this* *list*
get and like the pattern, but go and ask folks on fw-general or in
#zftalk -- you'll get a very different story.

>    2. To satisfy the requirement of consistency, each (configurable)
>    component has to have its own config class - this means +30% class count
>    (namespace pollution, performance degradation).

This has yet to be proven; it's all speculation at this point. We may
end up with only 5-10% more classes. And in a given execution cycle, we
may only have a handful that need configuration. I think arguments like
this need to wait until we have more information and have tried the
pattern out on multiple components.

>    3. Custom method calls, native function calls and object instantiations
>    are very expensive as compared to array() and isset() (performance, memory).

And what about array configuration?

 * Most classes that accept configuration proxy to setter methods. If
   "N" is the number of configuration keys, you're guaranteed N+1 method
   calls (assuming you pass to the constructor). Plus, there are the
   method_exists() calls, etc.
 * Most classes accepting configuration also allow passing a Zend_Config
   object -- which, arguably, is the most often passed. They then call
   toArray() on that object. That specific call is incredibly expensive
   -- and it may happen many, many times. It also means you're
   duplicating at least subsections of configuration in memory.

What I'm saying here is that while we can point to potential problems in
a new solution, the old solution isn't without its own.

>    4. It "increases" learning curve in terms of framework usability,
>    developer-side (UX)

Potentially. We haven't explored all the possibilities yet. We may allow
for passing the configuration _array_ (or traversable object) to the
component, and have it then pass that to the configuration class. There
are a variety of ways we can make this usable.

>    5. It "increases" learning curve in terms of extendability, think custom
>    extensions (UX, time-to-market).

I'm failing to see what you mean here; can you elaborate?

>    6. It decreases readability, increases code volume.

I'd argue that it _increases_ readability, particularly when you're
trying to understand what options are available, as well as when working
with options. You likely won't need to worry about casing issues (the
configuration class would take care of that), you'd get type-hinting,
API docs you can read to learn about options, etc.

>    7. Because config objects are injected inside parent objects, how do I
>    change the config at runtime? $obj->getConfig()->setSomething() ? (as
>    opposed to $obj->setSomething(), readability, usability )

That will depend on the component and what configuration it allows at
runtime.

>    8. Using config object internally, while allowing array() configuration
>    as an option, might help with education, but will still decrease
>    performance.

We'd need to quantify this. It may not be an issue; it may be a big one.
Right now, everything is speculation -- as noted above, the current
solution of using an array or Zend_Config object is not necessarily
terribly performant, either.

> Objects are up to twice slower at init and take up to double memory:
> https://gist.github.com/1136563

But what are the amounts of time and memory we're talking about in a
single request? Is this a micro-optimization, or a real concern? Without
any empirical data to point at for the use cases of the framework, we
can't tell.

> Of course that's without autoloading and only using SPL ArrayObject
> which is somewhat lightweight (compiled-in).
>
> Because I believe my points are also valid, we are now at the point of
> a real discussion and weighting pros and cons of both approaches.

I think before we can have a real discussion, we need more empirical
performance benchmarks about both ZF1-style configuration (status quo)
vs using configuration objects. This is something I can likely take on
soon -- the zf-quickstart project is built in large part to provide me
with something we can benchmark.

> I'd also vote for maximum consistency, so regardless of which we
> decide upon, it should be implemented across the board and stay that
> way during the whole ZF2 lifecycle.

Absolutely.

> I believe in code maturing, I'm against ZF being "component
> warehouse". I'm also against conformism and trying to make PHP
> something it will never be (think Java ;-), it's 2011 and still no
> String class in PHP? ). Also keep in mind that operational performance
> can be easily measured, while development performance (i.e. time for
> an average developer to understand and build something useful) is very
> hard to assess.

Correct -- and it's also possible to do build/deployment-time
optimizations that can mitigate many of the operational performance
concerns while helping retain developer performance.

> KISS is useful, gradual learning curve is also very valuable for a
> framework. In our context that would mean a compromise, where a
> beginner developer could start with something like
>     $a = new Adapter();
>     $s = new Service();
>     $s->setOption('foo','bar');
>     $s->setAdapter($s);
>
> ... then we could go into application (ini) config, and we get into the
> point of :
>     $s = new Service(array(
>          'foo' => 'bar',
>          'adapter' => array(
>              'name' => 'adapter',
>              'options' => array(  )
>          )
>     ));

Please read my points above about array keys being difficult to learn.
The fact is, the beginner developer very likely will _not_ start with
the example that requires more code, but with a configuration-based
approach. (This is in fact why so many folks have trouble understanding
Zend_Form -- they are thinking of it entirely in terms of configuration
options and not the programmatic aspects those map to.)

> ... and then recommend the most appropriate and optimized way:
>     $c = new ServiceConfig(array( ... ) );
>     $s = new Service($c);

Actually, more optimized would be extending ServiceConfig locally to
provide app-specific defaults, which in turn makes...

> ..  and then possibly a more DI way with custom components.

... much simpler and easier to configure and trace. :)

> Although as I write these examples, I've got this itching and strange
> feeling that if I write docs for say OAuth or HTTP it kinda looks ok.
> But with much simpler classes, requiring 1 or 2 parameters,
> config-class-syntax simply looks... obese... or like if someone was
> speaking java to me :-)

If a class only has a few parameters, these may be something to pass to
the constructor _explicitly_ instead of using a configuration object.
Our DI container already supports configuration injection, so that would
work quite easily.

My main points in my response here are:

 * We can't debate operational performance until we benchmark both
   solutions.
 * We can likely provide a "convenience API" surrounding configuration
   that looks similar to what we use today, but instead feeds
   configuration objects.
 * Consistency and learnability should be key aspects of any solution
   used.

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Alessandro Pellizzari
On Wed, 10 Aug 2011 08:40:13 -0500, Matthew Weier O'Phinney wrote:

> Yes, but nobody here is listening to a key argument I made: while
> popular, they are:
>  
>  * they "bloat" the class being configured, as the established pattern
>    is a 1:1 relationship between configuration key and setter method
>  * easy to mis-type
>  * provide no assistance to coding environments (e.g., you can't usually
>    get code completion for configuration array keys)
>
> These last two items lead to one really, really important problem:
> combined, they make finding and understanding available configuration
> options very difficult for end users. Yes, many folks *on* *this* *list*
> get and like the pattern, but go and ask folks on fw-general or in
> #zftalk -- you'll get a very different story.

I understand what you mean. My main concern is not on performance but in
programming speed.

Having IDE assistance is good, but it should not be the base to work on.
I personally hate getters/setters. I understand why they are used, but
don't like them either. They bloat the classes. I would prefer a better
documentation telling me what I can and can't do.

If you don't want to use arrays, then the code would become something like

$config = new Class\Config();
$config->setA('a');
$config->setB('b');
$config->setC('c');
$obj = new Class($config);

instead of

$obj = new Class(array(
 'a' => 'a',
 'b' => 'b',
 'c' => 'c'
));

I find the array notation more readable. And is supports a tree-like
structure.
And it doesn't force me to know the internals of the config object (so I
don't have to write something like $obj->getConfig()->getA())

I think an Interface and good doc blocks would help much more:

interface Configurable
{
 public function setConfig(array $config);
 public function getConfig(array $config);
}

class Class implements Configurable
{
 /**
 * Description...
 * $config can be an array:
 * ['a'] => value for a
 * ['b'] => value for b
 * ['c'] => array of sub-configurations for c:
 * ['c'][1] => first config for c
 * ...
 */
 public function getConfig(array $config) { ... }
}

This way, writing

$obj->setConfig([CTRL-space]

would bring up the popup explaining what options I can use.

This would not bloat up the class code more than what ZF-1 does, as every
getter and setter already has doc blocks, and they can be stripped on
production servers.

And I would not need to check the manual to find out if the class needs a
Configuration class or not.

Sorry if I have not been clear. It would be difficult to explain it in
italian, I am having a hard time explaining it in english. :)

Bye.



--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unified API

Marco Pivetta
This post has NOT been accepted by the mailing list yet.
@Alessandro, I just worked with some huge projects involving Zend Framework and Doctrine2, and I'd rather pay to get someone to rewrite all the code to use setters and getters only rather than adding a single magic method. If I need to traverse objects in an "ArrayAccess way" I prefer to use some kind of reflection, and I also spent hours debugging stupid bugs caused by misconfiguration :) The idea of the "Configurable" interface is good, but I'd also add the configuration object class to the constructor signature...

I really like the idea of having a configuration class that can validate my input config, enforce me to do things or filter input provided before it is used by a "consumer" class. This allows me to hook in callbacks and additional functionality without having the end user of the classes worrying about i.e. creating directories where caches should be placed (the configuration object could do this for me or throw an exception if the path is not writeable/readable or similars). The DIC and the EventManager provide additional flexibility to this pattern :)

I really like this approach of end class "consuming" a configuration object. I'd really like to see it applied in ZF2! Performance also isn't that much of a change imho... How many configuration objects do you need to instantiate at runtime? Shouldn't the DIC be able to help you out of that trouble? Is that really the problem or should we focus on removing clutter on other more often called constructors/methods?

Just my thoughts. Quoting Alessandro's last sentence as like him I'm a "Maccheroni English" speaker :)

Marco Pivetta
http://twitter.com/Ocramius
http://marco-pivetta.com



On 10 August 2011 16:36, Alessandro Pellizzari [via Zend Framework Community] <[hidden email]> wrote:
On Wed, 10 Aug 2011 08:40:13 -0500, Matthew Weier O'Phinney wrote:

> Yes, but nobody here is listening to a key argument I made: while
> popular, they are:
>  
>  * they "bloat" the class being configured, as the established pattern
>    is a 1:1 relationship between configuration key and setter method
>  * easy to mis-type
>  * provide no assistance to coding environments (e.g., you can't usually
>    get code completion for configuration array keys)
>
> These last two items lead to one really, really important problem:
> combined, they make finding and understanding available configuration
> options very difficult for end users. Yes, many folks *on* *this* *list*
> get and like the pattern, but go and ask folks on fw-general or in
> #zftalk -- you'll get a very different story.
I understand what you mean. My main concern is not on performance but in
programming speed.

Having IDE assistance is good, but it should not be the base to work on.
I personally hate getters/setters. I understand why they are used, but
don't like them either. They bloat the classes. I would prefer a better
documentation telling me what I can and can't do.

If you don't want to use arrays, then the code would become something like

$config = new Class\Config();
$config->setA('a');
$config->setB('b');
$config->setC('c');
$obj = new Class($config);

instead of

$obj = new Class(array(
 'a' => 'a',
 'b' => 'b',
 'c' => 'c'
));

I find the array notation more readable. And is supports a tree-like
structure.
And it doesn't force me to know the internals of the config object (so I
don't have to write something like $obj->getConfig()->getA())

I think an Interface and good doc blocks would help much more:

interface Configurable
{
 public function setConfig(array $config);
 public function getConfig(array $config);
}

class Class implements Configurable
{
 /**
 * Description...
 * $config can be an array:
 * ['a'] => value for a
 * ['b'] => value for b
 * ['c'] => array of sub-configurations for c:
 * ['c'][1] => first config for c
 * ...
 */
 public function getConfig(array $config) { ... }
}

This way, writing

$obj->setConfig([CTRL-space]

would bring up the popup explaining what options I can use.

This would not bloat up the class code more than what ZF-1 does, as every
getter and setter already has doc blocks, and they can be stripped on
production servers.

And I would not need to check the manual to find out if the class needs a
Configuration class or not.

Sorry if I have not been clear. It would be difficult to explain it in
italian, I am having a hard time explaining it in english. :)

Bye.



--
List: [hidden email]
Unsubscribe: [hidden email]





If you reply to this email, your message will be added to the discussion below:
http://zend-framework-community.634137.n4.nabble.com/Unified-API-tp3730937p3733086.html
To start a new topic under ZF Contributor, email [hidden email]
To unsubscribe from ZF Contributor, click here.

12
Loading...