Some thoughts about ZF

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Some thoughts about ZF

Александр Шелковский
Hello.

Today I read small article about trend of increasing complexity in PHP frameworks (here is a link http://funkatron.com/posts/the-microphp-manifesto.html), and as illustration of this process a portion of code from Zend FW bootstrap used.

I understand why Zend FW seems quite complex for new developers, and also I understand the reason of why it being complex. But also I think that sometimes it is a bit too much, and Zend team forgot one of the main principle of software development: "Keep it simple", and try to follow another anti-pattern: predict all possible use cases and be much much flexible than required. Frameworks stand for frames, and I feel that there is too much freedom in Zend framework, and it is a big problem. Instead of havening one and obvious way to solve the problem we have dozen.

I want to show it on example of one of core ZF2 components -- Loader (of course that is not a final version, but you can get a point):
Lets just open a dir with component, what functionality we expect when dealing with Autoloaders? It should just  load classes based on simple rules. We have simple rules for loading classes: PSR-0. But when I open dir I see 15+ files and one dir, component have ~5 classes and few interfaces. We can easily
exclude some classes, because they don't work with loading classes directly they work with loading modules, plugins and etc. I don't say that we must remove this classes from Loader component, I just say that, when I want components which loads classes I don't expect something like PluginBroker. But even when I look in StandardAutoloader, it feels overcomplcated for me. What is fallback autoloader? Why it should work for prefixes and namespces? Isn't name spaces is more then enough? Do we have code with prefixes inside of ZF? If not why ZF should support this? Don't external library have their own autoloader, which will support required rules? So when I open this component in order to solve simple problem: "How to load some class", I have a bit frustrated. Even this small component looks not very easy to understand for new developer. But when we talk about something bigger, it is just a nightmare. I think we should reduce complexity of the FW, and very carefully use methods which works as catalyst for complexity. By catalyst I mean things like event system, now many of core components are heavily use it.

Thank you and sorry for my English.
 
Reply | Threaded
Open this post in threaded view
|

Re: Some thoughts about ZF

weierophinney
Administrator
-- Александр Шелковский <[hidden email]> wrote
(on Thursday, 01 March 2012, 02:55 PM +0600):
> I understand why Zend FW seems quite complex for new developers, and also I
> understand the reason of why it being complex. But also I think that sometimes
> it is a bit too much, and Zend team forgot one of the main principle of
> software development: "Keep it simple", and try to follow another anti-pattern:
> predict all possible use cases and be much much flexible than required.

There's two things going on in ZF2 right now.

 * We're trying to create a core that is de-coupled on which we can
   build applications and/or application architectures.

 * We're _planning_ on a layer on top of these pieces to make it more
   usable and easy to use for developers.

Believe it or not, the goal of the first point is actually KISS -- each
component should do one thing, and one thing well. This is why the
PhpRenderer looks very different today in ZF2 than Zend_View did in ZF1
-- instead of trying to do everything itself, it now composes other
objects to take care of discrete tasks:

 * Instead of resolving view scripts itself, and maintaining all the
   code for manipulating stacks of paths, it delegates this to
   resolvers. This has the side benefit of allowing different resolution
   strategies -- which helps developers address either performance
   concerns or differences in application architecture.

 * Instead of acting as a loader and registry for helpers, it delegates
   this to a PluginBroker. This allows using a consistent paradigm --
   the broker -- across many components, easing the learning curve. It
   also means, again, the ability to drop in an alternate implementation
   when desired.

 * Instead of composing and managing a filter chain for output
   filtering, it delegates this to FilterChain instance.

 * Instead of composing and assigning view variables directly to itself,
   it composes them.

Basically, each performs one responsibility well.

From the outside, this looks more complex:

    $renderer = new PhpRenderer();
    $renderer->setResolver(new TemplatePathStack(array(__DIR__ .  '/view'));
    $renderer->getBroker()->getClassLocator()->registerPlugin('foo', 'My\Helper\Foo');

    $model = new ViewModel(array('foo' => 'bar'));
    $model->setTemplate('foo/bar');

    $renderer->render($model);

But when you know what each piece does, it makes sense. Should you have
to know what each piece does? In most cases, no. And that's where the
second point comes in: the convenience API, where we make things simpler
for developers to consume. This doesn't mean getting rid of the
de-coupling; it means having a layer that introduces coupling in order
to make things simpler to consume.

The nice part about design decisions like this is that we can cater to
the developers wanting rapid application development, as well as those
needing to customize the framework workflow for performance or business
reasons.

> Frameworks stand for frames, and I feel that there is too much freedom
> in Zend framework, and it is a big problem. Instead of havening one
> and obvious way to solve the problem we have dozen.

However, this is precisely the niche ZF is trying to fill. We don't want
to provide one way of doing things, because we recognize that developers
have many, often competing, needs. We're not a convention over
configuration framework like Rails.

> I want to show it on example of one of core ZF2 components -- Loader
> (of course that is not a final version, but you can get a point): Lets
> just open a dir with component, what functionality we expect when
> dealing with Autoloaders? It should just  load classes based on simple
> rules. We have simple rules for loading classes: PSR-0. But when I
> open dir I see 15+ files and one dir, component have ~5 classes and
> few interfaces. We can easily exclude some classes, because they don't
> work with loading classes directly they work with loading modules,
> plugins and etc. I don't say that we must remove this classes from
> Loader component, I just say that, when I want components which loads
> classes I don't expect something like PluginBroker.

Where would you put the plugin broker, then? It deals with loading and
returning object instances. DI might be a good place, but the broker
isn't really about DI.

As for multiple autoloader implementations -- the reason is because
there is no one-size-fits-all solution. PSR-0, while it gives a nice
convention for how to organize code on the filesystem, has a terrible
default implementation when it comes to performance, as it requires
filesystem stat calls that may fail -- even if another autoloader
further down the chain can handle it. Approaches like the
ClassMapAutoloader are much more performant -- at the trade-off of
requiring either manually adding classes to the map, using a script to
update the map, or needing to use it along with another approach like
the StandardAutoloader as a fallback mechanism.

Developers often want RAD benefits during development, but raw
performance during production, and there's no simple way to accomplish
both in most cases. As such, we often need to provide alternate
strategies, and easy ways to invoke different ones in different
environments.

> But even when I look in StandardAutoloader, it feels overcomplcated
> for me. What is fallback autoloader? Why it should work for prefixes
> and namespces? Isn't name spaces is more then enough? Do we have code
> with prefixes inside of ZF? If not why ZF should support this?

 * Fallback autoloading is disabled by default, because using the
   include_path is very, very slow. But we have it as an option, because
   it's useful for RAD.
 * Why both prefixes and namespaces? To provide a migration path for
   code written for ZF1.

> Don't external library have their own autoloader, which will support
> required rules?

If the code was written for ZF1 and used ZF1's autoloader, why wouldn't
we support them in ZF2?

> So when I open this component in order to solve simple problem: "How
> to load some class", I have a bit frustrated. Even this small
> component looks not very easy to understand for new developer. But
> when we talk about something bigger, it is just a nightmare. I think
> we should reduce complexity of the FW, and very carefully use methods
> which works as catalyst for complexity. By catalyst I mean things like
> event system, now many of core components are heavily use it.

Thinks like the EM may introduce complexity... but simultaneously reduce
complexity, as well as coupling between components.

Believe me, we're aiming at a very usable framework. But you also have
to trust that perceived complexity often has solid architectural
considerations behind it.

--
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
Reply | Threaded
Open this post in threaded view
|

Re: Some thoughts about ZF

Tomáš Fejfar
Matthew, your last paragraph has a big idea in it. It's really true, that most of the architectural decisions that seemed utterly wrong at first has proved themselves to be the best ones (decorators and not using active record comes in mind). 

The thing is that ZF lacks the WOW EFFECT :) I have a one-to-one comparison with nette, which is build around the wow effect. It has RobotLoader - which is  nothing more than Classmap autoloader with automatic discovery and automatic caching. It also has very tight coupling form-presenter, which allows automatic form submition handling (but comes with nearly untestable presenter dependency). And a lot more. 

I could hear many times that someone said, that they want something done in nette and they need to monkey-patch the framework or use globals or stuff like that. But I can't remember even once that we couldn't do anything in ZF :) I guess we need little more faith in the way ZF is build as it proved it's usefulness 


