Moving VuFind to Zend Framework 2: Part 2 — First Impressions
I’ve now been working with Zend Framework 2 for a few days, and I’m starting to get a feel for how it works. It seemed worth sharing a few initial thoughts.
The use of PHP namespaces is a big change, mostly for the better. VuFind 1.x suffered from a total lack of namespacing. This resulted in haphazard include/require statements at the tops of most files and occasional naming conflicts between VuFind classes and external libraries. When I began adapting the code to Zend Framework 1, I used Zend’s autoloader to eliminate all of the includes and requires and prefixed all classes with “VF_” to achieve a sort of namespacing. Using namespaces in ZF2 requires namespace declarations at the tops of all the files, which brings back some of the noise of the include/require statements. However, unlike includes/requires, namespace declarations do not cause a significant performance hit, and they also are more informative to the reader about the dependency structure of the code. Because namespacing allows you to include classes under aliased names, it also means the code that follows the namespace declarations can be made much more readable than the ZF1-style prefix-heavy code. On balance, I think ZF2 has it right, though some small part of me wishes that some of the repetition of the namespace declarations could be avoided somehow.
Dependency Injection is one of the the leading buzz-phrases of Zend Framework 2 (and the PHP development world in general). It’s a simple enough concept: instead of having your classes forge their own connections to their dependencies (i.e. using global variables, calling factories/constructors), you instead “inject” those dependencies through constructor parameters and/or setters. This makes your code more flexible, since you can inject different versions of the dependencies in different situations to change behavior. It also makes testing easier, since you can inject dummy objects to test particular classes without having to worry about lots of external details.
Obviously, the problem with dependency injection is that it makes external code responsible for feeding dependencies to classes, which can lead to lengthy and repetitive code. This can become a burden. That’s where Dependency Injection Containers come in — classes which automatically build sets of related classes with all the dependencies properly injected. And that’s where things can start to get complicated and confusing. I don’t claim to have dug into this topic too deeply yet, though I’m sure I’ll gain familiarity as I work with ZF2, since it uses a Dependency Injection Container for much of its internal functionality.
As far as VuFind is concerned, I don’t plan to go crazy with Dependency Injection. More specifically, I don’t plan on using a Dependency Injection Container unless there is a very strong justification for doing so. Unfortunately, PHP as a language is not ideally suited for DI, so there are trade-offs in terms of complexity and/or performance when trying to automate DI through a container. However, I do plan on investigating places where the general idea of DI (minus the automation of a container) can be used to make local customizations and testing easier. One of the beauties of DI is that you can have the best of both worlds: you can build classes that allow injection of dependencies but also auto-generate those dependencies if none are provided. This is probably the direction the code will take, at least for the first iteration.
Configuration vs. Magic
One of the balancing acts in any framework involves the trade-offs between configuration and “magic.” How much functionality just works by convention, and how much does the programmer have to explicitly set up? Too much magic and you end up with code that’s very difficult to debug, since it’s hard to trace where and why things are happening. Too much configuration and simple tasks become a burden to achieve.
ZF2 seems to have a heavier emphasis on explicit configuration than ZF1 did — a lot of this has to do with the fact that some of ZF1’s “magic” led to performance-related problems; for example, auto-loading from a lengthy search path requires a lot of extra file accesses, which take significant time. I admit that I’ve been spoiled by some of ZF1’s magic features. Obviously, ZF2 doesn’t actually prevent you from using some of the same techniques as ZF1, but I would like to use best practices, and I’m going to try to recalibrate the code to use more configuration as I move forward. That being said, one of my highest priorities is making local customization simple, and if that requires a bit of magic, I’m willing to sacrifice a little performance.
The New View Layer
One of the big changes in ZF2 is a major refactoring of the view layer (and MVC in general). ZF1’s view was a bit of a monolithic beast. ZF2 has broken this into smaller chunks that interact with each other. There are now a lot of moving parts to keep track of, but each part is simpler to understand and individually modify than the previous whole. In any case, I don’t expect that the internals of the view layer will have too much impact on my design for VuFind, and the good news is that the actual templates themselves haven’t changed too much. The biggest non-backward-compatible change I’ve run into is the fact that the URL view helper has changed its parameter list, and this is actually a very good thing: the absolute worst feature of ZF1 views was the fact that generating URLs required an unwieldy call to the URL view helper. In ZF2, these calls are now much more concise and understandable — provided that you create a comprehensive router configuration, which I plan to do.
Obviously, my relationship with ZF2 is still very young, but so far my impression is largely positive, and I’m enjoying the process of moving forward. The biggest downside I can see so far is a general increase in verbosity (through namespacing and explicit configuration) which may slightly steepen the learning curve for working with VuFind. However, I think the benefits of these costs (more readable code, better performance, more reliable extensibility) make it worthwhile, and I hope to compensate for complexity through tutorials in the wiki once the design is a bit more stable.
I hope these ramblings have been informative. Comments are welcome if you feel I have misrepresented anything. If you have any questions, feel free to either post them here or take them to the vufind-tech list.
0 Comments »
No comments yet.
RSS feed for comments on this post. TrackBack URI