The Zend Framework: Problems with Controllers, Models and Domain Modeling


In talking with an ex-colleague, I realized that there’s a lot of confusion that takes place in these so-called MVC frameworks. What I’ve noticed is that many have different interpretations of what the Model-View-Controller looks like (typically only getting the view portion correct in implementation). Most controversy in architecture revolves around the Model and the Controller. Some systems employ simple Object-to-Table mappings such as a POJO system like Hibernate. Others might completely miss the ballpark in the interpretation. I feel that the Zend Framework is one such situation where the two have some distinct issues.

I feel that perhaps one of the most disputed aspects in MVC coding is modeling. It goes back to the idea of Domain Modeling. If you look at strict interpretations of Domain Modeling, such as Martin Fowler’s description, you’ll see that the idea at the very basis is simple: take related objects and make them into one solid entity. The problem is that while the abstract idea is easy to conceive, domain modeling itself is pretty much an art (if not a lost art). I feel and have written in the past that the biggest issue in domain modeling is that the examples just don’t exist for most practical scenarios. Most examples are overly simplistic and have leeway in terms of what may constitute an entity or not. Without clear, concrete illustrations that are also complex, it’s very difficult to perform good domain modeling as a practice. In fact, I’ve rarely if not ever seen companies do real domain modeling.

What I do see is what frameworks like Zend present, which is more or less a 1-1 mapping between a table/row in a database and an object. That said, Zend, to me, does not have a “true” model framework. The model system Zend implements seems to fall more under the data repository pattern. Pretty much you’re just isolating the database details and exposing retrieval/storage methods into your tables with Zend. And really the way Zend’s modeling system works it’s just a complex table mapping system.

That said, it does not resolve the issue of domain modeling. In fact, the way it’s set up suggests and perhaps even enforces a completely data driven mentality. You can move away from this method, but I doubt developers are disciplined enough to see how one can convert the Zend modeling system into a true Domain Modeling system.

Now, here’s where the difficult comes in. Because Zend’s modeling system is data driven, you often see business logic placed at the controller layer. If you do have “business logic” at the model level, it usually is relegated to convenience methods that act as retrievals of the data. However, that isn’t exactly what business logic processing is about and why the mentality behind Zend’s modeling system is skewed in many ways.

The controller itself should NOT contain business logic. Business logic as defined by Domain Modeling should occur at the model level. The idea is that Domain Models are an abstraction of an object. They have attributes (adjectives) which describe that object. Then the methods (processing/verbs) are what occurs upon those attributes. A car can be considered a domain model and tires are parts that compose a car. In OOP terms, the car contains a “has-a” relationship with the tires. In a business sense, the tires themselves are meaningless without the car. But again, this is where you need to define your rules around the domain objects since a tire can exist on its own yet in a different context (like a child can play inside of a tire).

Going back to the controller though, the content of the controller is just the pipelines where data flows between. The controller is just another way of describing the Observer design pattern. It’s function is simply to direct traffic based on some inputs. In that sense, it’s nothing more than a traffic cop. Let’s say you have motorcycles, bicyclists, a semi truck and various other automobiles. The cop itself doesn’t care how these cars operates. All the cop cares about is where these cars will collide with each other, are going at the appropriate speed (probably not even that) and most importantly going at the right time to the right place.

With regards to controllers, the controller is dumb in that sense as well. It does not care how something is saved or whether or not an email is sent. All it cares about is taking the data from a request and figuring out where that data goes next. It keeps doing this until it’s satisfied and produces some output (usually a view in the form of html, json, etc.)

I think the problem with Zend and controllers in general is that there’s no enforcement of these policies. There’s nothing to penalize a developer in putting code in the wrong spot. That can be okay in the sense that Zend is loosely coupled and allows for a great deal of interpretation. Yet sometimes this freedom can get out of hand to the point where organizations may have long term issues resulting from poorly designed code.

But my issue is that the domain modeling principle itself perhaps is just too abstract, too loose and lacks concrete methodologies for enforcement. In practice, it’s just really difficult except for the most disciplined of software engineers. One such principle I read about a while back is called MOVE or Model-Operations-View-Event (I think that’s the acronym). It takes the same ideas behind MVC but changes the acronym slightly for clarity and adds the Operations layer. The Operations layer is where the controversial business logic layer resides. This is where the processing (usually all the if/then/else statements) occurs and manages the model layer.

By doing this, the Event layer just takes the inputs from a request (i.e. $_POST, $_GET) and sends them to the operations layer. The operations layer can then process these elements, add any other non-data specific logic such as mailing out a notification, etc. and provide a response in the form of POJO or array/hashes. I like this idea because the operations aspect can be isolated from the necessity of being in a web environment (e.g. the controller) and one can re-use the logic here as opposed to the more throw-away controller style. Lastly, by isolating the logic processing units, you can further add unit tests.

Unfortunately, Zend by itself does not provide such an abstraction layer. You could put this at the helper level, but I felt that helpers themselves can be too abstract at times and require a better design from Zend to make them more useless.

(Visited 45 times, 1 visits today)

Comments

comments