views:

798

answers:

5

I have been reading up on multiple PHP frameworks, especially the Zend Framework but I am getting confused about the proper way to go forward.

Zend Framework does not use ActiveRecords but instead uses the Table Data Gateway and Row Data Gateway pattern, and uses a DataMapper to map the contents of the Row Data Gateway to the model, because ActiveRecord breaks down when your models don't have a 1:1 mapping to your database tables. There is an example of this in the Zend Quickstart guide.

To me, their example looks very bloated with a ton of getters and setters all over the place. I came across various blog posts about Domain Driven Design arguing that using so many getters and setters is bad practice because it exposes all the inner model data to the outside, so it has no advantage over public attributes. Here is one example.

My question: If you remove those getters and setters, how will you render your views? At some point the data has to hit the view so you can actually show something to the user. Following the DDD advice seems to break the separation between M and V in MVC. Following the MVC and Zend example seems to break DDD and leaves me typing up a whole lot of getters, setters and DataMappers for all my models. Aside from being a lot of work it also seems to violate DRY.

I would really appreciate some (links to) good examples or more information about how it all fits together. I'm trying to improve my achitecture and design skills here.

+2  A: 

You don't need to implement all the getters/setters, you can use__get() and __set(). What's the problem then?

Tomáš Fejfar
+1  A: 

From my reading of the post, the question is more philosophical rather than practical.

I don't have the time to write in depth, but here is my two cents. While I agree that you want to limit the number of get and set requests because a class should hide its internals, you also need to take into account the Java and PHP are different tools and have different purposes. In the web environment your classes are being built and taken down with each request and therefore the code you write should not depend on huge classes. In the article you pointed out the author suggests placing the view logic in the class. This probably does not makes sense on the web since I will likely want to present the view in multiple formats (rss, html, etc...). Using accessor methods (get & set) therefore is a necessary evil. You still want to use them thoughtfully so that you don't shoot yourself in the foot. The key is to try to have your classes do the work for you instead of trying to force them to do work externally. By accessing your properties with a method instead of directly you hide the internals which is what you want.

Again, this post could use some examples, but I don't have the time right now.

Can someone else provide a few examples of why accessor methods aren't evil?

Thanks. My question is indeed more philosophical than practical. Putting view logic in the domain model did seem problematic to me (as it violates MVC) and that's what prompted the question. What I really hope to see is some practical examples that clearly show the theory in action. If it's indeed a balance between Domain Driven Design and MVC then I'd love to see how other people solve the apparent conflict between them.
Sander Marechal
+2  A: 

Using Value Objects, you can eliminate some of those public setter methods. Here's a description of the difference between Entity and Value Objects. Value Objects are immutable and often tied to an Entity. If you pass all values in with the constructor, you don't need to set these properties from external code.

Something extra, not directly related to an answer, but more focused on DDD:

(Disclaimer: The only thing I know about the Zend Framework is what I read in the linked article.) The Zend Framework is using DataMappers instead of Repositories. Is this really DDD-ish? Well, Fowler's interpretation of a Repository might say no. However, Eric Evans states that a DDD Repository can be very simple. At its simplest, a Repository is a DataMapper (See DDD book). For something more complex and still DDD, see the Fowler article. DDD has a conceptual Repository that may differ from the pattern definition.

I urge you to continue reading about Domain-Driven Design. I think there's a flaw in the assumption that getters and setters violate DDD. DDD is about focusing on the domain model and best practices to accomplish that. Accessors are just a minor detail.

Kevin Swiber
Thanks. That Devlicious article makes a good read. I'm going to read the rest of the series as well.
Sander Marechal
This is a good answer and I would add that there is noting wrong with getters, setters. In fact, having them is an excellent way to add validation logic. Making properties public is quick and dirty and is OK while prototyping but not a great long-term solution. Suppose you wanted to change the name of a property. If you do this, every piece of code that accesses that property needs to change. If you use a generic name for the accessor method, you don't have to change client code. Also, Doctrine is a much richer solution than Zend DB. I would not recommend Doctrine1, but do try Doctrine2.
wilmoore
A: 

Implementing getters and setters has two advantages, in my eyes:

  1. You can choose which properties to make public, so you don't necessarily have to expose all of the model's internals
  2. If you use an IDE with autocomplete, all the available properties will be a TAB away when you start typing "get" or "set"—this alone is reason enough for me.
inxilpro
+1  A: 

There are two approaches here: What I call the "tell don't ask approach", and the other is the ViewModel/DTO approach. Essentially the questions revolves around what is the "model" in your view. Tell don't ask requires that the only way an object can be externalized, is from the the object itself. In other words, to render an object, you would have a render method, but that render method would need to talk to an interface. Something like this:

class DomainObject {
   ....
   public function render(DomainObjectRenderer $renderer) {
        return $renderer->renderDomainObject(array $thegorydetails);
   }
}

In the context of Zend Framework, you can subclass Zend_View and have your subclass implement this interface.

I've done this before, but its a bit unwieldy.

The second option is convert your domain model in to a ViewModel object, which is like a simplified, flattened out, "stringed out" view of your data, customized for each specific view (with one ViewModel per view), and on the way back, convert the POST data to an EditModel.

This is a very popular pattern in the ASP.NET MVC world, but its also similar to the class "DTO" pattern used to transfer data between "layers" in an application. You would need to create mappers to do the dirty work for you (not unlike a DataMapper, actually). In PHP 5.3, you can use reflection to change private properties, so your DomainObject doesn't even need to expose itself either!

blockhead