Domain driven design, entity lazy loading - php

I am fairly new to Domain Driven Design (DDD), but what I understand of it is that you speak to the application service, which is the entry to your "model". The service can talk to a repository which uses sources (files, databases, etc) to get data. The repository returns an entity.
That is the global idea what I get of it. The service knows the repository but not the entity etc.
Now I have the following issue.
I have an entity user, which is something like the following (is just an example)
<?php
class User
{
protected $name;
protected $city_id;
public function getCity()
{
// return $city_entity;
}
}
The getCity() function returns the city entity. I wish for this function to use lazy loading so injecting the CityEntity when you use the user repository is not really lazy loading.
I came with two solutions to the problem. But I feel that both are against the DDD principals.
First solution I came up with is to inject the city repository in the user entity, which has disadvantages: if you need more repositories you have to load them all in the entity. It looks like answer but it just looks like a wrapper for the repository to me. So why not just inject the repository then?
Second solution, you give the entity a service locator. The disadvantage of this is you don't know any more which repositories are needed unless you read the code.
So now, the question is, what is the best way to give the flexibility of lazy loading while keeping the DDD principals intact?

One of main point in DDD is that your domain model should only express the ubiquitous language of the bounded context to handle the business rules.
Thus, in DDD entities, lazy loading is an anti-pattern. There are some reasons for that:
if an aggregate holds only the data that it requires to ensure business invariants, it needs them all and they are few, thus eager loading works better.
if you lazy load data, your clients have to handle much more exceptional paths that those relevant in business terms
you can use shared identifiers to cope with references between aggregates
it's cheap to use dedicated queries for projective purposes (often called read-model)
IMHO, you should never use DDD entities as a data access technique: use DTOs for that.
For further info you could take a look at Effective Aggregate Design by Vaughn Vernon.

Related

Should we save/update models in repository pattern?

i'm learning about repository pattern and i have seen a lot of examples where repository pattern is used for creation and update.
Here is one example of repisotory interface.
interface RepositoryInterface
{
public function all();
public function create(array $data);
public function update(array $data, $id);
public function delete($id);
public function show($id);
}
This repository interface is responsible for creating/retrieving and updating models.
But then, after a little better search, i found that people should avoid to persist data in repository and that repositories should act as collections and be used only for retrieving data. Here is the link .
Here is what they say there.
Probably the most important distinction about repositories is that they represent collections of entities. They do not represent database storage or caching or any number of technical concerns. Repositories represent collections. How you hold those collections is simply an implementation detail.
Here is one example of repository that only retrieve data.
interface BlogRepositoryInterface
{
public function all();
public function getByUser(User $user);
}
I am wondering what is the best practice for repository pattern?
If we should use repository only for retrieving models, how then we handle create/update/delete models ?
Object persistance is totally allowed by Repository pattern.
From Martin Fowler's book Patterns of Enterprise Application Architecture (p.322):
A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes.
The excerpt is clear: As Repository is a collection, you should be able to add and delete objects from it at your will.
The only concern I have is about your interface. You should break it in two or more as you will probably have objects that:
are not meant to be deleted
are not meant to be updated
are not meant to be inserted
Creating different interfaces would make your code meet the Interface Segregation Principle that states that no client should be forced to depend on methods it does not use.
Some examples:
Let's say you have a class that represents a state of your country. It's rare to see a country adding new states, deleting or changing their names frequently. Thus, the class State could implement an interface that has only the methods all() and show().
Suppose that you are coding an e-commerce. Deleting a Customer from database is not an option because all his data like buying history, searches, etc, would be lost. So you would do a soft delete, setting a flag $customer->deleted = true;. In this case, the class Customer could implement an interface that has only the methods all() and show() and other interface - or two interfaces - for the methods insert() and update().
I think you misunderstood the sentences you quoted:
Probably the most important distinction about repositories is that
they represent collections of entities. They do not represent database
storage or caching or any number of technical concerns. Repositories
represent collections. How you hold those collections is simply an
implementation detail.
There is no statement saying that you should only use repositories for reading. The most important characteristic of repositories is that when you create or update an item with repositories, the changes may not be applied to the persistence layer immediately. The time changes are applied depends on the implementation of the repository.
A small note from me, we shouldn't have a method called create in the repository. As a collection, we add item to it, not create item. I usually have an add method instead of the create method in my repository interfaces. The creation should be the responsibility of a factory.

