views:

748

answers:

2

I've asked this question on the zfforums as well, but I maybe I'll get a response here.

So the Zend Framework is a general purpose, flexible, loosly coupled, high quality framework. However, I find some of the MVC parts inconsistent and overly complex. Hopefully some of you can justify some of the zf design decisions and answer some questions:

General Questions/Comments

  1. Why doesn't zend mvc follow the same naming conventions as other zend components? For example, mvc uses lower case, plural directory names and class names aren't prefixed with directory info so they can't be easily autoloaded.

  2. I'd like the option to add a module root directory. That way, I wouldn't have to explicitly configure the dispatcher by adding controller/module directories. I'd be able to drop in a module and have it accessible immediately.

  3. Why is there a distinction between view and action helpers? Currently, the helpers aren't designed to be shared throughout the code and there are inconsistent methods of loading and accessing the helpers. Other frameworks allow you to share the same helpers anywhere in your code. I don't see the need to specialize and violate DRY.

Zend View Questions

  1. Why do views use "$this" to access resources? I don't see the need for the extra typing. Some other frameworks extract() an array of view variables and allow loading global functions or autoloading static helpers from within the view: myHelper::someMethod();

  2. Why do view helpers only allow one function per class? That results in a lot of classes and associated maintenance. I'd prefer static classes with any number of methods as already mentioned.

+1  A: 

I don't know all the answers to these but they're interesting questions so I'll have a stab and hopefully someone can fill in the blanks.

General

  1. Classes not in the default module are prefixed with the module name, e.g. Admin_IndexController and would reside in /admin/controllers. I think the reason for the separation, and inconsistent naming (vs. library classes) is that there would be little benefit having them in a nested folder structure. Controllers are part of your implementation so I think it makes sense, personally. Traversing the folders does get a little tiresome, however.

  2. You could modify the dispatcher, or write a plugin to scan for directories and add them.

  3. There is definitely overlap here - the URL helpers are a good example of this. Generally a view helper generates markup so I think there's a big enough distinction.

View

  1. I don't know the exact reason but I'd guess it allows other helpers and view functionality to work together more easily. For example, if you've used the doctype helper to set the doctype, the form element helpers can generate XHTML or HTML as appropriate.

  2. It definitely results in a lot of classes, but I'm not sure about maintenance. I've not run in to any problems. I can see the use in static classes, but remember that Zend_View won't stop you using them. If you have your static classes in your include path (and use Zend_Loader or similar), you can use them instead of or in addition to View Helpers.

David Caunt
Thanks a lot for some good answers!
rick
Response to general question #1: In the name of consistency (which is 1 of 4 traits of good code according to MIT) perhaps controller names should be switched to "Admin_Controllers_Index". It would be more consistent to use a singular "Controller" for the directory and class name.
rick
Response to general question #2: Actually, I did write a dispatcher that extended the default standard dispatcher to use a single root directory and have the controllers and directories follow the zf lib naming conventions. In defense of zf flexibility, this was quite pluggable and straight forward.
rick
Response to #3: I just can't excuse having to write the same helper more than once. Of course, the view helpers could call global helpers. Not a bad solution, if not for the extra work and maintenance.
rick
Response to View #1: This is the type of answer I was hoping for. Maybe there are cases where having a view object maintain state between method calls makes sense. Doesn't explain why variables couldn't be held in an associative array within the view obj AND extracted though.
rick
Response to #2. Good point: I can use static classes within views as I'm accustomed. I guess I'm looking for a unified approach. I'll have to think about the possibilites.
rick
+3  A: 

I´m using the Zend Framework in a huge intranet site, since it´s early stages, 0.3 or 0.4 I think, and I followed the most of decisions regarding your questions. I´ll try to explain them a bit:

  1. In most cases you don´t need to use modules. You can drop all your controllers in your application/default directory, name them IndexController or HelpController and you´re done, just access http://www.domain.com/ or http://www.domain.com/help.

    If your project starts go grow you can add modules as you wish, prefixing them with the name of the module (directory name) Admin_IndexController or Forum_PostController, acessing them by http://www.domain.com/admin (you´re in admin module, index controller; not in default module/admin controller).

  2. You can set your modules directory at applicatoin/modules, for example, and configure the FrontController to look at this directory for modules. Using addModuleDictory Whenever you create a new directory and put your view/controllers there, they´re auto-discovered by the dispatcher. Here is an example.

  3. As I see they serve clearly distinct purposes. ViewHelpers are used to generate markup and render other actions directly in the view, abstracting menu creation, sidebar, etc. OTOH ActionHelpers interact with the dispatch process, allowing you to redirect to another action, as an example.

Views

  1. In the beggining I too felt it a little awkward, but I got used to. I think the main reason is not to pollute the namespace, but I can be wrong with this. By the way I´m not very fond of the use of extract(), but it´s just my personal preference.

  2. For the main reason that it´s not allowed to have more than one controller per file: autoloading. When you use $this->someViewHelper() the underlying engine looks for a class named *_SomeViewHelper_Helper in your plugin paths. Another reason is that static classes are very hard to unit test against. There´s even a proposal to rewrite the FrontController as an instance class, not a Singleton.

You´re right about the overly complex part that you say in your second paragraph and the developers and community knows about it. It just has to be this way to accomodate all requiriments and variations.

In the end I think that ZF is a very robust framework, giving us the freedom to do what we want.

I hope I could help you clearing your questions.

Luiz Damim
Thank you so much. The fog is starting to lift.
rick
The first general question was about directory and class naming, and I'm still not understanding why conventions were disregarded for mvc. Consistency is simplicity and I want to easily autoload all classes.
rick
Thanks for shedding light on addModuleDictory(). I thought it was an alias for addControllerDirectory() but now I understand it provides the path to the root of a collection of modules.
rick
I think extract() would make a compelling option. It's just a matter of storing view variables in an internal associative array and adding a config parameter.
rick
Yes, the framework is generic and flexible which necessitates some complexity. Mostly I'd like consistency improved.
rick
I don't think there is an issue with autoloading Controllers; they are included on demand when a request will be dispatched. This must be handled by the front controller or dispatcher somewhere.
David Caunt
Extracting view variables could potentially cause conflicts with existing symbols, e.g. front. While you should avoid globals, I think use of $this mitigates any risk
David Caunt
I have a need for load controllers and use reflection to discover methods and build an ACL. Just one example. But I think the naming inconsistency bothers me more than autoload problem.
rick
Extracting view variables within the run() method before the view template include() wouldn't conflict with the global namespace. The variables would be local to the run() method scope.
rick
I remember 0.2 or something. It's come a long, long way. This is an interesting "history". Thanks for sharing!
Till