Thursday, November 12, 2009

Zend Framework 2.0

I just wrote in a comment that Zend Framework 2.x did not yet exist and, today, the lead developer Matthew Weier O'Phinney has posted the roadmap for the 2.0 version of the framework, invitating php developers to participate in the discussion by commenting on the wiki or via the zf-contributors mailing list.
I already posted some questions on the wiki, but I would like to expand my thoughts on the architectural changes from a testing and design point of views, that are what interest my readers.
Here's a list of the guidelines that have the greatest impact.

Unified constructor
Every injectable class will have a constructor which accepts an array or a Zend_Config (I guess it will become Zend\Config) instance whose elements are passed to setters. This is becoming more and more the most adopted injection paradigm also in the 1.x branch. A standard is necessary and in a dynamic language like php the unified constructor works well, while accessing type hinting via reflection like Dependency Injection frameworks do in static-typed languages is troublesome and I don't even now if it is possible.

Elimination of singletons
Eventually, singletons will be refactored and we will stop seeing Zend_Controller_Front::getInstance() calls scattered in all the codebase. The various reset operations accomplished by the Zend_Test component during tests teardown should have hinted that something was fundamentally problematic in the design.

Design by contract
Multiple implementations of interfaces should be allowed by injection hooks, and interfaces should be extracted where needed. The abstract base classes so diffused in the 1.x version of the framework do not make easier to favor composition over inheritance since they force our classes to choose them as the unique parent.

Exceptions without inheritance
An example of avoiding problematic inheritance is the elimination of deep inheritance trees for exceptions. Base exceptions of a component should be interfaces. This is a finess I appreciate.

Obviously php 5.3 namespaces will be adopted and the _ in class names will be substituted by the \ namespace separator.
A thing I downvote is the separate namespace for testing: I would rather have unit tests in a parallel tree like they were in java packages (library/Zend/Filter/Int.php and tests/Zend/Filter/IntTest.php). A parallel structure gives different advantages:
  • saves the developer from having to import classes he is writing tests for;
  • naming collision with the production code are impossible since the class and file names in the parallel tree all end with 'Test.php';
  • the unique use statements expose only the imports the code is performing from different namespaces, expressing the real coupling of the system under test. Coupling to classes which live in the same folder is often inevitable and is not interesting to keep it under control.
Mvc implementation
The Mvc implementation (Zend_Controller) will undergo some surgery to improve performance and simplicity. In my opinion many features can be dropped: for instance I stopped using the action stack to perform multiple operations because it was too slow. It is also not test-friendly since you cannot assert that different actions were performed: I prefer to simply keep my logic out of controllers, so I see no use for great features in request dispatching as long as controllers are proposed as thin classes.
The point of the design by contract paradigm is to gain freedom in setting up the Mvc stack and injecting different collaborators which adhere to the contract. I saw the Phly_Mvc reference implementation and the interfaces are already present; it also uses a publish/subscribe pattern to dispatch events. In Zend Framework 1 we were able to substitute parts of the Mvc machine only by subclassing, while in 2 the approach will be cleaner as code will only depend on an interface.

The backward-compatibility break in 2.0 version is the right time for changing also Zend_Session and improving its Api and behavior. Testing that involves sessions is difficult and I think the right approach is not transforming Zend_Session in a singleton, but decoupling the controllers code with a session container, which implementation can be injected during bootstrap: it is something I would want to isolate just like a mail service.
The Zend_Session_Namespace objects in 1.x access directly the $_SESSION variable, mutating global state and becoming hard to test: a different solution could be placing them in a $_SESSION variable when they are constructed or reconstituted in their factory (which now does not exist). Anyway, the session namespace objects should do less work, particularly in the constructor.

The discussion is important as we are now shaping the future framework. Feel free to counterargue in the comments and in the wiki. :)


elton said...

Thanks for the great analysis of the proposed ZF 2.0 changes.

dries said...

When will the framework be released ?

Giorgio said...

The development is in the architectural stage, and it has been said the release will be "during 2010".

Shad Hartman said...

Zend framework 2 will improve the code base to make it more maintainable, easier to extend, or make use of new language features that better accomodate the design,