In symfony, I see some coders put business logic in the actions ( controllers that is ), and some coders put it in the models ( Doctrine ). Where should the business logic belong, in the controller or model? What if I didn't use Doctrine, and it was just plain text files?
Put the business logic in the controller is a bad pratice, the model is home for it.
If you don't have Doctrine, you can still have entities, model classes of your own (you should). Your files can be abstracted, and then put their business logic in their own classes, not in the controller.
It's all about MVC, and the M is really up to you.
Standard Symfony and MVC conventions would have the controller only doing what is necessary to receive information passed from the view or to the view. Any data processing of that information, for the most part, should sit inside your model and library classes where they could be set up for optimal reuse or structured code organization.
One of the greatest strengths of Symfony is the fact that any other good Symfony developer can quickly code into a project of any other good Symfony developer, mostly because of the MVC conventions and the organization that Symfony forces upon your development with good coding standards.
Bus. logic should not live in controllers. Controllers should well, control or direct the flow of control in the application they live in.
Bus. logic should live in domain level objects where they could be shared amoung various applications.
Related
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.
I've been learning Yii2 framework for a couple of weeks now. One of its core concepts is "Fat models, thin controllers". Reading the source code of the advanced application template I found that due to this concept nearly all the logic is contained within the models.
Well, there could be no questions at all if I hadn't some experience with Spring MVC where service layer seems to be a kind of natural way to decouple application's logic from its actual data.
So the question is: can it be a good practice to implement such an enterprise-like structure in an application built with Yii2? Speaking more specifically: is it worth breaking Yii's models into Entities, DTOs and Services?
Thank you in advance!
P.S.: The question can seem to be a kind of too abstract or subjective but having little experience with Yii2 I'd like to know are there any architectural features in Yii2 that could make the above mentioned implementation be not optimal in regard to code maintenance, performance and so on?
You can actually create models that are not ActiveRecords, so they actually become your service layer, just need to extend from yii\base\Model or yii\base\Object as you see fit, and implement all the logic you need there. You can also create those models on another folder called services, so their namespace would become app\services\ModelName
Using another feature instead of built-in feature can not be a good practice for every framework.
IMO, the model part is a killer feature of yii2, so if you do not need scaffold (code generation), you can use any other php framework without model part (zf2, symfony2, micro-frameworks).
So you can use your own model architecture without any perfomance lag but you'll need to write more code to make things done and your models will be hard to support by other people that are using yii2 and therefore I recommend to use another framework which comes without model layer.
CakePHP doesn't seem to ever mention separating the business logic and data access layers of an app. This is my first MVC app and my "fat models" are turning out to be very fat because they contain all kinds of business logic whose only real thing in common is requiring access to the same database.
When you hear the suggestion to move your business logic from controllers into the model, is it really acceptable to wind up in such a state? Does CakePHP provide any structure for a separate business logic layer as part of their framework?
Thanks, Brian
No. It sounds to me that what you are running into is the classic downside of the Active Record pattern. Also, it doesn't help that CakePHP is all based around result associative arrays instead of object instances. I suggest that you take a look at packages like Doctrine 2. It implements a DataMapper pattern instead of an ActiveRecord pattern. It keeps your business logic completely separate from your data access layer.
There are CakePHP extensions to integrate Doctrine into CakePHP.
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.
Many PHP frameworks claim that they implement MVC design pattern. However, in their implementation, the model and view don't know each other and each communication in between must be done through controller. As I read in wikipedia, this is MVA (Model View Adapter) instead of MVC design pattern approach because in MVC, model and view communicates directly.
Those frameworks' claim are wrong or did I miss something?
Frameworks like CodeIgniter are MVA, yes. However, their claims are not wrong since MVA is basically a different type of MVC deployment. Mediating controllers are hit by users which handle the business logic; they also call to the model to get the data and prepare the view.
This is not wholly diverged from strict MVC where the Model and View can talk to each other, so to say it's "wrong" is a bit harsh. I would say it's a different take on MVC.
EDIT:
See CodeIgniter's take on it:
https://www.codeigniter.com/user_guide/overview/at_a_glance.html#
Models are not required as everything can be done in the controller (not advised, obviously). Note that CI (and most other frameworks) say they are based on MVC principles.