On Thu, Mar 1, 2012 at 4:46 PM, Matthew Weier O'Phinney <[hidden email]> wrote:
-- Александр Шелковский <[hidden email]> wrote
(on Thursday, 01 March 2012, 02:55 PM +0600):
> I understand why Zend FW seems quite complex for new developers, and also I
> understand the reason of why it being complex. But also I think that sometimes
> it is a bit too much, and Zend team forgot one of the main principle of
> software development: "Keep it simple", and try to follow another anti-pattern:
> predict all possible use cases and be much much flexible than required.

There's two things going on in ZF2 right now.

 * We're trying to create a core that is de-coupled on which we can
  build applications and/or application architectures.

 * We're _planning_ on a layer on top of these pieces to make it more
  usable and easy to use for developers.

Believe it or not, the goal of the first point is actually KISS -- each
component should do one thing, and one thing well. This is why the
PhpRenderer looks very different today in ZF2 than Zend_View did in ZF1
-- instead of trying to do everything itself, it now composes other
objects to take care of discrete tasks:

 * Instead of resolving view scripts itself, and maintaining all the
  code for manipulating stacks of paths, it delegates this to
  resolvers. This has the side benefit of allowing different resolution
  strategies -- which helps developers address either performance
  concerns or differences in application architecture.

 * Instead of acting as a loader and registry for helpers, it delegates
  this to a PluginBroker. This allows using a consistent paradigm --
  the broker -- across many components, easing the learning curve. It
  also means, again, the ability to drop in an alternate implementation
  when desired.

 * Instead of composing and managing a filter chain for output
  filtering, it delegates this to FilterChain instance.

 * Instead of composing and assigning view variables directly to itself,
  it composes them.

