I have a PHP MVC application. The business logic is implemented in a service layer and a domain model. My question is, where should I implement authorisation checks? In the service layer? Or the domain model?
In a discussion on the service layer pattern, http://martinfowler.com/eaaCatalog/serviceLayer.html, Martin Fowler prefers to separate 'application logic' from 'business logic'. The former goes in the service layer, the latter in the domain objects.
Some of my authorisation rules are complex. Authorisation can depend on the current user, their roles, the state of many otherwise unrelated objects, etc. These seem to belong in the domain objects, or in some cases the factories for these objects.
But in other cases, the rules are quite simple. For example, "only a supervisor can approve a new noticeboard post". In these cases I am tempted to check authorisation in the service layer. It obviates the security requirements, and by putting them in a (mock-able) service layer listener, my code becomes easier to test.
So, the question is should I put simple authorisation checks in the service layer, and more complex ones in the domain objects? Or am I asking for trouble by splitting it across two layers?
OK, So I moved the authentication code to the service layer and found that there were only a couple of instances where I still needed to do additional checks in the model. For consistency, I could pull these checks into the service layer too, at the expense of performance, but so far I have not felt the need.
Related
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.
Can an application layer in ddd have models?
To be more explicit, I have a credential entity in my system that is related to the authentication process which is outside of my domain layer, so where this entity will be? I'm new at Domain Driven Design.
The Application Layer can use its own data representations. If you wire it to the user interface, the Application Layer will have to translate Domain objects to view-able data.
But I wouldn't call this "model", except maybe in the sense of "view model."
Without more details, it's hard to say anything more useful, so I'll try to answer to your integration problem by example.
Vaughn Vernon's example app
Taking a look at Vernon's sample application, you can have an authentication service isolated from your consuming application. Vernon models three stand-alone Java applications for this.
Now there's the IdentityAccess service providing all the authentication. There, you can create Tenant Entities. Then there's the Collaboration app (forum etc.) which uses its own internal representation of Tenant.
So the client app obtains a TenantId and creates its own Tenant objects to associate forum threads with a tenant. Tenants aren't changed or persisted from within this app, only used.
Tying Domain objects to stuff outside it
Your point may be even simpler. If you have a Credential Entity (in your Domain) and some auth logic outside of it, make the "authenticator" implement a specialized interface of the Domain and inject it back into Domain objects if you really need to. (That's the Ports & Adapters approach: both sides may specify interfaces and wait for concrete implementations; the other side implements the interface and injects an object back in.)
I guess you don't really have to have access from within your Domain to the authentication logic, but we'd have to see more code to judge this.
Vernon uses an AuthenticationService inside the Domain to handle wrong login details.
I have found some explanation http://www.bennadel.com/blog/2379-a-better-understanding-of-mvc-model-view-controller-thanks-to-steven-neiland.htm which describes the MVC architecture.
The model is described in the following way:
The Model's job is to represent the problem domain, maintain state, and provide methods for accessing and mutating the state of the application. The Model layer is typically broken down into several different layers:
Service layer - this layer provides cohesive, high-level logic for
related parts of an application. This layer is invoked directly by
the Controller and View helpers.
Data Access layer - (ex. Data Gateway, Data Access Object) this layer
provides access to the persistence layer. This layer is only ever
invoked by Service objects. Objects in the data access layer do not
know about each other.
Value Objects layer - this layer provides simple, data-oriented
representations of "leaf" nodes in your model hierarchy.
What is the goal of the Value Objects layer? I couldn't find any good explanation...
Thanks
I will preface by saying I don't completely get it either, but I'll take a stab at my interpretation:
Different models are used in different parts of your code, and it sounds like here they are referring to more light weight models/objects that have no dependency on deeper parts of your project like services or the data layer. These objects are used purely for at the view/presentation layer.
Although I could be completely wrong!
EDIT: Removed the part about DTOs since it wasn't quite right.
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.
My experience is mostly limited to PHP, yet as far as I know both Rails and ASP.NET MVC have taken the same path.
The point is that nearly every web framework I've ever come across implements controller actions as methods, e.g. create, edit, show, etc. These methods reside in a single class like PostsController, but they hardly ever share state or dependencies, because only one of them gets called during the whole request.
That's why to me this approach seems quite unreasonable, as the class only acts as some kind of namespace. Seeing examples with large chunks of barely related controller action code composing even larger controller classes doesn't help either. Yet a lot of frameworks do exactly that, and only a few use a class for each action.
So the question is, why is it so? Perhaps it's subjective, but I believe that I may have missed an important advantage of this approach.
I would argue that the MVC design pattern in general dictates this approach to building controllers. The main purpose of the controller is to provide the appropriate "wiring" between the associated view and the models it needs to interact with, along with any business logic needed to handle the input from the view. Controllers should just be a thin layer between these other components.
For example, Wikipedia describes the controller as follows:
The controller receives input and
initiates a response by making calls
on model objects. A controller accepts
input from the user and instructs the
model and viewport to perform actions
based on that input.
I do agree that controllers in other, non-web environments do maintain state, but the reason for the lack of state in PHP, for example, is simply that HTTP is a stateless protocol. Using MVC in this environment is inherently going to result in controllers that don't maintain state.
Why do so many MVC web frameworks favor grouping multiple controller actions in a single class?
That is essential to object oriented programming resulting in a properly layered software architecture where the controller objects encapsulate all responsibilities about domain objects (model). If there is a PostModel, then there should be a PostController responsible for calling the right business methods on the domain api to satisfy the user request and to push the results into the view. Having a controller class for every single possible request leads to a procedural structured architecture in my opinion.
On the other hand, if you have too many resonsibilities in your controller class, you should split these responsibilities into multiple controllers. It depends on your application at hand, there is no one-fits-all solution. Every controller should be responsible for a cohesive group of actions on the domain layer.