Is a repository or service provider required?

I am building a Laravel 5.3 app that pulls data from a number of potential sources. It's a fallback system with 3 sources:
Database
If not found, source 1
If not found, source 2
All 3 sources are quite simple and will be accessed in the same way, by using the following 2 methods:
function get($id)
function query($type, $string)
I'm aware there is various terminology around the different ways to implement this, but I'm unsure after reading the docs what the cleanest approach is. Should each data source be implemented as a Repository? A ServiceProvider wrapped in a container? I find the docs thorough but also lacking in overall/high level explanations, so any pointers are appreciated.
The Repository Pattern is the following:
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
With that in mind, you can say that Eloquent itself is a much larger implementation of the Repository Pattern, but a Repository nonetheless. Since it's an ActiveRecord implementation, there isn't any real separation between the Repository and Storage mechanisms.
On to your question specifically, Laravel won't really cover the Repository Pattern itself in much the same way it doesn't cover Service classes or Singletons: It's not Laravel's responsibility to teach you these patterns, it's just giving you the means to organize these patterns more easily if you choose to implement them.
All that said, I would agree with you that each data source implement its own RepositoryInterface. From there, you can register your own ServiceProvider that in turn instantiates a custom Service Class whose purpose is to return the appropriate Repository.
If determining the appropriate Repository is light in logic, and is dependent only on the Controller responsible for the alternate data source, you can likely use Contextual Binding and skip the Service Class altogether.
Either way, there's a few ways to skin this cat, but you're on the right track.
Edit: As an aside, if you want to strictly go "by the book" on this, you would probably want to separate out different Storage classes that connect to each data store separately, which you can then query as appropriate. Then your Repository - which is likely housing the same type of data collection regardless of its storage origins - can be responsible for the returned results.
Otherwise, if you want to stick with Eloquent as much as possible, you can look into multiple data connections to house each of your data sets.

Entity, Repository and composition - Dependency Injection

I'm trying to learn about DDD and there's a thing about the entities and repositories that I'm unable to understand.
From other questions here on SO I realized it is a bad habit to inject Repositories into Entities. But how to avoid injecting repository when I'm composing objects?
Let's have simple situation - events and events application. This seems simple.
$event->add($application);
$eventRepository->save($event);
I believe the $application is an Entity so I believe there should be some $applicationRepository.
Does it mean, that I should inject $applicationRepository to $eventRepository to save the Event entity? Like
class eventRepository {
...
public function save(Event $event) {
...
foreach ($event->applications as $app) {
$this->applicationRepository->save($app);
}
...
}
}
Another solution that came to my mind is this:
$eventService->addAplication($event, $application);
class $eventService {
...
public function addApplication(Event $event, Application $app) {
// simple example of validation, something like $event->isAplyable()
if ($event->capacity > count($event->applications)) {
$this->applicationRepository->save($app);
$event->addApplication($app);
}
}
}
Is one method better than the other? Or did I completely messed it up?
You should have a repository per aggregate root only, and they should work independently.
So there are two scenarios that I can see, and which you choose depends on how the business does things:
If the application and the event are two different aggregate roots (can one application be added to multiple events and should all the events then reference the same entity?), they should be tied together data-wise using references, so that when you save the event, it will not save the applications, but only references to the applications that it holds.
If the event is the aggregate root and the application is something that lives, dies and changes with it (and they share consistency boundaries) your event repository should be able to save the application as a part of the event. Now you don't say how you persist data, but an ORM can help you with that.
Hope that helps a little. And feel free to ask.
One way to avoid an explicit call to an application repository is for the event repository to persists application instances that are associated with a given event. This is essentially the first option you propose, however depending on the persistence framework you use, the code could look a little different. For instance, some ORMs support persistence by reachability which means that if you're persisting an event and the frameworks finds transient application instances reachable from the event, it will persist those too. In this case there is not need for an explicit application repository.
The idea at play here is that of aggregate roots. If an Event is an aggregate root and an Application is a constituent value object, then the event repository must be able to persist the entire object graph, including the associated application instances. DDD suggests one repository per aggregate root not necessarily per-entity.
It may be the case that both Event and Application are aggregate roots (ARs). In that case it is not advised to have direct object references between ARs, but to instead use identity references. In that case, your second example would apply, except in a slightly different form. The event service should be an application service which hosts specific use cases associated with events. One of those is adding an application. The difference is that the addApplication method should accept an event ID and application ID as arguments which it would then load from the respective repositories. It would also be able to explicitly persist both events and applications using their respective repositories.
Take a look at Effective Aggregate Design by Vaughn Vernon for ideas on how to determine ARs in your domain.

