Unless you’ve been living under a rock for the last few years, you must have noticed the increasing interest and popularity in the web framework area. Django, Ruby on Rails, Symphony, Grails.. at one point it became so busy at Hype Station that it became hard to decide what bandwagon to jump on. PHP has been around for a while, even before anyone had heard of the frameworks mentioned. When PHP became popular, there was no PHP framework, other than PHP itself. This means that the PHP language become popular before any framework that was written in PHP. It also means that no discipline in terms of code structure was enforced on people writing PHP code. Let’s have a look at discipline. Why is discipline so important in writing code?
Code that is written in a disciplinary manner…
- is easy to read once the reader understands its patterns
- makes talking about the code easier
- can be extended while keeping its readability
These points often make a lot of sense. Code needs to be maintained, code needs to be explained, and code needs to be extended. Every popular piece of software “suffers” under these factors. So, we can pretty much conclude that discipline is important in writing software in any environment, small or big. This conclusion is also one of the primary reasons that frameworks are becoming increasingly popular. After all, one of the most important points of using a framework is enforcement of structure – in other words, they force you to write code in a very disciplinary manner. PHP based web frameworks quickly appeared at the horizon. I even remember seeing a fairly complete Struts clone written in PHP, a long while ago. After that there were CakePHP, Solar, Symphony, CodeIgniter, the list became endless. Some of these frameworks became rather popular, but the big hit in PHP’s framework department came when Zend released its own framework – the Zend Framework. Being “the PHP company” and all, their framework got a lot of attention. And it wasn’t all marketing buzz. It really is a fairly well architected, functional piece of software that can make the lives of developers easier. But what did the Zend Framework offer us, in reality? When compared to most frameworks mentioned before, the Zend Framework is basically a grab bag. You can pick the components you find convenient, and use just those. Want to write console based applications? Go with Zend_Console_Getopts. Want to parse an RSS feed? Use Zend_Rss. Want to write an MVC web application? Go with Zend_Controller and its relatives. Want to implement some authentication mechanism but don’t want to reinvent the wheel? Go with Zend_ACL. Want to do database stuff? Find your convenient friends in the Zend_Db package. Great, so we have choices. For now, let’s focus on your average web application and focus on the MVC parts only. Model, view, controller.
Zend’s interpretion of Model View Controller
When you take a look at the Zend MVC components, you can quickly see that there is plenty of support for the Controller and View layers. Not quite as much for the Model layer, however. Either that, or the Zend folks had a different understanding of what a model should be. After all, when you read the reference documentation for Zend_Db_Table, it actually seems that Zend encourages putting domain logic in your Zend_Db_Table derivatives (update: it appears that the Zend reference documentation has been changed in the meantime). Or maybe the developers using the Zend Framework generally have a different idea of how applications should be designed with Zend_Db. It appears that according to most people who develop with Zend_MVC, the model equals objects that extend from Zend_Db_Table. I can understand the way of thinking, as at first sight, this might seem natural. Zend_Db_Table feels a lot like working with Rails’ ActiveRecord, and in Rails, objects extending ActiveRecord are usually treated as domain objects. In fact, it’s recommended in the Rails community to use them as such. Let’s question that approach for a moment, before we look at Zend_Db_Table more specifically. Domain objects, by definition, should contain business logic, and business logic only. There’s a lot of controversy around this paradigm lately – especially since the arrival of so called opiniated software, which does not exactly encourage seperation between business logic and persistence logic. While I’m always open to different perspectives, I personally tend to stick to the original paradigm.
Mixing business and persistence logic – the cons
Why exactly do we want to separate the logic of business and persistence? Why does it matter so much? Isn’t this just some form of criticism that is only a pedantic concern of object orientation purists? I don’t think it is. The reason behind this principle can most definitely be rationalized by practical scenarios – so let’s give that a shot.
- Who gets to touch what
I for one, don’t want my application’s view to have access to persistence logic when I push domain objects to it from my controller. They should be “dumb”, apart from the logic that domain objects should actually contain. Of course, this really depends on what kind of environment or team setup you work in, but in general, people who work on the frontend side of things are concerned with other aspects of the application than the people who work on the backend of the application. You don’t want both ends to be fiddling with each others’ business. Also, you want to eliminate a situation where all developers need to have knowledge of all aspects of the application. - Public interfaces
Another reason to not mix business logic and persistence logic is that your domain objects become too “fat” to sensibly serialize, to be of any use in e.g. an RPC-based webservice. Having persistence related metadata in the objects that are returned from your webservice is probably not desirable. Would you like to have, for example, table association metadata about your objects exposed in the objects you return from a webservice? Or things like database adapters that are properties of your persistence objects? You probably don’t. That means that if you want to return an object from your webservice, you’ll have to take an extra step to only return the desired information. Some might argue that this is what Transfer Objects are for. However, Transfer Objects serve the purpose of returning more efficient data structures, not hide away other aspects of your application. -
Database refactoring
When you make changes in your database layer, this does not necessarily mean these changes are naturally reflected in your domain model. When optimizing a database schema for performance reasons (by denormalization), this should not necessarily reflect changes in your domain model. In fact, it’s often not desirable at all, as your whole application will then suffer from the optimizations that are made on the database layer, as such changes are often degressive to the natural structure of the model. An example, you say? Let’s say your database schema contains a list of books, and these books are tagged by your users. However, at one point you discover that joining the books table with the tags table eats up too many resources. So given the number of tags that a book gets at max, you decide to create a text field in the books table to store its tags, and remove the tags table completely, so a join is no longer needed. So, does this mean your domain model should also change? No, because it’s perfectly natural for a Book object to have multiple Tag objects. That’s just a tiny example of how a database schema and a domain model can easily get out of sync. The same goes for situations where you want to implement persistency for legacy (often badly designed) databases, and keep your domain model clean. - Parallel Development
Especially when you have a clear seperation amongst different team members in terms of backend and front end development, it is important that you don’t keep each other waiting. The front end is usually heavily dependent on the implementation of the backend, so development time of the backend should not frustrate the timelines in which the front end is being built. When you design your backend interfaces well, the front end can use mock objects that are returned from your backend services while the actual backend is still being developed, as to allow for parallel development. Wait, mock objects? In a scenario where your domain objects hold persistency logic, it would not likely be easy to substitute them with mock objects for the time being. When keeping your domain model seperate from persistency, it becomes a lot easier to use mock objects since they would only contain business logic and can be represented using a very natural interface. In fact, chances are that you won’t even need to use mock objects when you keep your persistency out, and use the domain objects right away while populating them with dummy data – gradually populating them with real data. - Cohesive testing
Last but certainly not least, it can be quite cumbersome to test business logic when the logic is mixed with persistence logic. When you write unit tests, it makes sense to test the business logic separately. For example, it is perfectly well possible that there are different validation rules business-wise, in contrast to validation that needs to be done because of how you designed your database. Business validation and persistence validation are often two different things, and if they aren’t already, there’s a fat chance they’ll grow separate in the future. Being separate things, we want to be able to test them independently. Also, avoiding dependencies (e.g. on database connectivity and accompanying code) makes unit testing much easier. Oh, and did I mention easy creation of mock objects yet?
All in all, keeping persistence and your domain model coupled will often lead to practical traps and complexity, instead of it just being a zealots’ principle.
What Zend_Db really is
Zend_Db, and Zend_Db_Table in particular is designed based on the Table Data Gateway pattern. The common idea behind this pattern is to provide, as the pattern name gives away, a gateway to your database tables. And it should be just that. By extending from Zend_Db_Table, you basically create a new gateway to a given database table. It doesn’t differ much from those situations where you created database helper classes that contained all the piles of SQL you didn’t want to clutter your other objects with. The nice thing about inheriting from Zend_Db_Table is that it provides you with a fluent interface to your database, so that you don’t have to write out all the SQL yourself. Of course, it doesn’t cover all situations – especially in terms of performance you probably want to influence the way your database is queried. Zend_Db_Table can guess a lot of things, but not everything. Differentiating between eager/lazy loading for example would probably require your intervention. Or eliminating inefficient JOINs where seperate SELECTs would make more sense performance wise. This is when you go into the classes that extend from Zend_Db_Table, and add your own highly efficient, sexy queries. That is persistence logic, and that’s where it belongs. But validating that an incoming email address doesn’t end with “hotmail.com”? Or determining whether reduction is in order for a certain item when the current date falls within the Christmas season? No, that’s not persistence logic, and should be kept out of your Table Data Gateways.
What your domain objects should be
As stated previously, Zend Framework does not provide any mechanism to facilitate in the creation of domain objects. That’s where you’re on your own. Not a problem, as we’re probably capable enough to implement domain objects without the help of a framework. So what should those domain objects look like? Simple, they should look as natural and cohesive as possible. You can of course follow your own rules when creating them, but I’ve found that adhering to a certain convention makes sense when designing your domain objects, especially since there is no framework enforcing any discipline upon us in this area, and we’ve already established that discipline is very important. The most common route nowadays when designing domain objects is to loosely follow Sun’s JavaBean conventions. They’re fairly simple:
- Use CamelCase naming conventions, where variables and methods always start with lowercase
- Create appropriate setters and getters for the object’s properties
- Prefix getters with “get”, setters with “set”
- As an exception to #3, use “is” as a prefix for getters that access boolean properties (e.g. “isPublished()”)
Next to conforming to these standards, I add a few more things to my domain objects, but I’ll discuss that later on when we will look at a practical example.
Introducing the Service Layer
A paradigm that has been somewhat popularized in the Rails world is “fat models, thin controllers”. This is a paradigm I can rarely agree with. A model should not do more than it is responsible for – defining business logic. Once you start introducing additional responsibilities to the model classes, the architecture becomes dirty. So controller logic belongs in the controller. But what is controller logic, exactly? Let’s attempt to define it.
Controller logic represents any logic that is necessary to handle incoming request data, delegate it to the appropriate objects and returns necesssary information for the view
So, what are these “appropriate objects”? Are they the model classes? Not likely, as they contain only business logic, and you probably want application specific logic as well. Thus, you want to centralize your application logic somewhere, for clarity and reusability. Say hello to the Service Layer pattern. This should be our “fat” friend. A service layer can basically be seen as a set of services that define exactly what your application can do. No more, no less. These services are optimized to provide a senseful API for the front ends that need access to your application logic. So, what should be the responsibility of such a service? A service should model the core behaviour of your application. It can talk with Table Data Gateways, throw domain objects around, talk to other services, and so on. Services are the only components where domain objects and table data gateways should meet each other. Their public APIs should have no concept of a concrete persistency mechanism at all. The fun thing about services is that their APIs can be designed in a very natural way, and thereby, create a lot of transparency in your application as a whole. Let’s take a look at a hypothetical service. Let’s say we’re designing a webstore, so we’ll need a shopping cart. Our service would be called “CartService”, and it would, for example, hold methods with the following signatures:
- “void setCart(Cart $cart)”
- “Product addProduct(Product $product)”
- “Product removeProduct(Product $product)”
- “void flush()”
- “Price calculateReduction()”
And to further simplify things, let’s introduce a service called “ProductService”, which would hold methods like the following:
- “Product findProduct(int $productId)”
- “Product[] getProductsForCategory(Category $category)”
- “int numProducts()”
- “Product findProductByName(String $name)”
I could go on for hours, but I think you get my point. The service models what this part of your application can do. The methods in the service generally receive domain objects and return domain objects. This means that in the application’s front end, one can simply populate a business object, throw it at the service, and expect the service to return a business object when needed. So the front ends have nothing to do with your database at all. They just work with regular, clear domain objects without any persistency fuzz. And, the back end needs not to be concerned that weird things happen in the database because of how the front end uses it. It also makes communication between the various discipline much easier. Wouldn’t it be easier to tell your co-worker who works on the front end, “hey, you can call findProductByName() on the ProductService now, and it will give you a simple Product object”, rather than explaining him how your database is designed (with all its weird optimization quirks), which objects to combine and giving him actual reference code (and risking re-invention of the wheel many times)? I think so. There’s yet another advantage to using services. Services can be very helpful to hide application details that are not part of the core logic of your application, but are so-called “aspects” of your application for purposes other than the logic itself. Good examples of these aspects are caching mechanisms and logging. Take caching, for example. Say you want to speed up the page responses on your website, so you decide to use an in-memory cache such as memcached. Your pages contain blog articles and accompanying comments. The blog articles can be cached for a long time. So can the comments, but you’ll need to invalidate the cached comments when a new comment is added, or when an inappropriate comment is being removed. It makes sense to centralize this logic in your service, so you a) don’t have to deal with it in all your controllers b) make sure all front end code uses the same caching logic c) don’t have to educate all your co-workers about when and how to cache/invalidate a cache. All in all, services have the following advantages:
- Decoupling the front end from your persistence layer
- Letting you reuse application logic from multiple front ends
- Making your application’s boundaries very clear
- Making communication with your co-workers easier
- Easy to expose as e.g. a webservice
- Easy to test
Putting the pieces together
So, to further clarify things, let’s take a look at an example application that uses the following concepts all together:
- domain objects
- table data gateways
- services
- unit tests
- caching
- logging
- a number of front ends
First, let us formulate a vision of what we want to build. Let’s take a common application – a discussion board. Our discussion board can consist of a number of “forums”. Each forum can hold an infinite number of posts, to which one can reply. Visitors need to sign up before they can post on the discussion board. The discussion board must offer a way to receive new forum posts as an RSS feed. Posts can be tagged with multiple keywords by users. A person who is assigned with the task of moderating the discussion board (the Moderator) must be able to remove unwanted posts and block users from posting. The following UML diagram depicts what such an application could look like when using the architectural concepts described in this document (click to enlarge).
As you can see, there’s a very clear separation of concerns between all application layers. First, there are the domain objects. These objects contain the core entities in our application, and the business logic that goes with them. In this case, typical examples of business logic could be:
- filtering of certain words in a post
- validating valid email domains in the users’ email address
- validating characters that are allowed inside a tag
- making sure posts can not be submitted on saturday evenings (chances are the user is drunk and will post something stupid)
- etc.
Next to the domain objects, we have the table data gateways. Obviously this is where we want to do all things that have to do with persisting data. These objects derive from Zend_Db_Table. They help us with storing, updating, deleting and fetching data. They should also do validation, but only on a level that matters for persistency. Let’s say that the field to store username has a length of 30 characters in the database; or a date field that only accepts the format YYYY-MM-DD; this is what should be validated in the table data gateways. Put simply, the table data gateways validate data in order to guarantee it can correctly be stored in the database. That is where their responsibility ends as far as validation goes. An interesting thing to notice about the table data gateways in comparison to the domain objects in the diagram is that there is a domain object called “Tag”, but not a table data gateway for a tags table. This is because we have designed our database in such a way that the tags are stored as a comma-delimited string along with a post, for efficiency. However, we can still assume that a Post object will have zero or more Tag objects. So our domain model stays natural, even though we have done some denormalization on our database. In the diagram, you can see that the table data gateways and the domain objects are not coupled at all. They meet each other in the service layer. In our case, the service layer consists of three services; the UserService, ForumService and ForumAdminService. Typically, you’d create a new service for every logical part of your application. In this case, the UserService takes care of everything that has to do with users. Registration, account verification, and so on. The ForumService takes care of everything that has to do with the forum functionality itself. Posting, fetching all child posts for a parent post, fetching all available forums, etc. It is good practice to keep your services small and focused on one clear aspect of your application. When a service becomes too big in future development, a senseful refactoring rule would be to extract a service from an existing service. Lastly, the ForumAdminService takes care of everything that has to do with administration of posts. It is perfectly fine for services to call each other. For example, when the ForumAdminService needs to fetch a list of available forums, it can simply call the ForumService to get the list instead of duplicating that logic. In a larger scenario, it is sometimes desired that services are more loosely coupled. A trick to accomplish this is to use the Observer pattern, but I’ll elaborate on that in a future post. Let’s look at a number of aspects the services use; it uses a logging object, a caching object, and a DomainConverter to convert back and forth from domain objects to table data gateways. I’d recommend keeping this kind of conversions in one place, to reduce possible errors and to easily be able to unit test them. Finally, the services are called from a number of front controllers. The controllers can all reuse the logic in the services, and can generally be kept “thin”. Also notice that both the services and the domain objects implement the Validatable interface. This interface holds a few methods such as validate(), hasErrors() and getErrors(), to provide a common interface for dealing with errors. Zend_Db_Table provides a validation mechanism by itself, so we’ll just use that for the table data gateways. For the exact implementation of the error handling I usually use an ErrorCollection method, so that I don’t have to duplicate that functionality in all services and domain objects. Such an object can easily be kept generic.
An opiniated footnote
I know that questions will be asked about this kind of architecture – which is fine, I like constructive discussions. There is no golden key to robust architecture. The architecture I have illustrated in this article works for me, and is based on my own experience and a number of proven practices. Having said that, I’d like to get some common questions out of the way already.
Question: Isn’t it more fashionable to not design upfront these days?
Answer: Keep in mind that you are not designing your concrete application using these practices, but rather you are laying out a foundation on which you can build. Not designing upfront at all is probably not a good idea. Remember how you comfortably comply to MVC patterns when implementing a web based front end? For these very same reasons, it’s probably a good idea to comply to a certain structure when implementing your backend. It makes understanding and refactoring your application a lot easier.
Question: Will I need this kind of robustness in a small scale application?
Answer: You probably know that succesful applications tend to keep growing, and you won’t know if your application will become successful or not. It is hard to refactor an existing application into a robust structure. So, yes, I would recommend to stick to robust patterns even when developing relatively small applications – unless they’re tiny, of course.
Question: Why wouldn’t we rather use the Transfer Object pattern instead of directly using the domain objects when dealing with front ends?
Answer: The Transfer Object pattern makes sense when the regular domain model is not efficient enough to facilitate the front ends. In most web applications, the domain model will do just fine, unless it’s defined in a layer that is not “web aware”. When you need Transfer Objects, use them – even when refactoring.
Question: Why do existing frameworks like Zend Framework, Rails or Django not facilitate in the service oriented approach and a separation of domain model and persistence logic?
Answer: I don’t know. There are some frameworks that do, Grails being the most noticable one. Frameworks tend to be designed in an “opiniated” manner. I’ve come to hate that term. “Opiniated” kind of suggests its design and principles are not open to discussion, and you should just stick to them. Fortunately, the Zend Framework (among others) is not designed to enforce any kind of approach, nor is its community very opiniated about it as far as I can tell.
Question: Won’t this approach cause a lot of performance overhead in my applications because of the extra layer?
Answer: Performance is always something that you need to keep in mind, but it is also important to find a balance between performance optimization and clean design. When the calls from your service layer tend to create queries that consume a high amount of resources, chances are that your query is being too greedy – so that’s the place where you should refactor. Having said that, there are always exceptions. Just don’t let the exceptions define your application design rules.
Question: Wouldn’t it be easier to just use Zend_Db_Table’s setRowClass()?
Probably not, for two reasons. First, you would couple your Zend_Db_Table objects directly with your domain model that way. Second, setRowClass() requires you to implement Zend_Db specific interfaces in the class you’re setting which leads to tight coupling (which is exactly what we want to avoid).
Question: Will you be writing about loosely coupling services anytime soon?
Answer: I hope so.
References

