Design problem for DDD and User entity implementing Symfony's UserInterface - php

Why Symfony docs suggest to implement UserInterface interface on my domain User entity?
https://symfony.com/doc/3.4/security/entity_provider.html
class User implements UserInterface, \Serializable {}
To me it looks like this is breaking a basic DDD approach because my domain entities should never rely on something that resides outside the domain (in this case UserInterface is a Symfony component).
The problem is that Symfony's UserPasswordEncoder need UserInterface object to retrieve salt/password from users.
At the moment I have a very sketchy solution that it is not bullet-proof/scalable at all, so I'm looking for solutions.
Do I need to implement my own UserPasswordEncoder that can work directly on my Domain User entity?

To me it looks like this is breaking a basic DDD approach because my domain entities should never rely on something that resides outside the domain (in this case UserInterface is a Symfony component).
Theoretically speaking you are correct. Your Aggregates should not depend in any way to the Infrastructure.
Many frameworks are focused on enabling fast delivery of software, not on clean code. From what've seen, Symfony is more suitable for CRUD Entities, in simple domains, not for complex domains where DDD is more suitable. This means that maybe you should not use DDD in this domain, and maybe a CRUD entity would suffice.
Or maybe, if you think the User should indeed be a DDD Aggregate because it has complex behavior, then you should extract the UserPassword into its own CRUD Entity, that is not bound to DDD restrictions. Then, in your User Aggregate, you refer to the password only by ID, i.e. private $passwordId;.
Do i need to implement my own UserPasswordEncoder that can work directly on my Domain User entity?
I think this would be the same thing as the framework's component, at least from the DDD point of view. The password hashing is an infrastructure component, no matter who's implementing it.

Related

Doctrine inheritance strategy when two different subclasses extend the same entity instance

I am developing an application for managing court interpreter services (using Doctrine and Zend Framework 2). There are a lot of people involved who have various specialized roles, hence a Person superclass, and subclasses. The class hierarchy is not complicated in a vertical sense -- one generation of inheritance is enough -- but the horizontal aspect is giving me trouble.
I don't think mapped superclasses fit my case. I also considered single-table inheritance but that would quickly get ugly because the subclasses have their own entity relationships, too much stuff to cram gracefully into a single table.
That leaves us with class table inheritance, which is a really nice fit in most respects, but... I will have plenty of cases where the subclass User (for authentication) and the subclass Interpreter will (or should) point to the same row in the parent data table, because they represent one and the same person in reality. But because of the discriminator column you have to choose one or the other, or else create two different rows holding the same data -- and the normalization police should get you for that.
I think maybe either the User or the Interpreter entity has to simply have a one-to-one relationship with the Person entity, and deal with that semi-manually. Another option I suppose would be to collapse User into Person -- but that's ugly because a lot of people will not be authenticating and will not have or need a password.
I have looked at
Doctrine inheritance, several entities extending the same super class and
How to change and entity type in Doctrine2 CTI Inheritance (inter alia) and neither one solves this.
So, I wonder if anyone has any suggestions. Thanks.
It sounds like you're managing a bunch of data about Persons, which identifies individual humans in the world. Since only some subset of the people in the system are Users, I'd argue that concerns about authentication, audit logging, notifications, etc are separate from the concerns of the Person class hierarchy.
I'd advise removing User from the Person class hierarchy. Perhaps rename it Account, to make it feel less person-y. An Account can have an owner property, which is a relation to Person. If you want to use the Person's email address as an identifier for authentication, that's fine. If you later wanted to add a username instead, that would be a property of Account, since it's only meaningful in that context.
Not sure about the underlying code (not a ZF developer), but I think you are confusing the behavior and the data.
To make the authentication working you do not need the inheritance really. Just found you code ontop of the interface dependencies.
To make the users able to auth (while generic person could not) - use the inheritance or, as #timdev suggested, the relation. In symfony world I'd better write this something like
class User extends Person implement UserInterface {
//... implementation
}
class Person {
//...
}
After that you can just be sure, that you have a UserInterface while any service stuff and authentication particularly.
In case if you have to dynamically switch the underlying class of User entity (i.e. you have Author extends Person and want allow some authors to sign in) I think the composition is the only suitable solution. Split the logic, split the entites, split the data. Be happy.

Adapting DDD interfaces to a concrete implementation

