The symfony 2 installer gives a best practice directory structure, but not a lot is said about how these directories should be used, where does each piece of code belong, sure the symfony framework narrows it down to views, entities and controllers, services etc. but more often then not, programmers end up putting a DQL query inside a controller and some logic to handle a specific task, while this does the job, there has to be a better method, even beyond symfony's out of the box directory structure, currently on a quest for better design pattern that would modularize and reuse as much as possible
On this quest, found a couple good articles on the interwebz, and spent a day on it, came up with a plan to separate all DB interactions to repositories, all logic to services, and keeping the controller 'thin' which acts as a central point for calling methods from repository and calling services. sounds good, will be modular and code can be reused.... BUT
This somehow moves away from OOP concepts and right into procedural programming, not that there is anything wrong with it, its just not leveraging the powerful concepts of OOP
Could making the objects more 'powerful' by adding in more functionality make it better? the services by definition should do a unit of task, will my approach make them big and ugly
a few good points on this blog here but could't really make out what they were trying to suggest as a solution
In general, the more behavior you find in the services, the more
likely you are to be robbing yourself of the benefits of a domain
model. If all your logic is in services, you've robbed yourself blind
-Martin Fowler
to summarize is Service oriented approach not leveraging the concepts of OOP? and how could this be supplemented
One of most important thoughts which you can find in Fowler's "Patterns of Enterprise Application Architecture", is that you should use right tools for your job. Depending on the complexity of your problem and domain, one or the other design pattern/architectural pattern may perform better. And following that way, in contrast to old frameworks (ZF1, SF1), SF2+ doesn't force you to go for any architectural pattern or organizing your business logic in specific way. You can even put everything outside bundles structure. So the best thing, which you can do, is to try learn more about design patterns (generally). And then, when you need, you will be able to pick one which will work best for your case.
You may want to look at:
mentioned earlier "Patterns of Enterprise Application Architecture", especially chapter: "Domain Logic Patterns".
The Four Architectures that will inspire your programming short review of different architectures.
any of books covering DDD, like: E.Evans "Domain-Driven Design", V.Vernon "Implementing Domain-Driven Design" or S.Millett and N.Tune "Patterns, Principles and Practices of Domain-Driven Design"
Domain-Driven Design in PHP decent book covering implementation of DDD patterns in PHP application, with some examples based on SF.
The Clean Architecture in PHP implementation of The Clean Architecture for PHP, focusing a lot on framework independence (with examples for ZF2 and Laravel).
With Domain Driven Design it creates fat model layers, and also calling a lot of services inside your controller may modularize your code, it still has its own set of challenges, it makes the design harder to create, and at some point there will be too many service calls inside the controller, what can actually be done is to use a few concepts from DDD.
two things to remember before starting DDD is :-
cohesion - modules that change together
coupling - modules that are dependent on each other
You need to lessen the coupling and recognize the cohesion and design the project according to it, main goal is to allow adding and removing or enable/disable/recombining of modules in future, in case you decide to alter the project
instead of having bundles depend on each other use interfaces instead
namespace MyProject\UserBundle\Activity ;
use MyProject\NotificationBundle\Notification;
use MyProject\MailBundle\Mail;
where UserBundle is coupled with NotificationBundle and MailBundle use interfaces that abstract the bundles instead
namespace MyProject\UserBundle\Activity ;
use MyProject\ServiceBundle\NotificationInterface;
use MyProject\ServiceBundle\MailInterface;
Main concepts of DDD are
value objects - an object that holds some data and is passed back and forth and does not focus identity but rather on the data that it holds, value objects can be used in symfony using embeddables
Entity - an object that holds some data but is dependent on an identity value rather than its data value
Repository - use of repository classes to make database operations make it possible to change the implementation later on, as it is centralized to one place
Aggregate - when several object belong together like a number of things that belong to a single category (eg: songs that belong to a genre), the entire collection of objects are treated as one and to make alteration to these objects would be thought on single aggregate object
Domain Events - any change in the state of the domain/data is regarded as an event, in symfony there are Event Listeners and Subscribers which can stand in for domain events, this is one of the most important concepts of DDD, filter also a great deal of improvement to the code
services - services are callable modules of code that do a unit of work, services allow code to be reused and are easier for testing and updating, services in symfony should contain the domain logic and the service layer can get pretty fat, this along with events make the code faster and more maintainable
Factory patter - this patter uses a 'factory' object that generates a different object, by doing this the name of the second object is abstracted, this helps when refactoring the code
these are generalized concepts that need to be applied to code that is highly situational, proper DDD requires the code to be modular which is a challenging task to achieve and need some experience on the engineer's part.
as already stated by others, books by 'martin fowler', ' V.Vernon' design patterns by ' gang of four' etc would be a good read
First of all there are best practices where to place files/components: http://symfony.com/doc/current/cookbook/bundles/best_practices.html.
Secondly http://symfony.com/doc/current/best_practices/business-logic.html:
In Symfony applications, business logic is all the custom code you write for your app that's not specific to the framework (e.g. routing and controllers). Domain classes, Doctrine entities and regular PHP classes that are used as services are good examples of business logic.
So you are not forced to use any architecture for your business logic.
Regarding your question - you can implement objects with operations and declare them as services (or use them directly, but in this case when you want to replace some functionality you'll need to rework more code).
there are always a lot of principles of software designing and we select what we think is more correct and makes more sense for a project and Symfony doesn't force us to use some special design pattern.
Related
Does MVC really means you have to separate => View aka design (html css) => controler (php code), model (mysql code into classes etc.)???
Are there not alternatives? Wondering because I would really like to avoid separating php code and mysqli as right now it's sooo easy to work on it (got used to it).
Yes, you definitely want to separate HTML and CSS from business logic.
Most frameworks use an ORM or something similar to abstract building queries but still give you the option to write plain SQL. I would recommend to use an ORM like doctrine2 for example over plain SQL. If you use any SQL directly the model would most likely the right place to put it into.
MVC exists for a reason, separation of concerns. This makes sure that your application becomes easy to maintain because every part of it should be easy to replace and not depend on each other to much. You want to avoid strong coupling. MVC is a pattern that helps you with that.
And like tttpapi said, there other ways to do it, but honestly, I personally think that specially Wordpress for example is a horrible clutter. I don't like Drupal or Joomla as well. The code base feels like working with 10 year old clutter compared to a modern well written application following the MVC pattern.
This is a little about discipline es well, I've seen totally messed up applications as well because people did not pay attention to separation of concerns and didn't follow the MVC pattern.
Does MVC really means you have to separate => View aka design (html
css) => controler (php code), model (mysql code into classes etc.)???
No.
MVC is about separation pf concerns. It separates presentation layer from model layer. And within presentation layer - it separates handling of input (controllers) from handling of output (views).
The model in MVC is not a databases abstraction or collection of queries. Instead it is a layer that contains several groups of classes. The major groups are domain objects, data mappers and services. The model in MVC is all these things taken together.
Longer explanation: here
Note: do not confuse MVC's model with domain model, which is the accumulated knowledge and vocabulary for specifica application. The part of domain model, that can be encompassed in code, is implemented using domain objects.
View is not html and css. Views in MVC are classes that contain the UI logic for the application. THey acquire data from model layer and then, based in this information, choose which templates to use for producing a response.
Longer explanation: here
Controllers are not some mystical "php code". They are part of application that takes user input, and based on that alter the state of model layer and (in rare cases) state of current view.
Are there not alternatives? Wondering because I would really like to
avoid separating php code and mysqli as right now it's sooo easy to
work on it (got used to it).
The point is NOT separating SQL from PHP.
The separation of concerns principle simply means that each part of your application should be dealing with one specific aspect.
And, if you try to implement MVC architecture, it will NOT mean that you separate sql from php, but that you separate business logic from persistence logic. Both of those would be written in PHP. But the trick is - MySQL is not the only form of storage. Data can also be stored in session, in cache, in noSQL, in files, in SOAP, etc. If you have separated business logic from persistence logic, then you can add caching to your existing application without rewriting the whole thing.
Also ...
There are more architectures then just MVC and Big Ball of Mud (which was advertised by people who talked about Drupal and Joomla).
You have MVP, MVVM, n-Tier, DCI, EDA and many others. And all these will be adhering to SoC principle .. but the result that they come up with will be different.
P.S.: If you actually want to learn about MVC, I would recommend for you to start going through materials from this list. It will start by introduction to simple concepts and gradually build up to ideas that you have to grasp to actually start working with MVC.
It is always up to you.
You always can find way how to use MVC as nonMVC. (example is Joomla here you can use just view with all code in it)
Or you can use systems that are not MVC bases such as Drupal.
But the MVC is here for some reasons.
To directly answer your question, yes MVC means exactly that.
However MVC is just a design pattern, and not a holy writ.
There are many variations available to you. I myself initially thought MVC to be restrictive and confusing, but in fact it was the particular MVC based framework i choose that had these failings.
There are many lightweight, flexable frameworks available. Take a look at https://github.com/bcosca/fatfree as a nice example, in particular the database section. You wont think mysqli is simple in comparison
Let me first say that I realize this question is vague and does not have a single answer. Nonetheless, I would greatly appreciate the insight of the StackOverflow community. To the purpose of this site, an answer will be chosen based on adherence to the specification and its address of roadblocks.
Overview
I am starting a project that will largely be a RESTful API, currently with about a half dozen models. However, their will also be a website. The goal is loosely to follow an MVC architecture so that the site and API utilize the same codebase. My plan is to heavily utilize Models, and light (or not at all) on Controllers. The views will vary between JSON (API) and HTML (website).
Specification
No ORM. I'm married to MySQL + PHP at the moment. While this may change later, I'm comfortable committing to the two and therefore don't need an ORM.
Balanced Abstraction. I do believe in Fat Models. However, per the above, I don't need queries written for me. Nonetheless, I still want to encapsulate the model properties.
Speed. As the site will largely utilize the API, speed is a cornerstone. With respect, I'd rather avoid the weight of a full-stack framework.
Roadblocks
If models are custom classes, what would be the best way to load multiple. I'd prefer to lazy load, but not at the expense of performance. Without pre-optimizing, what would be a clean approach for loading multiple models without the a half dozed require() statements at the top of every page.
Balancing abstraction, I don't want to create getX() methods in each Model for every possible query. Yet, I would like to avoid writing queries in my views. So how can I cleanly balance this between abstraction and still respect MVC paradigm?
If something exists that focuses on Model abstraction, which it probably does, please point me in that direction. However, I am familiar with CakePHP, Frapi, Code Ignitor and have read up on Doctrine. I believe these don't meet the specification.
Check out Eric Evans' Domain-Driven Design, or the free online redux Domain-Driven Design Quickly.
Specification
You don't need to use an ORM if you don't want to. Or you can use an ORM sometimes, or custom SQL other times as needed. Whatever code you write within those methods to query a database is an implementation detail and should be abstracted by the public-facing interface of the Model class.
You should write Model methods to encapsulate logical operations pertaining to your application. That is, your classes and methods are based on higher-level business requirements, not as low-level CRUD operations.
There's no need to have a Framework with a capital F to utilize Models. Check out the Page Controller pattern, which IMHO fits the PHP convention better than the Front Controller pattern that is so common among frameworks.
Roadblocks
Regarding lazy-loading, try the autoloading feature of PHP.
Avoid tedious getters and setters by designing your Model classes to higher-level interfaces, according to business goals, not low-level CRUD. A Model method could return a PHP hash array of other Model object instances. For simple object fields, you could simply make object member variables public.
I am looking into using Doctrine2 with my Zend Framework setup. I really like the datamapper pattern, mainly because it seperates my domain models with my database.
My question is what is the best practice for using Doctrine and DQL with my controllers?
controllers uses Doctrine
DQL/EntityManager directly for
saving/loading my domain models?
create my own classes in the
datamapper pattern for
saving/loading my domain models, and
then use Doctrine internally in
my own classes?
The pros. for #1 is of course that I don't need to create my own datamapper models, but again, with #2 I can later replace Doctrine (in theory)
What would you do?
Regarding your abstraction question, I'd say it really depends on the lifetime of this project and how portable your code needs to be. If it's a one-off website that will need minimal maintenance, it would probably save you some time to forego the additional abstraction layer and just write Doctrine code in your controllers. However, if you're planning to reuse this code, move it to different platforms, or maintain it for a long period of time, I'd take the time to add that abstraction because it will give you a lot more flexibility.
If you're still researching frameworks, take a look at Kohana. It's basically a lightweight rewrite of CodeIgniter written for PHP5.
I second the advice from pix0r. The additional abstraction is only worth it if it is a larger project with a potentially long lifetime and maybe with many developers on it. This is pretty much the guideline I follow, too, be it in php with doctrine2 or in java with jpa (since doctrine2 heavily resembles jpa).
If you want the additional abstraction, doctrine2 already ships with the possibility to use repositories (repositories are very similar or even equal to DAOs, maybe with a stronger focus on the business terms and logic). There is a base class Doctrine\ORM\EntityRepository. Whenever you call EntityManager#getRepository($entityName) Doctrine will look whether you configured a custom repository class for that entity. If not, it instantiates a Doctrine\ORM\EntityRepository. You can configure a custom repository class for an entity in the metadata, for example in docblock annotations: #Entity(..., repositoryClass="My\Project\Domain\UserRepository"). Such a custom class should inherit from EntityRepository and call the parent constructor appropriately. The base class already contains some basic find* functionality.
Roman
Also consider Symfony in your research. It will let you use ORM(propel/doctrine) or you may write your own data model. You can also bypass the data relationship and use direct SQL if needed.
To address your concern on 1 or 2, I personally go with ORM in my projects and bypass it if need arises. And better yet with symfony, you may switch between doctrine and propel or your own classes if you ever need to.
Pros:
1) faster development. easier to maintain. generally more secure and consistent. easy to switch databases should you ever need to.(from MySQL to Oracle, etc).
2) Faster runtime. Less dependency.
Cons:
1) Slower runtime and larger memory footprint. Dependency on other projects.
2) (reverse the pros for #1)
My thoughts are similar to pix0r's response. However, if your project is small enough that you could use the EntityManager/DQL directly in controllers then Doctrine 2 is possibly overkill for your project and maybe you should consider a smaller/simpler system.
In my experience writing persistence layer logic in the controller has always come back to haunt me in the form of technical debt. This seemingly small decision now will likely cause unavoidable and potentially large scale re-factoring in the future even on small projects. Ideally we would love to be able to copy and paste extremely thin controllers reconfigured with the appropriate models to prevent us from having to repeatedly create CRUD controllers over and over, but to allow also for customization of these controllers. In my opinion this can only be accomplished by being disciplined and keeping the persistence layer abstracted away from our application as much as possible. Since the overhead of doing that especially on a clean room controller is minimal, I can't see any good reason to advice you not to.
I'm thinking of implementing a Domain Driven Design approach (similar to the one described here), but want to integrate it with the Doctrine ORM. Has anyone had any success doing anything like this?
My initial instinct was to use Doctrine as the DAO layer, but it seems a a bit convoluted for Doctrine to map my database fields, and my entity objects map to (essentially) the same set of fields on the Doctrine object.
My original goal was to separate all my DQL/query logic from my domain Entities, but now I'm feeling a little lost in design-pattern land at the moment.
I know Doctrine 2 is supposed to provide a much more friendly approach to DDD techniques, but I'm not sure I want to wait that long. Does what I want to do make sense, or should I find another approach?
Thanks.
Doctrine is, in my opinion, imperfect for DDD because of the lack of a Repository class. Doctrine supports patterns such as Table Data Gateway and Active Record which, whilst good patterns for certain problems, aren't necessarily the best choice for 'classic' DDD. You can, however, work around these deficiencies.
One option is to derive from Doctrine_Table and use that as a poor man's repository. For example, if you have a class called 'BlogPost', you might have a table class 'BlogPostTable', inheriting from Doctrine_Table. You can then add methods such as 'findByCategory' to the BlogPostTable class, keeping such logic separate from your domain objects (which inherit from Doctrine_Record). It's not exactly the same as the patterns advocated by 'pure' DDD, but it's close enough.
Even without the exact same design patterns, you can still use the central insights of DDD. The main one is the Ubiquitous Language, the concept of trying to describe your domain using precise language that is readable by domain experts and developers alike.
Recently thanks to rails' popularity, many people start using activerecord as model. however, before I heard of rails (my peer group was not a fan of open source stuff, we were taught in a .NET school...) and while I was doing my final year project, i found this definition for a model
The model represents enterprise data and the business rules that govern access to and updates of this data. Often the model serves as a software approximation to a real-world process, so simple real-world modeling techniques apply when defining the model.
it doesn't say the model should represent one table as what activerecord does. And normally within a transaction, one may have to query a few unrelated tables and then manipulate data from different tables... so if activerecord is used as model, then either one would have to cram all the logic code into the controller (which is kinda popular in some php frameworks) that makes it difficult to test or hack the activerecord model so that it performs database operation on not only the table it maps to, but also other related tables as well...
so, what is so great about abusing (IMHO) activerecord as the model in a MVC architectural pattern?
Martin Fowler described this pattern in Patterns of Enterprise Application Architecture together with two other patterns or architectures. These patterns are good for different situations and different amounts of complexity.
If you want to so only simple stuff you can use Transaction Script. This is an architecture you saw in lot's of old ASP and PHP pages where a single script contained the business logic, data-access logic and presentation logic. This falls apart fast when things get more complicated.
The next thing you can do is add some separation between presentation and model. This is activerecord. The model is still tied to the database but you've a bit more flexibility because you can reuse your model/dataccess between views/pages/whatever. It's not as flexible as it could be but depending on your data-access solution it can be flexible enough. Frameworks like CSLA in .Net have a lot of aspects from this patterm (I think Entity Framework looks a bit too much like this too). It can still handle a lot of complexity without becoming unmaintainable.
The next step is separating your data-access layer and your model. This usually requires a good OR mapper or a lot of work. So not everyone wants to go this way. Lot's of methodologies like domain driven design perscribe this approach.
So it's all a matter of context. What do you need and what is the best solution. I even still use transaction-script sometimes for simple single use code.
I've said many times that using Active Record (or ORM which is almost the same) as Business Models is not a good idea. Let me explain:
The fact that PHP is Open Source, Free (and all that long story...) provides it with a vast community of developers pouring code into forums, sites like GitHub, Google code and so on. You might see this as a good thing, but sometimes it tends not to be "so good". For instance, suppose you are facing a project and you wish to use a ORM framework for facing your problem written in PHP, well... you'll have a lot of options to choose for:
Doctrine
Propel
QCodo
Torpor
RedBean
And the list goes on and on. New projects are created regularly. So imagine that you've built a full blown framework and even a source code generator based on that framework. But you didn't placed business classes because, after all, "why writing the same classes again?". Time goes by and a new ORM framework is released and you want to switch to the new ORM, but you'll have to modify almost every client application using direct reference to your data model.
Bottom line, Active Record and ORM are meant to be in the Data Layer of your application, if you mix them with your Presentation Layer, you can experience problems like this example I've just laid.
Hear #Mendelt's wise words: Read Martin Fowler. He's put many books and articles on OO design and published some good material on the subject. Also, you might want to look into Anti-Patterns, more specifically into Vendor Lock In, which is what happens when we make our application dependent on 3rd party tools. Finally, I wrote this blog post speaking about the same issue, so if you want to, check it out.
Hope my answer has been of any use.
The great thing about using the Rails ActiveRecord as a model in MVC is that it gives you an automatic ORM (Object Relational Mapper) and easy way to create associations between models. As you have pointed out, MVC can sometimes be lacking.
Therefore, for some complex transaction involving many models, I'd suggest to use a Presenter in between your controller and your models (Rails Presenter Pattern). The Presenter would aggregate your models and transactional logic and would remain easily testable. You definitely want to strive to keep all of your business logic in your models or presenters, and out of your controllers (Skinny Controller, Fat Model).