Peter Steevensz wrote:
Very nice post.
I absolutely agree with the Service layer concept it keeps the controller and model thin and acts as a natural interface between these parts.
Service logic like caching mechanismes can easily be placed in stand-alone libraries. They can even be tuned, with a factory pattern, to connect with different models (e.g file system and databse for storage).
Link | March 31st, 2009 at 5:47 am
milos wrote:
Pagionation
In this architecture Service layer should implement Zend_Paginator_Adapter_Interface.
Link | April 3rd, 2009 at 12:54 am
Tibo wrote:
Great and very thorough article. I definitely noticed that the ‘models’ and ‘controllers’ folders, as demonstrated in a lot of example projects, are just not sufficient. So I end up with an application-specific bunch of classes that in fact are a mix of domain and service. Reading this article I definitely think looking at design in terms front, model, domain, service and support objects is a great starting point.
Link | April 3rd, 2009 at 2:34 am
Gabriel wrote:
Great, easy to understand example! A while ago I have read the following article which tried to express similar ideas: http://akrabat.com/2008/12/13/on-models-in-a-zend-framework-application/
Be warned, though, that in this article, the author uses the term “Gateway” where you use “Service”.
You have presented much more understandable and tangible example. But calling the layer between Domain Models and table Gateways “Service” is a bit confusing for me because there is already the “SOA” and things like “Web Services”. Any suggestions for another name?
Link | April 3rd, 2009 at 7:52 am
Steven (breakerfall) wrote:
Good post – I’m happy you finally finished it and got it online!
Could you elaborate further on the DomainConverter? I very much like the idea of having another layer between database access objects and controllers and I first thought that having domain models would be fine and dandy, but I see that you’re proposing those _and_ another layer with “Service” objects. I like the idea, but I’m still thinking about the implementation and how data is passed between everything. I assume this is the job of the converter?
Link | April 3rd, 2009 at 3:59 pm
Nick wrote:
Great post! I have a couple questions:
1) Does the Service Layer or Domain Object decide when to persist data?
2) One stumbling block I’ve had with the “ZF Grab Bag” is where to put different pieces of my applications. Could you explain where to put the domain objects, table data gateways, and services classes in the directory structure?
3) Since ZF sort of only provides the VC in MVC, do you have any thoughts on using Doctrine for the Model component?
Link | April 3rd, 2009 at 11:09 pm
aleks wrote:
the ’services’ sound like a good approach to me. some example code would be helpful to further illustrate the separation and responsibilities of controllers, services, business objects, database persistency objects and frontend.
and i take it that a service would always have to call the validation methods of both the business and the database objects and return those as a single collection to the controller in order to display it in the frontend? and how would you handle validations for incoming forms?
(this is no criticism at all, just thinking aloud and wondering what an actual ‘application’ would look like.)
Link | April 4th, 2009 at 8:25 am
lbrouwer wrote:
@Gabriel
Thank you for your kind words. Also note that in the article you mentioned, the models extend from Zend_Db_Table_Row_Abstract, and as a result of that you’d create a tightly coupled object design and it eliminates the possibility of using “natural” inheritance in your domain model (e.g. what if FancyPost would have to extend from Post?). As for the name of the layer – I agree that “Service” is kind of confusing. I’ve found that I had to elaborate on this many times, because most people assume you mean “web services”. However, they’re called that way in books such as Patterns of Enterprise Application Architecture (Fowler) and frameworks such as Grails (and to some extent in JEE architectures). I suppose it’s an “accepted” term in some sense, but yes, I agree that it can be confusing.
Link | April 7th, 2009 at 2:10 am
lbrouwer wrote:
@Steven:
Thanks, about time, I admit it. The role of the DomainConverter is essentially to convert Zend_Db_Table_Row instances to domain objects and the other way around. It acts as a helper class that is used by the services. Converting these two kinds of objects is a job that happens often in the services, so to keep things reusable I’d abstract it away in a dedicated (usually static) class. A similar approach is used when applying the Transfer Object Assembler: http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObjectAssembler.html (but I’m not using transfer objects unless it’s really necessary, to avoid senseless overhead).
Link | April 7th, 2009 at 2:17 am
lbrouwer wrote:
@Nick:
1) The Service Layer decides this, as it is application logic.
2) What I do is creating a few extra directories next to the controllers etc., called “gateways”, “services” and “domain”; in some environments a different convention is expected of course, but in a standard Zend based application that’s what I do.
3) Doctrine is a nice framework, but it ties your model classes directly to Doctrine classes, thus you’ll end up with tight coupling between model and persistency logic. So using Doctrine would imply that Doctrine would have the same role as Zend_Db has currently. Whether or not to use Doctrine instead of Zend_Db is a matter of preference I suppose.
Link | April 7th, 2009 at 2:37 am
lbrouwer wrote:
@aleks:
I’ll try to post some example code soon. For now, the UML diagram in the article should give an indication of how the objects are related – but yeah, code probably tells you more in this case. Yes, the service would call the validation methods of domain objects and table data gateways. To make this process more transparent, I let the domain objects, table data gateways and services implement a “Validatable” interface which enforces these objects to implement e.g. getErrors(), resetErrors() etc. To handle the errors internally, I use an ErrorCollection object. The service basically returns an ErrorCollection object to the controller. Data that comes in from forms gets validated through the service, so the controller doesn’t do a lot of validation (unless it is validation that typically belongs in this controller, which is a possible scenario in the case of multiple front ends – but I tend to refactor such scenarios by adding a specialized method to the service for this).
Link | April 8th, 2009 at 2:25 am
Hessel wrote:
Impressive Leendert.
Respect.
Link | April 9th, 2009 at 4:16 am
Steven Bakhtiari (breakerfall) wrote:
Hi Leendert,
I’ve got one more question – in regards to relationships. Using your example, code-wise, how would you typically pull posts related to a user? Typically, it wouldn’t have been out of the ordinary to see something along the lines of: $user->getPosts(); but this would require the $user object (which is our domain model) to have some knowledge of the persistence layer (to retrieve the records from a database, or some other storage). Perhaps we could do something along the lines of UserService::getPostsFromUser([$userObject | $userId); ?
Matthew Weier O’Phinney has a blog post in the same vein http://weierophinney.net/matthew/archives/202-Model-Infrastructure.html where he discusses a similar idea. For the problem I mention above, the solution they came up with was sticking the row object (Zend_Db_Table_Row_Abstract) inside the model, then any calls like getUserPosts() could internally fetch records directly from the row object. To me, this feels a little dirty and seems wrong. Injecting the persistence layer into your domain model, just so it has access to it appears to side step the entire point of separating them. Of course, you could prevent any access of the persistence stuff to the consumer of the domain model, but eghh…
I’m curious to hear your take on the issue.
Regards,
Link | April 14th, 2009 at 2:38 pm
lbrouwer wrote:
Hi Steven, thanks for your input and for the link to Matthew’s article. I like how he starts off, but the further I read, the more coupling of model and persistence is introduced. As far as your $user->getPosts() question goes, yes, that’s a natural way of dealing with the domain model. So, yes, in this case User would have a getter/setter for Post objects. However, I don’t set the Posts from inside the User object, but rather from the service. The service queries both the User and Post gateways, performs necessary joins etc., and lastly assembles a clean object graph to return to the service client. That way the only layer that ties the gateways and domain model together is the service layer. In the front end you can then simply call $user->getPosts() to get your collection of Post objects.
Having said that, I tend to worry about performance when it comes to scenarios like this (e.g. one-to-many relationships). What I usually do is creating a number of convenience methods in the service, so that it’s easy to to also get a user without its posts. When you eventually would need them, you can always create something like getPostsForUser(User $user) in the service.
Link | April 15th, 2009 at 12:40 am
Snef wrote:
Hi Leendert,
Nice article. The last days I’m playing/messing around with the M of MVC. Already did a little project in Zend a while ago and with that i simply used Zend_Db_Table en Zend_Db_Table_Row(set) classes as models. Extra functionality (like getPosts, addPost…) where done in classes that extended the Zend_Db_Table(_Row) class. All went well.
(better late than never…)
Now a bigger project is come up so now is the time to adjust my ‘habits’ and learn more about the M
Again, nice article. Are you going to write more about it? And maybe some (pseudo) code examples?
Would be nice to read more here (not only about this subject)
Link | April 21st, 2009 at 7:36 am
F@bio wrote:
Great article!! It opens my mind.
Please, we need some (pseudo) code examples.
Link | April 23rd, 2009 at 10:05 am
James wrote:
I’ve been playing around with zend db and tables, confused about the coupling, maintainability etc. Then I read this article, great stuff!
Link | April 24th, 2009 at 8:18 am
Alan wrote:
Nice post I was just looking for some better explanation like this, tnx.
What about code? Maybe just code skeleton or something? Maybe with one insert and one read
Anyhow, tnx.
A
Link | April 29th, 2009 at 11:25 am
zach wrote:
Hey Leendert,
Amazing post!
I still don’t quite understand the job of the DomainConverter. You say it is used to convert gateway objects to domain objects? What exactly do you mean by that? Is is something like this …
$user = $this->_converter->makeDomain($userDbTableGateway);
/**/
$user->save();
…
Would you mind just giving me a simple exanple of what you mean by “convert”.
Link | April 29th, 2009 at 11:41 pm
James wrote:
the zend quickstart for 1.8 covers some of this ground:
http://framework.zend.com/docs/quickstart
I notice in the namespacing for the new loader
http://devzone.zend.com/article/4525-Developing-a-Comprehensive-Autoloader
it now has a name space for ’services’
Link | May 2nd, 2009 at 3:57 am
Fábio T. da Costa wrote:
So, in the case of ZF quickstar, the DomainConverter is the Default_Model_GuestbookMapper class?
Link | May 4th, 2009 at 10:45 am
zach wrote:
Hey,
Was also wondering, methods such as save(); would these be methods to put into the Domain/Value Object? For example, should my User_Model has a save() method that calls the service save() method, or have the save() method in the service accept a User_Model to save? User_Model_Service::save( User_Model $user)?
Link | May 6th, 2009 at 10:42 am
Fábio T. da Costa wrote:
Update! Update! Update!
Link | May 12th, 2009 at 5:55 am
Gawel wrote:
Hi,
Thanks for your article, it show me the way for a better development.
I’m a big fan of domain model, and your view of it is really interesting.
I’m actually trying your design to a test project, and i’m facing some problem on the Domain Converter.
I firstly try to make a generic converter who reads fields from database and properties from my domain objects, but i didn’t find a clean solution for doing it.
So i decided to try the way of one converter per domain objects but i have trouble to make them simple.
Could you, or someone, point me in the good direction about this ?
Sorry for my bad frenchy english …
And keep up the good work !
Link | May 12th, 2009 at 12:46 pm
Greg wrote:
This is a great article, some sample code would be nice.
Link | May 15th, 2009 at 11:09 am
Fábio T. da Costa wrote:
Please update!!!
Link | May 25th, 2009 at 8:20 am
Adam wrote:
Interesting post. I’ve been playing around with some of these concepts and wanted to run a very simple example by people here. I’ve only built out a simple model, but wanted to get some feedback on the approach before taking things further. Please have a look. Code below (I’m using v1.8.+).
My main goal was to treat domain object as true domain objects and have them be totally oblivious about persistence. I’ve created a simple User model with a single property $_username, but I’ve included some magic methods so this could be built out further. In addition, the majority of the methods in this object would fare better in a parent class so they could be inherited. In any case, you’ll notice that in the setter method for $_username there are two params in addition to the value to be set. These are $isTrustedInput and $useLazyValidation. The idea behind $isTrustedInput is to provide a way to set the property without having to undergo the overhead of validation. So, if the model is being built from a trusted data source, we can just set the property and not have to waste resources. It defaults to false for security reasons. The idea behind $useLazyValidation is to provide a way to chain validation routines when setting object properties (I really think that any non-persistence layer validation, e.g. unique, should exist in a domain object’s setter methods). As a use case, think of a $_POST request. Let’s say we are creating a model from the data in $_POST and will store it if it validates, but want to present the user with error messages should the input be invalid. By specifying $useLazyValidation as true, if the data is invalid when setting a property, the error message gets appended to an array property on the model, as opposed to throwing an exception which is the default behavior and can be used for testing. We can then display the value of this array in our views. The logic in our controller would be something like:
if post() create model object from post input - $isTrustedInput = false, $useLazyValidation = true if model has error messages display error messages in view else use our gateway or services to store the model in our persistence layerHere is the model:
Link | May 31st, 2009 at 12:28 am
Ralf wrote:
Great post! I enjoyed reading it a lot…
We are facing simliar problems with the fat-model approach in our application. But instead of defining services we implemented static methods in the model classes. Usual pattern, right? Yet, we face the situation of having all service aspects mixed in ever growing models and inheritence hierarchies. To tackle this problem we decided using the decorator pattern to our domain models. Those decorators are used to add or remove implementation aspects like validation, filtering and even persistence. They can then be applied on different service levels. It looks like a common way for “single inheritence” languages to simulate something like “mixins”. Some experiments with simple aspects and models already showed that this is in fact a promising approach.
Here is an example of the usage pattern:
// standard usage $user = new User; $user->setFirstName('Fred'); // decorating with attribute accessor $user = new Decorator_AttributeAccessor($user); $user->lastName = 'Flintstone'; // decorating with persistence accessor $user = new Decorator_Peristence($user); $user->store();It is like accessing functionality defined in the domain model while keeping all aspects strictly separated. Do you see any issues here?
Link | May 31st, 2009 at 12:47 pm
Sven wrote:
Hi Ralf, although I find the Decorator-Pattern really nice, it’s not a good choice here. This article is not only about Seperation of Concerns, it is about structuring your project. With Mix-Ins or Decorators, you can practice SoC, but your structure gets cluttered. Let me give an example. You’re using your Service_Users::findByName this is a child of Domain_Users, which itself is a child of Persistence_Users, which is a child of Zend_Db_Table. It returns a Service_User which goes the other way round, just in singluar and it’s parent is Zend_Db_Table_Row
In every layer you have the chance to implement layer-specific behaviour.
If you think your code gets bloated, why not introducting another layer? May be a Validation-Layer on top of the domain-layer could help to simplyfy your code.
Link | June 8th, 2009 at 2:36 am
Fábio T. da Costa wrote:
In this slides, Matthew Weier O’Phinney talks about using decorators too: http://www.slideshare.net/weierophinney/playdoh-modelling-your-objects
Link | June 9th, 2009 at 10:07 am
Ahmet wrote:
Hi there,
Excellent job.
I am a j2ee developer for 3 years, and coding with spring and hibernate generally.
I am waiting for your practical example, because I do not like zend in this way. There are lots of people here whom writing the business logic in the controller and some writing it on the persistence layer. Both I dislike. Business logic must have its own layer!
Link | June 13th, 2009 at 1:45 pm
Martin Sall wrote:
Hi., Leendert.
.
Great article. I have just started my master’s degree work about ORM tools and their role in various architectures and design patterns. As I see, domain driven design and SOA are “the coolest” and most popular words around the web lately
I have an experience of a .NET project which, I guess, was based on model-driven design. We used electronic implementations (business objects) of various physical paper documents and their relationships as basic building elements. Only system analysts had a direct contact with the client. Developers had only data diagrams and UI specifications but no clear idea about the business logic and domain objects. Business logic was mostly given as comments for UI elements (like “this combo box filters records by actual period”). We were using NHibernate. Developers created almost 1:1 mapping for almost each database table and used model’s classes only as a new datatypes without implementing any functionality in them. Our business objects were really just some “property bags” (I guess it is not the best way of using object-oriented design). All the basic CRUD functionality and business logic was implemented in some „business object factory” (BOF) layer. In that project we tried two technologies. The first was NHibernate. We ended up with creating many (over 100) similar entities, similar BOF classes and similar web services – it was a big “copy-paste-rename-customize BOF classes to fit the particular document business logic” work but we were lucky that NHIbernate allows to treat all the entities the same way – dynamic filtering methods which can be used for any business entity were so simple to write and use for all of our 100+ kinds of entities (it would be hard to implement dynamic entity independent filtering with Microsoft LINQToSQL and Entity Framework, I have tried it). Finding business logic “by place” was fast because it was right in the CRUD methods – if something got wrong with saving some business object, we knew that we have to look in that particular BOF class and Save method for that object (all the BOFs were mostly just copy-pasted so all of them had Save, Read etc. methods). But finding the business logic “by idea” was hard… While reading your article I thought that we should have our „business object factory” layer transform to ServiceLayer so it does all the CRUD, and move all of our business logic to the business entities so they become true domain objects, am I right?
But now let’s add SOA to this all. It is so tempting (especially in .NET) to add some serialization to domain objects to serialize domain objects straight away (as we did with our business entities). As it would be wrong to add something serialization related to our domain objects because they have to be clear and technology independent, then ServiceLayer could deal with XML serialization. Am I right? How then ServiceLayer could serialize domain objects? Do we need some serializable duplicates of each domain object? And our domain objects are not immutable if they pass to some UI (in our project we used SharePoint and InfoPath forms “because the client said so”) through the XML and then get back changed somehow, so they cannot be treated like DTOs, am I right? (I do not know much about “data transfer objects” design pattern yet, one more topic to study). It seems we have a tradeoff now – clear domain objects versus easy XML (de)serialization.
For ServiceLayer – is the following idea true: the more work ORM tool has done for us, the less work there is for ServiceLayer DomainConverter to do?
And one more question. How to be sure which functions are business logic and should be embedded into domain objects and which functions are application specific and should go to the ServiceLayer? I mean: your CartService methods
Product addProduct(Product $product)
Product removeProduct(Product $product)
Price calculateReduction()
look like some business processes to me. Why are they not a part of some Cart domain object?
Also I am thinking about that project I mentioned above. We had some business logic where some value for some business entity (let’s pretend for a moment that it is a domain object) vas calculated based on some other values in some other collection of business objects (from database example – a sum of rows of another table). And this had to be calculated when saving the entity. If the domain object itself does not know anything about persistence then it has no idea when Save occurs and the business logic should be executed. Only ServiceLayer knows that. So what would be the right way to implement it? Implement some method CalculateSumOfSomething, add that list of Something as a children so the ServiceLayer fills them?
I’ll be doing also some small PHP and Zend project and I definitely will use your article as a guide. I am just a bit overwhelmed lately with all those design patterns and approaches and how they are hierarchically related (MVC, n-tier, data-driven design, model-driven design, domain-driven design, active records and so on). Also – what would you call a “model” in your article (I mean related to model-driven design pattern)? Is it domain object model in this case? Ohh, I just started to read famous Eric Evans book about DDD.
By the way, I found an article about Extending Zend_Db for Increased Utility. Maybe it can somehow help to ease the work for ServiceLayer – DoaminConverter:
http://bwegrzyn.blogspot.com/2008/08/extending-zenddb-for-increased-utility.html
Link | June 27th, 2009 at 12:23 pm
Agustín wrote:
Great article!
Hope to read more soon!
Link | June 29th, 2009 at 11:39 am
UJ wrote:
Thanks for putting this together – very helpful.
I have not heard the term “domain converter” before, but from what you say, I understand is as a “data mapper” working with “dao” objects (db tables in your example) together, I am correct?
Thanks again.
Link | July 28th, 2009 at 4:26 am
Ian wrote:
Martin Sall
In regards to your question ‘which functions are business logic and should be embedded into domain objects’, the business logic remains inside the domain object, but is just referenced by the service layer and as such should be treated as an application specific implementation (IMO).
Trying to incorporate removeProduct into a cart domain object would mean coupling your domain object with a persistence layer, unless of course you have a middle man (the service layer) to perform the management of these actions.
Link | August 6th, 2009 at 1:38 pm
Pete wrote:
Using a service layer, how on earth can we implement lazy instantiation? I would normally do:
public function getUser()
{
if(isset($this->_user))
{
$this->_user = new User::getById($this->_userId);
}
return $this->_user;
}
But, now that User::getById exists in the service layer, I can’t figure out a good way to implement that (without moving the getUser() method into the service or calling the UserService::GetUserById inside of this domain object).
Link | August 10th, 2009 at 6:22 am
Pete wrote:
Sorry, there are a couple of typos in the above example, but I presume it is clear enough to understand what I’m getting at. If it isn’t clear, let me know. Thanks!
Link | August 10th, 2009 at 6:40 am
matp wrote:
Hi,
Thanks for a great article! There is one thing though I don’t understand. Why should the caching mechanism be placed in the Service layer? Wouldn’t it be more natural to implement it in the DAOs? What about Lucene indexing mechanizm, would you recommend to put it also in the Service layer?
Link | August 11th, 2009 at 6:17 am
Pete wrote:
Disregard. Used a proxy object. Thanks for your post; incredibly useful!
Link | August 11th, 2009 at 7:05 am
matp wrote:
Ian,
I think the proposed Service layer contains business logic. Why do you think that removing an item from the cart is not a business logic?
Link | August 11th, 2009 at 10:30 am
matp wrote:
Ok, after doing some rethinking. The domain model here has been reduced to almost a Value Objects group with some absolutely basic validation rules and no behavior, while the main logic (not only application logic) stays in Service layer. For example implementing a State Pattern on some business object here would also require some proxy class I guess. Shouldn’t we let the core business behaviors stay in domain model and create some helper classes if a use case requires it? And yes, the domain model would have to use some DAO to access persistance layer.
Link | August 11th, 2009 at 1:08 pm
matp wrote:
How to implement the following use case with the given architecture?:
UC Posting a new forum topic
————————
1. User submits a new topic
2. System saves new topic
3. System checks that this is a 20th topic from the user so the user is promoted to a higher level of forum members hierarchy
4. System is about to send a message to the user but first fetches his prefered message sending channel (email | sms)
5. Prefered message channel is sms, System sends sms to the user with congratulations
What would be the domain model role in this flow?
Link | August 11th, 2009 at 4:46 pm
Ahmet wrote:
Hi., Leendert.
Can anyone post a simple hello world project using the above code standarts..
Link | August 18th, 2009 at 10:46 pm
Khalil wrote:
We must be careful not to fall into the Anemic Domain Model anti-pattern (See http://martinfowler.com/bliki/AnemicDomainModel.html)
Link | September 5th, 2009 at 2:13 pm
pbo wrote:
For me I use a repository class for my entities. To the domain and application layer, this repository is just a in memory collection of domain objects. This is very similar to your service layers. I use Service for domain objects that are neither entities nor value objects.
The part I have been stuck on is trying to remove all these getters/setters. I am trying to have as few public methods as possible, and only expose methods that are necessary to interact with the domain object and keep it in a valid state. The hard part is getting the data out for the ui layer and for the repository to save it. I don’t want the domain objects to save themselves or draw themselves as I feel that gives the object more than one responsibility. The domain object should do its role in the model and nothing else.
That being said, the only way for me to get data out is to give these domain objects one method – either called exportAsDto, or toArray, or something that basically returns a flat array or some specialized Dto object.
Any thoughts?
Link | September 6th, 2009 at 6:36 am
rvdavid wrote:
Thank you for a very detailed explanation on something that has been eluding me for several projects now. I’ve been following the common train of thought that most developers I’ve come across have had for the past few years and that’s extending the Database Abstraction Layer as my model layer – It just felt wrong, but I had no Idea how to fix it. Your post has helped me tremendously and I am grateful.
Thank you again.
Link | September 30th, 2009 at 5:44 am
rvdavid wrote:
> We must be careful not to fall into the Anemic Domain Model anti-pattern (See http://martinfowler.com/bliki/AnemicDomainModel.html)
Whoa! It’s like that page recommended against everything you’re suggesting here – oh well, guess it’s back to the old drawing board for me.
However, your post did put a few things into perspective still, so thank you for that.
Link | September 30th, 2009 at 8:08 am
matp wrote:
>That being said, the only way for me to get data out is to give these domain objects one method – either called exportAsDto, or toArray, or something that basically returns a flat array or some specialized Dto object.
>Any thoughts?
pbo,
I think a good way might be to use Reflection and add extra meta information inside comments to domain model objects’ attributes in order to tell the Reflection which of the attributes should be exported to form a DTO.
This exporting should be done by factories that create DTO’s.
To speed up the reflection one can use some sort of caching. I don’t have yet any examples, but I’m working on it.
Link | October 12th, 2009 at 2:11 pm
dmitrybelyakov wrote:
> We must be careful not to fall into the Anemic Domain Model anti-pattern (See http://martinfowler.com/blik/AnemicDomainModel.html
Yes indeed, that gets us to look at another side of the problem. Thanks for the link – quite on topic.
Link | October 16th, 2009 at 2:11 pm
Benjamin D. wrote:
Hi,
Very interesting article, I have some remarks about it.
First, if we respect the Domain Model, domain objects should be plain independent php objects, and independent from any framework too. So, when data come from a form, how do you perform validation ? because domain objects shouldn’t have dependencies with Zend validate objects.
I don’t know if it is what you mean with the validatable interface that you told about, but i think the service layer should perform data validation. By reading you, I think you’re ok with that, so i’m interested to know how you’re dealing with that
Other point, the purpose of separating layers is also to minimize refactoring when something changes in persistence layer. But your services (which will have to handle all application logic) communicate directly with Zend db tables. So, a big application which needs to provide an API through web services, you will based your API on services, but now, if some data are not anymore retrieved from a relational database but from Directory or a web service (XML, JSON), you will have to refactor your data access layer but also your services.
In that case, have you ever considered integrating a DAO layer in your architecture ?
Last point, with that kind of architecture, we assume that controllers loose a part of their purpose which is to perform validation and filtering of data before invoking the model. All the application logic is moved into the service layer to predict the possible establishment of an API. So the controllers end just empty
I just want to know if every body is aware and ok with that :p
Cya,
Benjamin.
Link | November 24th, 2009 at 5:29 am
Jeboy wrote:
Hi,
Very nice concept, by the way how can you structure these to zend framework, do you have proposed directory/folder structure?
Thanks
Link | January 25th, 2010 at 9:38 pm
iSac wrote:
Thanks for the article, it looks like I’m a little late to the party but I found it really helpful in trying to wrap my head around service layers.
There’s two things I’m struggling with, and would love any help anyone can give.
First, does the Service object handle basic updating of the domain object, or does this happen some other way? For instance, let’s say for your user object there are effectively three kinds of properties: personal information (name, email address, nickname, and favorite animal), password, and preferences. Would User_Service implement upatePersonal, updatePassword, and upatePreferences methods? How would the controller handle this? Would it create a Zend_Form, call getValues, and pass the values to the User_Service update methods? Or, is this simple enough to let the controller handle, or better yet put in the persistData method of the form object you used?
Second, is it the Service object’s responsibility to try to figure out what kind of joins can be done natively by the underlying persistence mechanism, or in this paradigm would that never be done? For instance, a Blog domain object probably has a 1-1 aggregation with a Member domain object, and if they are both stored on the same MySql server, does the Blog_Service object have mysql do the join (through the mapper), or does it have to fetch the blogs, then query the User_Service, then join them on it’s own?
Link | August 2nd, 2010 at 12:01 am