Is Symfony2 a MVC framework? This question in tricky and you can’t see answer at the first moment when you visit symfony.com website. Even more – MVC pattern isn’t mentioned in elevator pitches in “What is Symfony” section. Most of PHP developers will tell you promptly, that this is Model View Controller implementation without a doubt.
The question is: where is Model layer in Symfony2? My answer is: there’s ain’t one and it’s good.
Symfony2 isn’t hardly bounded with Model layer, as it could have been seen in first version. We can see many Active Record model implementations in modern web frameworks such as Ruby on Rails, Django and symfony 1. I’m not saying those solutions are bad. The main problem was, that big systems maintained by plenty of developers changing over time tends to have a messy codebase. The common place to locate business logic were Model layer. The result of that approach were huge model classes, randomly structured Table/Peer classes full of static method and general feeling that system is hardly impossible to maintain anymore.
The problem: complex systems
Nowadays Internet and business needs agile team working on sophisticated and higly complicated systems. Simple problems were solved years ago. If one wants to make a success with his web application, he needs to solve tough problems. Those systems are impossible to be produced with old fashioned Watterfall software development process. Something better fitting should taken into the consideration to adapt to current conditions. Most of development process can be covered by agile tools such a Scrum or Kanban.
All those cases, from architectural point of view, could be solved by Domain Driven Design
The solution: Domain Driven Design
It’s a approach and way of thinking about complex systems. It supports best known design patterns, good separation of concerns, agility and good communication layer between technical and business people, for example by using ubiquitous language.
So if you ask, where should I look for a Model in Symfony2 projects, I’ll tell you: look for it around the domain. Symfony2 has plenty of capabilities that could be used for developing system with DDD approach, I’ll name just a few of them.
Dependency Injection Container
A component which revolutionized way of building Symfony applications. Dependency Injection is a technique that allows to create open for extension systems without hard coding dependencies. It holds services, which are one of the core concepts of DDD. Services are objects that encapsulates some business logic and solves some distinct problem. They defines system behaviour, are easy to test and proves that system could evolve in the future.
Entity is an object which has own identity. This identiy could be a database primary key, a MongoDb ObjectId (_id field) or any other kind of identifier that could be used to identify and entity. Most common ORM layer for Symfony2 is Doctrine2 which perfectly fits to Domain Driven Design. It uses POPO pattern (Plain Old PHP Objects, borrowed from Java POJO). Entities could be persisted to database but don’t inherit from base class, which makes them light and transparent for developers.
Provide access to data stored in some persistance layer. Again, Doctrine2 is great example, because of separation from storage layer. We could use same approach of repository for ORM (with MySQL, Postgres or whatever else modern RDBMS) as well as with ODM, which maps entities to MongoDb documents.
Underestimated concept of defining data. Developers tend to pass data structures along application with associative array, because it’s easy to do with PHP. This is a common pitfall in complex systems, because those array isn’t type safe, are mutable (which can make confussions) and most of the times are undocumented. You’ve probably seen dozen of method that takes ”an array of options” as an argument.
Value objects helps to definine a contract for object that has no identity (like options array) and doesn’t need to be persisted in database.
In non-trivial systems you can find plenty of objects that has sophisticated process of construction. Factories are one of the well known and understood design pattern. Symfony’s Dependency Injection Container supports factories method which makes it even more powerful.
View and Controller layers are very well visible for newcomers to Symfony2 world. Model is the part, which requires change of mindset after coming from symfony1 world or any other Active Record implementation. Good news is Symfony2 supports the best approach for designing and developing highly complex system, which is Domain Driven Design. With help of Doctrine2 ORM and its implementation of Repository Pattern, it gives an opportunity to create rock solid systems that could be think as maintainable and easy to extend in a long run.
For more reading about DDD I suggest great book by Eric Evens: Domain-Driven Design — Tackling Complexity in the Heart of Software.
In next blog posts I’ll try to illustrate DDD approach with Symfony2 by some code examples.
To be continued.