I'm currently trying to understand how to develop DDD classes, without any assumptions on the implementations that may need to use them. I managed to develop a small structure, made of a user object called User which implements a IUser interface so I can keep an efficient abstraction for reuse purposes.
I now would like to use this user object in a concrete implementation, by using Symfony2 in my case. In order to benefit from the Symfony security layer, my user object needs to implement the UserInterface interface provided by Symfony.
If I understand the pattern correctly, this would be a great opportunity to implement an Adapter called UserAdapter which would allow me to make my user class work with Symfony. So far so good, this works perfectly fine. But here goes my problem :
Suppose I add a Comment class in my DDD lib, which has an $user attribute. To bind a user to a comment, I use for instance a setUser() setter which requires anything that implements the IUser interface. If tomorrow I want to change the user class to be used in this context, all I need is a new user class that implements the IUser interface.
But in my concrete implementation, in a Symfony controller for example, I'm using an instance of the UserAdapter class, which implements the Symfony UserInterface interface. When calling the setUser() setter on my Comment object, the interface doesn't match.
What am I missing?
Am I using the Adapter pattern in a wrong way, should I use a different strategy in my implementation?
There are two solutions that come to my mind. One solution works with inheritance, one with delegation.
Inheritance
In your UserAdapter class extend from your DDD User class. Also implement the Symfony2 UserInterface in the adapter. Now implement the methods from the UserInterface by using the attributes from the parent class.
Delegation
Same as in the inheritance case the UserAdapter class must implement the Symfony2 UserInterface. But now you create an association from the adapter to the concrete user class. So your adapter "has one" user. To avoid having adapters without a user you can require a user in the adapters constructor. Then you can call the setUser method with setUser($userAdapter->getUser()).

Objective oriented design in a PHP MVC Framework

Traditionally in a MVC framework (Such as CodeIgniter or Kohana) I create controllers as I create different pages. There will be a login controller, a home controller and so on. But recently I learned more about objective oriented programming and want to start using it. And even though the framework uses classes, it's not the same principle as an object.
Yes. The login controller is as an object. But where am I supposed to write my "User" class for example? Do I write them in a library and import them when needed? What is the proper way of doing this, if there even is any.
I'm just puzzled on how I can do this right.
<rant>
If you start out with frameworks that are either direct Rails clones or heavily influenced by Rails architecture, you are not really implementing MVC. Ruby on Rails framework was originally intended to be a purely rapid prototyping framework, which means that they sacrificed most of MVC concepts on "The Altar of Scaffolding".
Rails-based PHP frameworks replace fully functional views with templates, model layer with some collection of active record instance and for the "controller" to deal with all the presentation and application logic.
</rant>
The bases of MVC design pattern is the separation between business logic (contained in model layer) and user interface (managed by presentation layer). These two layers each contains different groups of structure.
The User is not a model. There are no "models" in modern MVC. Instead your User instance is a domain object. Also, it should not be directly exposed to the controllers or other presentation layer structures.
The interaction between presentation layer and model layer should be performed by services. Services in model layer are structures, which are responsible for handling the interaction between domain objects and storage abstractions (either data mappers directly or via repositories and/or units of work).
namespace Controller;
class Authentication
{
// .... snip
public function postLogin( $request )
{
$service = $this->serviceFactory->create('Recognition');
$service->authenticate( $request->getParameter('username'),
$request->getParameter('password') );
}
// .... snip
}
In this case the User instance is somewhere inside the recognition service, which is there to deal with different business-logic aspects of user authentication. And do not confuse it with authorization. For authorization in MVC context there is a bit different recommended approach.
P.S.: if you are just now starting to really delve into OOP, you might find this list useful in your research.
my two cents
It is better to write your User class as a library since it is not a controller(assumption) and you should not have direct access to the User class through the URL. So the best practice is to write a Class if you want it to be object oriented. Or you can create a helper file if you want to have static functions.
I think it's too individual. Really depends on what kind of application is built. Let's think out of the CodeIgniter or Kohana, but for your individual framework, with individual application.
If you have simple login system, where the user is nothing but a Name and an ID, and all the interactions are between the other stages of the application, instead interactions between the users, your User Class which only contains information about the user (simple queries to the db which retrieves certain information from users table), can be a helper.
But in some applications (platforms in this case), the user might be an equal to any other object in it.
For example building a Forum-like application, you might want to have Warn level, Reputation, various logs of user actions, etc.
Also the user is an equal object like a 'topic', which also have for example likes/dislikes, priority, etc.
In this case you build a model and a controller for the user. For example in your Model you will have methods like
createUser(), getUser(), getUserWarnActions(), updateUserActions(), logUserActionChange(), etc, etc.
All of that methods, will be in a class called i.e. UserModel which extends the Model main class
where for example UserActions are the warn level, the email change, username change, reputation change.
In your controller, you might want to have
updateWarnLevel() => which interracts with updateUserActions(), tells the model it's action = warn level, and updates it, by the given value
so these methods will be in a class i.e. called UserController which extends the Controller main class
But at all it really depends how you look on your User class as. According to me it will be bad practice to have Controller/Model called Warn level, since it's a part of another abstraction, but not individual one.
To assume which is a child or a parent, I would try to make a structure, like a db one, and then create models/controllers/helpers.
If you have the following database tables:
users
user_reputation
user_warnlevels
topics
topic_votes
warn_levels // contains i.e. id | level | something_which_depends_on_the_level
It definately means that Users and Topics would be Models/Controllers in your application, where warn_levels won't be, since they are separate table only because they have some logic, but they are no parent table, only child one

Domain driven design, entity lazy loading

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.

Service layer and model associations with Domain-Driven Design

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.

Categories