Basically, each performs one responsibility well.

From the outside, this looks more complex:

   $renderer = new PhpRenderer();
   $renderer->setResolver(new TemplatePathStack(array(__DIR__ .  '/view'));
   $renderer->getBroker()->getClassLocator()->registerPlugin('foo', 'My\Helper\Foo');

   $model = new ViewModel(array('foo' => 'bar'));
   $model->setTemplate('foo/bar');

   $renderer->render($model);

But when you know what each piece does, it makes sense. Should you have
to know what each piece does? In most cases, no. And that's where the
second point comes in: the convenience API, where we make things simpler
for developers to consume. This doesn't mean getting rid of the
de-coupling; it means having a layer that introduces coupling in order
to make things simpler to consume.

The nice part about design decisions like this is that we can cater to
the developers wanting rapid application development, as well as those
needing to customize the framework workflow for performance or business
reasons.

> Frameworks stand for frames, and I feel that there is too much freedom
> in Zend framework, and it is a big problem. Instead of havening one
> and obvious way to solve the problem we have dozen.

However, this is precisely the niche ZF is trying to fill. We don't want
to provide one way of doing things, because we recognize that developers
have many, often competing, needs. We're not a convention over
configuration framework like Rails.

> I want to show it on example of one of core ZF2 components -- Loader
> (of course that is not a final version, but you can get a point): Lets
> just open a dir with component, what functionality we expect when
> dealing with Autoloaders? It should just  load classes based on simple
> rules. We have simple rules for loading classes: PSR-0. But when I
> open dir I see 15+ files and one dir, component have ~5 classes and
> few interfaces. We can easily exclude some classes, because they don't
> work with loading classes directly they work with loading modules,
> plugins and etc. I don't say that we must remove this classes from
> Loader component, I just say that, when I want components which loads
> classes I don't expect something like PluginBroker.

Where would you put the plugin broker, then? It deals with loading and
returning object instances. DI might be a good place, but the broker
isn't really about DI.

As for multiple autoloader implementations -- the reason is because
there is no one-size-fits-all solution. PSR-0, while it gives a nice
convention for how to organize code on the filesystem, has a terrible
default implementation when it comes to performance, as it requires
filesystem stat calls that may fail -- even if another autoloader
further down the chain can handle it. Approaches like the
ClassMapAutoloader are much more performant -- at the trade-off of
requiring either manually adding classes to the map, using a script to
update the map, or needing to use it along with another approach like
the StandardAutoloader as a fallback mechanism.

Developers often want RAD benefits during development, but raw
performance during production, and there's no simple way to accomplish
both in most cases. As such, we often need to provide alternate
strategies, and easy ways to invoke different ones in different
environments.

> But even when I look in StandardAutoloader, it feels overcomplcated
> for me. What is fallback autoloader? Why it should work for prefixes
> and namespces? Isn't name spaces is more then enough? Do we have code
> with prefixes inside of ZF? If not why ZF should support this?

 * Fallback autoloading is disabled by default, because using the
  include_path is very, very slow. But we have it as an option, because
  it's useful for RAD.
 * Why both prefixes and namespaces? To provide a migration path for
  code written for ZF1.

> Don't external library have their own autoloader, which will support
> required rules?

If the code was written for ZF1 and used ZF1's autoloader, why wouldn't
we support them in ZF2?

> So when I open this component in order to solve simple problem: "How
> to load some class", I have a bit frustrated. Even this small
> component looks not very easy to understand for new developer. But
> when we talk about something bigger, it is just a nightmare. I think
> we should reduce complexity of the FW, and very carefully use methods
> which works as catalyst for complexity. By catalyst I mean things like
> event system, now many of core components are heavily use it.

Thinks like the EM may introduce complexity... but simultaneously reduce
complexity, as well as coupling between components.

Believe me, we're aiming at a very usable framework. But you also have
to trust that perceived complexity often has solid architectural
considerations behind it.

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

Reply | Threaded
Open this post in threaded view
|

Re: Some thoughts about ZF

Artur Bodera
2012/3/1 Tomáš Fejfar <[hidden email]>
I could hear many times that someone said, that they want something done in nette and they need to monkey-patch the framework or use globals or stuff like that. But I can't remember even once that we couldn't do anything in ZF :) I guess we need little more faith in the way ZF is build as it proved it's usefulness 