Where do I put a database query in MVC?

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!

repository pattern vs ORM

What good is a repository pattern when you have an ORM?
Example. Suppose i have the following (fictional) tables:
Table: users
pk_user_id
fk_userrole_id
username
Table: userroles
fk_userrole_id
role
Now with an orm i could simply put this in a model file:
$user = ORM::load('users', $id);
Now $user is already my object, which could easily be lazy loaded:
(would be even nicer if things are automatically singular/pluralized)
foreach ( $user->userroles()->role as $role )
{
echo $role;
}
Now with the Repository pattern i'd had to create a repository for the Users and one for the Roles. The repository also needs all kinds of functions to retrieve data for me and to store it. Plus it needs to work with Entity models. So i have to create all of those too.
To me that looks like alot of stuff do... When i could simply get the data like i described above with an ORM. And i could store it just as easy:
ORM::store($user);
In this case it would not only store the user object to the database, but also any changes i made to the 'Roles' object aswell. So no need for any extra work like you need with the repository pattern...
So my question basically is, why would i want to use a repository pattern with an ORM? I've seen tutorials where to use that pattern (like with Doctrine). But it really just doesn't make any sense to me... Anyone any explanation for its use in combination with an ORM..??
The ORM is an implementation detail of the Repository. The ORM just makes it easy to access the db tables in an OOP friendly way. That's it.
The repository abstract persistence access, whatever storage it is. That is its purpose. The fact that you're using a db or xml files or an ORM doesn't matter. The Repository allows the rest of the application to ignore persistence details. This way, you can easily test the app via mocking or stubbing and you can change storages if it's needed. Today you might use MySql, tomorrow you'll want to use NoSql or Cloud Storage. Do that with an ORM!
Repositories deal with Domain/Business objects (from the app point of view), an ORM handles db objects. A business objects IS NOT a db object, first has behaviour, the second is a glorified DTO, it only holds data.
Edit
You might say that both repository and ORM abstract access to data, however the devil is in the details. The repository abstract the access to all storage concerns, while the ORM abstract access to a specific RDBMS
In a nutshell, Repository and ORM's have DIFFERENT purposes and as I've said above, the ORM is always an implementation detail of the repo.
You can also check this post about more details about the repository pattern.
ORM and repository pattern...depends on setup.
If you use your ORM entities as the domain layer, then please use no repositories.
If you have a separate domain model and you need to map from that model to ORM entities and so perform a save, then repositories are what you need.
More details you find here (but must be logged to linked-in). Also to understand the difference, check out the definition of the repository pattern.
Most people use classes that they call repositories, but aren't repositories at all, just query classes - this is how/where you should place your queries if you decided to go with the #1 option (see answer above). In this case make sure not to expose DbContext or ISession from that query class, nor to expose CUD-methods from there - remember, Query class!
The #2 option is a tough one. If you do a real repository, all the inputs and outputs on the repository interface will contain clear domain classes (and no database related object). It's forbidden to expose ORM mapped classes or ORM architecture related objects from there. There will be a Save method also. These repositories might also contain queries, but unlike query classes, these repos will do more - they will take your domain aggregate (collection and tree of entities) and save them to DB by mapping those classes to ORM classes and perform a save on ORM. This style (#2) does not needs to use ORM, the repository pattern was primarly made for ADO.NET (any kind of data access).
Anyhow these 2 options are the 2 extremes we can do. A lot of people use repositories with ORM, but they just add an extra layer of code without real function, the only real function there is the query class like behaviour.
Also I'd be careful when someone talks about UnitOfWork, especially with ORM. Almost every sample on the internet is a fail in terms of architecture. If you need UoW, why not use TransactionScope (just make sure you got a wrapper which uses other than Serializable transaction by default). In 99,9% you won't need to manage 2 sets of independent changes in data (so 2 sets of OuW), so TransactionScope will be a fine choce in .NET - for PHP i'd look for some open-session-view implementations...

Categories