Read a lot of articles where people say that I should return Domain Model... But that will ruin the whole idea of my repository then.
I am using laravel Eloquent Models (that, if I am correct - Domain Models). I have repository, so in case I will decide to switch to Doctrine, I could just swap it all in a service provider. But if I will return an instance of Domain Model (in this case, Eloquent Model) that makes no sense. I need to return the same result from repository, and DTO seems just what I need...
Can someone explain me why am I wrong?
What is what
First off I'd like to give my interpretation of the terms you're using.
DTO (Data transfer object)
Typically a PHP class with public properties
Only responsible for carrying data
Does not does not validate the data
Does not know about any implementation specific things (e.g. which ORM it's tied to)
Usually used for passing data between parts of the application, without either part knowing about the implementation of the other
Domain model
Typically a PHP class with private properties
Should only contain valid data
Validates that any changes result in a valid state
Does not know about any implementation specific things (e.g. which ORM it's tied to)
Repository
Is only responsible for storing and retrieving data
Does know about it's implementation (e.g. which ORM it's tied to)
Is not responsible for returning valid data
What this means for your case
The answer really depends on how pure you'd like to think in terms of splitting responsibilities.
If you're talking to purists they'd say that Eloquent models are not DTOs and they are not domain models either. A repository will return an eloquent model, which will be mapped to a domain model. That domain model can then be modified or converted to a DTO, which can be used for reading data. In this case the responsibilities are separated at the cost of having more code.
If you're talking to pragmatists they'd say that Eloquent models are DTOs and domain models (and sometimes even repositories as well). As the eloquent models are responsible for storing data, retrieving data, modifying data and passing this data to other parts of the application.
In the end it's all about preference. You can go pure, you can go pragmatic, you can even pick something in between. It purely depends on how advanced a coder you are, how big the project is, how maintainable it should be, how quick changes have to be made etc.
Tdlr
A repository can return a DTO or a domain model depending on how pure you're thinking in terms of separating responsibilities.
Related
I have struggled with an MVC concept for a long time in php since I'm not a php developer. I refactored my site several times but it still looks like a cannon pointed in a mosquito. I've read many articles, posts and answears about MVC but it still makes me confused.
Let's have a simple website with articles and comments system. Everything is stored directly in a database (information about articles, paths, comments etc.). Mostly based on this I developed my own app using MVC. Here is how it works:
Controller retrieves data from the database about an article and related comments
It creates required model's objects (current article and comments)
... and then passes necessary data to the View
View presents those data by applying particular templates for provided objects
Everything works like a charm but...
my model's objects don't need any external logic so my domain objects are bordered to getter/setter classes -I'm wondering: do I need domain objects? It's pointless to store separated objects only for getting them from DB and displaying on a website after a while, isn't it?
controller holds a DB connection passed to services and mappers for creating a model's object -but queries stored in mappers can be merged into services functionality
In conclusion, I wonder if it's not a better approach to replace three-part model with a single manager (per object) which will retrieve all necessary data from the database and will pass them in any way and form (i.e. associative array) to the View.
Please do note, that I'm describing a simple case (1:1:1) with tiny logic, where most data retrieved from database are only for a presentation purpose.
Well what you have just described is an architectural pattern for data modelling called the Data Mapper pattern.
In this pattern you separate the persistence logic to a Mapper class and leave all of the Data stuff in The Domain Model. In your scenario you mentioned there is little logic, which is fine. Logic grows as your application matures. The key point is the separation, persistence has nothing to do with logic and therefore should be moved into a different class.
The Mapper class is only concerned with persisting data (generally to whatever data store you choose), in practice you uses "Adapters", which is why in some ORMs you see a different adapter for different data stores (ie. MySQLAdapater vs PostGresAdapater... etc, implementing a abstract Adapter Interface/Base Class).
It should be noted though, in your conclusion what you describe is actually the MVC Architecture.
The Model Layer is essentially your Persistence Layer (like described above)
The View Layer is where you present your data.
Your Controller Layer is where your data manipulation ie On your domain object's data.
Typically a MVC request goes like...
a URI gets mapped to a controller::action
Action gets data, manipulates it and sends it to the view for rendering.
When MVC applications run into trouble is when your Controller accesses several different objects and needs to persist them all. The class architecture of an MVC application tends to be very heavy as the Models typically have more logic on them than in the Data Mapper pattern since MVC models have persistence tied into them (in practice).
Just as an aside, for simple projects like yours, you might want to look into simple presentation frameworks like http://www.slimframework.com/ It has no persistence layer built in, which leaves you to choose the best for your project.
So I've been studying the role of the repository pattern as a means of decoupling the persistence layer from my models in an MVC framework. Prior to this, I might have my UserModel calling active record methods directly in order to store/retrieve domain objects.
Here's a sketch of what I'm thinking in regards to the call stack in a request that should create a new User:
Here are my questions:
Is this a correct implementation of the repository pattern?
I understand that the controller should take the user's information from the request and pass it into the model. How does that usually happen? Should the controller create a User object and then pass that into the model? I sure as heck don't wanna just pass in an array of values into the model--nor do I want to pass in 15 arguments to the model method that creates a user.
In order for this pattern to really work, it looks like to me I would need to have a domain object that is just a simple data structure with no behavior and then if I'm using an ORM, I would have an ORM object which will describe how the object is persisted. Initially I resisted this because it feels like duplicate code, but if I'm really separating persistence from the business logic, this would be needed right? For example, what if I went with an in-memory store? I would no longer use the ORM object.
Am I thinking correctly here? Is this acceptable. Please help me connect the dots in my head.
1. Is this a correct implementation of the repository pattern?
I'm not sure where you been doing that research, but you have got it wrong.
Repositories as for separating the domain objects from data mappers.
There no such thing as "models". Model in MVC design pattern is one of the to main layers: presentation layer and model layer.
And the repository pattern is incompatible with active record (anti)pattern, which combines domain and storage logic in single instance, thus causing a major SRP violation.
To use a real world example for, when and how to use a repository here is an example:
You are creating some document management tool, where said documents can come from several sources (for example: local SQL database, SOAP service and cache). In this situation you create a repository, which deals with the "routing" of storage. It is the part of application, that decides which data mapper to use for storing/retrieving each document.
The goal of repository is to separate the domain logic from the interaction with storage. For the system, that was described above, a repository would also let add new data sources, without need to rewrite large amounts of code (if any). You could just add another type of mapper for the document.
2. Should the controller create a User object and then pass that into the model?
To begin with, controller itself should not create anything. Instead your controller should use a factory for acquiring instance of the object that you need. This factory can be provided to the controller through constructor or some other method. This is called: Dependency Injection (to learn more about it, watch this lecture).
Also, as noted above, model is a layer, not any specific class or object. The responsibility of controller is to alter the state of model layer (by passing data to it). You could interact with domain objects and mappers (or repositories) directly in the controller, but it would mean leaking some of the business logic in the controller. It is recommended to instead use services, which then manipulates said domain objects and storage related structures.
As for the issue with 10+ parameter, that you would require for creation of new user account, let's assume you have action with following footprint:
public function postUser( Request $request )
{
....
}
If the action gets called with specific Request instance, you have two options how to deal with large amount of parameters:
Wrap the instance in a decorator, which would let you call a single method for forming the data from request in a specific array. Then you pass this array to the service(s).
Form the array inside the controller's action and pass it, where th data is required.
The former solution is more suited for large scale applications, where such formation of data would be required repeatedly though-out the code. But in a small/medium projects the second option is the common-sense approach.
Thing is, the job of the controller is to take the user's input, and distribute it to the model layer and current view. And formation of such array fits right-in with this mandate.
3. (..) main object that is just a simple data structure with no behavior and then (..)
No. Domain object is not "simple data". It is where most of the domain business logic resides in the application.
And forget about magical ORMs. First step for implementing a repository is to separate the domain and storage logic. Domain object handles the validation and business rules, mapper deals with persistence and data integrity (small example here).
Another thing that you must realize is that repositories for web application do not really interact with in-memory persistence (apart from cache). Instead your repository would be juggling mappers for different data sources.
Should the controller create a User object and then pass that into the model?
I'm not sure what you mean by "pass that into the model" -- the User object is the model. "Controller" and "model" represent different layers in the design, they are not specific objects, and there shouldn't be a separate UserModel object as you mentioned.
The repository interface itself is generally considered part of the model, though the domain objects shouldn't be saving themselves -- this should be done in the controller.
Your controller's job would then be to interpret the request and create a User object, then use the repository to save the user:
$user = new User(...); // based on Request
$repository->save($user);
it looks like to me I would need to have a domain object that is just a simple data structure with no behavior
This is not true, you can and should encapsulate behaviour in your domain objects. As for how persistence is actually implemented, a good ORM should take care of most of the details and you shouldn't have to create additional classes by hand.
I'm in the process of designing the base architecture of a web application. The project follows the Domain-Driven Design approach because the business model and logic is very complex.
The project also aims to be a SOA project (Service Oriented Architecture). So I'm learning a lot about Services and how to construct the project around it.
Following a previous question of mine, I have a question regarding associations in model classes.
I understand that model classes shouldn't know and do anything related to persistence. However I have trouble deciding for situations with association between model classes.
For example:
class Person
class Car has one driver (for the example)
Where should the getDriver and getCars be?
in the model classes: $car->getDriver()
in the service layer with primitive types: $personService->getPerson($car->getDriverId())
in the service layer using OOP: $carService->getDriver($car)
Solution 1. seems the more natural. I'm using Doctrine 2, so the model associations are handled with DB mapping annotations. That way, the model doesn't do anything related to persistence (even though it does through Doctrine actually). It's my favorite solution, but then what's the point of the Service except load the list of "cars" to start with?
Solution 2. seems just stupid because it throws away OOP and the Model/Service user has to know about the Database model to fetch association (he has to know that this ID is a "Person" id). And he has to do the association himself.
Solution 3. is a bit better than solution 2, but still where is the OOP in that?
So, for me solution 1. is the best. But I have seen Solution 2. and Solution 3. used in real projects (sometimes mixed together), and so I have doubts.
And the question becomes more complex when there are additional parameters, for example:
$person->getCars($nameFilter, $maxNumberOfResults, $offset);
(in this case, it really looks like a SQL query/persistence query)
So, which one should be used for a Model/Service architecture on a project following the Domain-Driven Design approach? With SOA, should my model be only "dumb" data container with no logic? If so, then where is the DDD approach?
In the context of DDD, this is a problem of deciding whether a relationship between entities is expressed via direct object association vs. repository. Both approaches can be valid and depend on the nature of the relationship. For example, in your domain, a person may have a lot of cars associated with them, and it doesn't really make sense to have a direct association to the set of cars from the person entity. Remember, the job of the entity, or more specifically the aggregate root, is to protect invariants and enforce business rules. If the set of cars associated with a person isn't required for any behavior that exists on the person class, then there is no reason to put the association on the person entity. Further more, as your example shows, the query for cars may need to be filtered. To answer your question, I would place the responsibility of representing the person-to-cars relationship in a repository. SOA is orthogonal to DDD and is more focused on how business functionality is accessed and deployed. It is informative to consider the interplay between DDD and SOA from the perspective of hexagonal architecture also called onion architecture. Your domain is at the core, encapsulated by a set of application services which form an API facade around your domain. These are different from services in SOA, which are ports/adapters in the hexagonal/onion architecture and they serve ti expose these application services as SOA services.
If your project is DDD I don't get it why you want a Model/Service architecture. IMO this creates an anemic model and everything is pretty much procedural .
Now, being DDD it means you don't care for the db. You have though (at least logically) 2 models: the domain and the persistence. The Domain model deals with the associations in the most natural way, best suitable to represent the business case. 'Has one driver' or has many it's a db centric thinking that has no place in DDD. The Persistence model handles the way the Aggregate Root will be stored in the db (here's where you define the ORM entities and their relationships et all).
About your questions, first of all it matters the context and the purpose. If it's strictly for queries (to display to a user) then a simple model can be used, no need for DDD and business rules. The controller can ask directly the specialised query repository for the data, returned as a DTO.
If you want to update the Person or a car, then in the Application Layer (I'm usually using a command based approach so in my case all these happen in a command handler, but architecturally it's still part of the Application Layer) you can retreieve the AR best suited for the task from the (domain) repository. The domain repository knows that getPerson($id) should return a domain entity as opposed to the query repository which returns a simple DTO.
$person=$repo->getPerson($id);
//do stuff
$repo->save($person);
//optionally raise event (if you're using the domain events apprach)
But what's tricky is to decide what is the AR in what context. A car has one driver in what context? A driver really belongs to a car? Is there the concept of the owner? You have the Person class, but a person can be the driver or the owner (or not if it's a rental company). As you see, it pretty much depends on the domain and only after you have a clear image of the domain you can start thinking about how do you store data and what object (entity) is returned by the repository.
When thinking about what goes where, consider the purpose of both the service and the model. Services reside in the application layer while models reside in the domain layer. So, what does your application need to know about a Person? Not much, probably. The UI will likely send some ids to process with a requested action.
Here, the AR is a Driver model. Keep in mind that services may contain other services and that Doctrine entites are POPOs and do not need to be anemic. Also, try to decouple the development thought-processes away from the persistence. For example, a $driverId does not need to be an integer, it can be any unique identifier that is relevant to the domain.
// DriverService
// If more parameters are needed, consider passing in a command object
public function beginTrip($driverId, $carId, $fromLocationId, $toLocationId)
{
$driver = $this->repository->find($driverId);
$car = $this->carService->getAvailableCar($carId, $driverId);
$withItenerary = $this->locationService->buildItenerary(
[$fromLocationId, $toLocationId]
);
$driver->drive($car, $withItenerary); // actual 'driving' logic goes here
$this->eventService->publish(new BeginTripEvent($driver, $car, $withItenerary));
}
OK first I understand I mixed SOA and application services.
True. You are mixing Domain Layer (DDD) methods with Domain Objects and Service Layer (SOA) methods with Data Transfer Objects in the question.
Domain Layer objects are different objects than Service Layer objects! For example, Service Layer may have a CarDTO object instead of Car object and DriverDTO object instead of Driver object.
$car->getDriver() is a perfectly correct way to access Driver in Domain Layer, and can also be used in a Service Layer with a restriction that wherever Service consumer requests Car data, Service always returns a Car with a Driver.
$personService->getPerson($car->getDriverId()) is valid only in Service Layer and invalid in Domain Layer. The reason for this method is Driver data is too large and complex to be always returned with a Car. Thus Service provides a separate method to request Driver data.
$carService->getDriver($car) is invalid in Domain Layer and strange to see in Service Layer, because this construction means that Service consumer must send all Car data to the a CarService to get Driver data. It is better to send only CarID and maybe to a PersonService, not to a CarService (Variant 2).
A more complex example $person->getCars($nameFilter, $maxNumberOfResults, $offset); looks strange in Domain Layer, since it doesn't contain much Business Logic. But if changed into $CarService->getCars($nameFilter, $maxNumberOfResults, $offset); it becomes suitable in Service Layer for partial requests.
The last few days, I have extensively read books and web pages about OOP and MVC in PHP, so that I can become a better programmer. I've come upon a little problem in my understanding of MVC:
Where do I put a mysql_query?
Should I put it in the controller and call a method on a model that returns data based on the provided query? Or should I put it in the model itself? Are both of the options I'm providing total garbage?
Materials on the subject of MVC
You could have listed the books you were reading, because most (if not all) php books, which touch on MVC, are wrong.
If you want to become a better developer, i would recommend for you to start with article by Marting Fowler - GUI Architectures. Followed by book from same author - "Patterns of Enterprise Application Architecture". Then the next step would be for you to research SOLID principles and understand how to write code which follows Law of Demeter. This should cover the basics =]
Can I use MVC with PHP ?
Not really. At least not the classical MVC as it was defined for Smalltalk.
Instead in PHP you have 4 other patterns which aim for the same goal: MVC Model2, MVP, MVVM and HMVC. Again, I am too lazy to write about differences one more time, so I'll just link to an old comment of mine.
What is Model ?
First thing you must understand is that Model in MVC is not a class or an object. It is a layer which contains multitude of classes. Basically model layer is all of the layers combined (though, the second layer there should be called "Domain Object Layer", because it contains "Domain Model Objects"). If you care to read quick summary on what is contained in each part of Model layer, you can try reading this old comment (skip to "side note" section).
The image is taken from Service Layer article on Fowler's site.
What does the Controllers do ?
Controller has one major responsibilities in MVC (I'm gonna talk about Model2 implementation here):
Execute commands on structures from model layer (services or domain objects), which change the state of said structures.
It usually have a secondary responsibility: to bind (or otherwise pass) structures from Model layer to the View, but it becomes a questionable practice, if you follow SRP
Where do I put SQL related code ?
The storage and retrieval of information is handled at the Data Source Layer, and is usually implemented as DataMapper (do not confuse with ORMs, which abuse that name).
Here is how a simplified use of it would look like:
$mapper = $this->mapperFactory->build(Model\Mappers\User::class);
$user = $this->entityFactory->build(Model\Entities\User::class);
$user->setId(42);
$mapper->fetch($user);
if ($user->isBanned() && $user->hasBannExpired()){
$user->setStatus(Model\Mappers\User::STATUS_ACTIVE);
}
$mapper->store($user);
As you see, at no point the Domain Object is even aware, that the information from it was stored. And neither it cases about where you put the data. It could be stored in MySQL or PostgreSQL or some noSQL database. Or maybe pushed to remote REST API. Or maybe the mapper was a mock for testing. All you would need to do, to replace the mapper, is provide this method with different factory.
Also, please see these related posts:
understanding MVC Views in PHP
testable Controllers with dependencies
how should services communicate between each other?
MVC for advanced PHP developers
Model and Entity Classes represents the data and the logic of an application, what many calls business logic. Usually, it’s responsible for:
Storing, deleting, updating the application data. Generally it includes the database operations, but implementing the same operations invoking external web services or APIs is not an unusual at all.
encapsulating the application logic. This is the layer that
should implement all the logic of the application
Here is the MVC Sequence Diagram which shows the flow during a http request:
In this case Model is the best place to implement the code realted to access database.
The model contains the domain objects or data structures that represent the application's state. [wikipedia]. So the model would be the place to make the database call.
In the 'classic' (lack of a better word atm) MVC pattern the view would get the current state from the model.
Don't make the mistake by saying that the model is for accessing the database. It's more than just accessing the database.
For one, don't use mysql_query() and family; they're being deprecated, so consider also learning about PDO and/or mysqli.
The model takes care of data handling; it provides an interface to the controller by which it retrieves and/or stores information. So this would be a primary place where database actions take place.
Update
To answer a question asked by the OP in the comments: "one generic model for the whole db or a model for each table/action?"
Models are meant to abstract away individual tables (although there are models that exclusively handle a single table); for instance, instead of asking for all articles and then query the usernames for the authors you would have one function like this:
function getArticles()
{
// query article table and join with user table to get username
}
How many models you will create largely depends on how big the project is and how inter-related the data is. If you can identify independent groups of data, it's likely that you'd create a model for each group; but this is no hard & fast rule.
Data manipulation can be part of the same model, unless you want a clear separation between read-only and write-only models (I wouldn't know of a situation that warrants this, but who knows).
To go even further, your model should not contain the database access code. This belongs to another layer outside the Model/View/Controller: this is called the persistence layer, which can be implemented using an Object-Relational Mapper such as the popular Doctrine 2 for PHP.
This way, you never touch any (my)SQL code. The persistence layer takes care of this for you.
I really advise you to have a look at a Doctrine tutorial, this is a really professional way to create your applications.
Instead of working with raw data loaded from the database, you create objects that hold your data, and the behavior associated with it.
For example, you might have a User class, such as:
class User
{
protected $id;
protected $name;
protected $privileges;
public function setName($name) { ... }
public function getName() { ... }
public function addPrivilege(Privilege $privilege) { ... }
public function getPrivileges() { ... }
}
You controller will only interact with objects:
class UserController
{
public function testAction()
{
// ...
$user = $em->getRepository('User')->find(123); // load User with id 123
$user->setName('John'); // work with your objects,
echo $user->getName(); // and don't worry about the db!
$em->flush(); // persist your changes
}
}
Behind the scenes, the ORM takes care of all the low-level work of issuing a SELECT query, instantiating your object, detecting modifications to your object, and issuing the necessary UPDATE statement!
Shouldn't models just describe data that will be passed from a controller to a view? Doesn't that make models unnecessary in weakly typed languages? In PHP, they are doing DB work in models, but isn't that wrong? As I see it, models are just unnecessary in weakly typed languages...
There are some misconceptions about the term model. Microsoft's MVC3 framework has the concept of a view-model, which is simply the data you use to render your views. This isn't however what the M stands for exactly in MVC. The model includes your business entities. We have thin controllers and fat models, but very thin view models. Our controllers make calls to services that perform business logic, and the controllers never do this logic themselves. We then translate our business entities (our data models) and convert them into a lightweight view model, which can be used for rendering a view.
So to answer your question
Shouldn't model just describe data that will be passed from controller to view?
Then perhaps what you are really asking is aren't view-models unnecessary? I'm not sure why you think this. View model + view makes the result. In PHP it can be helpful to define a class with easily accessible properties on it. This is just sensible for clarifying your expectations and prevents you from calling methods with hideously long sets or arguments. In JavaScript there is no need to define a view model as such, you just push the properties onto a new object and pass it along with your view to your view rendering logic. This is more a reflection of the OO pattern these languages use and not the fact that they are weakly typed.
If you are asking if model is unnecessary, then you have missed the purpose of the MVC architecture. A big part of MVC is that you separate your concerns. Why apply any architecture to your code? I am sure you can find a better explanation of the motivation behind MVC than I can give you.
A model is a useful conceptual tool, even if it's not strictly necessary in PHP to separate it from the DB code e.g. you can have a data object associated with each table that encapsulates some business logic, or define a set of business entities that aggregate the data across tables into domain-specific objects that the controllers can then use, or just have one monster DB object that has all the access functions and returns the entities. This has definite advantages over having DB code directly in use by the controllers:
If you are defining complex data structures that run across DB tables, you don't want to do that in controller code due to the risk of duplication - far better to have a single definition that enforces consistency across the system. Although this can introduce dependencies, having one function/object that defines that data makes it easy to find out where the data is used so you can fix things.
Third party maintenance is far easier if there's one place to go to where all the data structure definitions are found.
It makes unit testing easier if you can swap out the whole model or parts of it and replace it with mock object(s) that will provide test data
It makes controllers lighter and therefore more readable and maintainable
So you could argue that it's not necessary, but it helps a lot.
I've always seen models as a tool to provide data. That means that your controller doesn't ever have to worry about the data source, and if you want to switch from using a database to XML files then you only have to swap out your model.
So long as you have some data provider abstraction. Some Models will do low level validation (tightly coupled to the storage engine - null checks etc) but the controller "should" do all of the business logic/validation.
I personally have a thin struct like class that is mapped to each table (all implementing IDataStruct). This struct, or a collection thereof, is the only thing that moves between the DomainObject and the DataProvider. I can then enforce via my interface what datastruct I should be receiving. This is not a silver bullet but I have found it to work well (Makes things like caching and unit testing quite easy)
I hope this hasn't confused the issue.