on that note - take a look at modules and Zfc. It will make a world of difference once zf2 ship. That is because we'll already have a full suite of just-add-water components you can use to build your applications. That goes beyond forms, helpers, mappers and other general-purpose classes that every framework provides. Those will be building blocks of real-world applications and I believe it's something that's been missing in ZF1.

Numbers matter, so we need to reach some critical mass of those modules, but we have put a cornerstone for that. 

Fancy admin/debug toolbars and css animations put aside, I think there is no better "wow effect" than being able to use the framework to build a proper, stable, workable application through a weekend ... and then so. And then be able to customize it and scale without monkey patching.

Cheers.

-- 
      __
     /.)\   +48 695 600 936
     \(./   [hidden email]




 
Reply | Threaded
Open this post in threaded view
|

Re: Some thoughts about ZF

Tomáš Fejfar
Agreed. But such kind of wow effect cannot be presented in 45 minute presentation. That's why IMO Zend lacks the zealot community which Rails (and Nette in our country) has, that is able to answer question for beginners, create plugin classes for the community, etc. Zealot users expect that "i created fully functional blog with comments and tags and RSS in 45minutes" effect to get excited and work for the community. And that's why ZF lacks the community momentum. It's not created to make you excited. It's created to get the work done. 

I agree that zhe ZF2 modules will be huge leap forward to some kind of presentable wow effect. But still it's highly dependant on community momentum to evaluate, rate and comment modules. You wouldn't use module from unknown developer that has been used 4 times before (unless it's something simple that you can evaluate from a short view in the source). You look for something broadly adopted, used by at least hundred developers, that has been tested in the wild. 

Maybe I'm biased by the situation in my country, where the community is not small, but it has no drive. Our monthly ZF meetups have only around 10 people (being advertised massively on the only ZF website in czech language). 

2012/3/1 Artur Bodera <[hidden email]>
2012/3/1 Tomáš Fejfar <[hidden email]>
I could hear many times that someone said, that they want something done in nette and they need to monkey-patch the framework or use globals or stuff like that. But I can't remember even once that we couldn't do anything in ZF :) I guess we need little more faith in the way ZF is build as it proved it's usefulness 

on that note - take a look at modules and Zfc. It will make a world of difference once zf2 ship. That is because we'll already have a full suite of just-add-water components you can use to build your applications. That goes beyond forms, helpers, mappers and other general-purpose classes that every framework provides. Those will be building blocks of real-world applications and I believe it's something that's been missing in ZF1.

Numbers matter, so we need to reach some critical mass of those modules, but we have put a cornerstone for that. 

Fancy admin/debug toolbars and css animations put aside, I think there is no better "wow effect" than being able to use the framework to build a proper, stable, workable application through a weekend ... and then so. And then be able to customize it and scale without monkey patching.

Cheers.

-- 
      __
     /.)\   <a href="tel:%2B48%20695%20600%20936" value="+48695600936" target="_blank">+48 695 600 936
     \(./   [hidden email]