ddd - Where should synchronization with remote API go? - php

In order for my application to work, I need to synchronize regularly data from an outside service (could be an API, or a simple text file, but for now it is an API).
Since this would require creating / updating many entities at once, I need to create a Domain Service. However, I also need to create some DTOs that will contain the response of the remote API right ?
Where should this logic go ? Should I have the following directory structure:
Domain -
Model - // my set of entities and repository interfaces are here
....
Synchronization -
RunSynchronizationService.php // domain service
Application
Synchronization -
SynchronizeData.php // application service
SynchronizationDataSourceInterface.php // used by application service
MySpecificRemoteApiDataSource.php // this implements the interface above
SynchronizationDataSourceResponse.php // this would be returned by each call of SynchronizationDataSourceInterface method, and would contain data normalized, but not validated.
Infrastructure -
MyConcreteImplementationOfModelEntityRepository.php
And when I want to synchronize the data, I smply call Application\Synchronization\SynchronizeData's sync method, wich will take a concrete implementation of SynchronizationDataSourceInterface, call its methods, and validate the returned SynchronizationDataSourceResponse objects before transferring them to Domain\Model\Synchronization\RunSynchronizationService ?
Or should I remove RunSynchronizationService (the Domain Service) and let the Application Service (SynchronizeData.php) create / update the domain entities at each step of the synchronization process ?

Generally when presented with the question as to where an external service interface should live, I try to think of it in terms of it being another repository. The level of abstraction I choose here will depend highly on who will use the service (just the domain/app layers of this project? other projects?), if there are different versions/vendors of the service, and how which service to use is determined.
For your example, I'm going to assume that this application is the only one using the sync service directly. Shared services require common end points (such as the interface and output objects) to be isolated even further to avoid spilling unnecessary objects into other projects.
But in this case, to treat the service as another repository, I'd place the interface for it and standard output the domain expects and uses in the domain.
What is meant by "validation" is a little vague in your description, so I'll try to attack the different views of that here. One or all may apply.
If validation requires you to compare against domain data, it should probably reside in the RunSynchronizationService.php module. That module appears to be responsible for taking the sync data and applying it to your domain.
If validation is on the data coming back from the sync service call, and doesn't require direct access to the domain object graph, I would put that validation on the service implementation of the interface, and expose that validation call on the service interface. To handle the situation of that validation being the same across several versions of the sync service (such as VersionA, VersionB, etc), you can use inheritance and overrides, or common helper functions to the sync service, etc. In my example below, I used inheritance.
It could be you need to do both kinds of validation. First check for sync data problems agnostic to the domain (on the implemented classes), and then against business rules in the domain (in RunSynchronizationService). But likely both of those calls would occur in the RunSynchronizationService as you'd expose the sync data validation call on the interface.
The application layer should be responsible for creating the instance of the service (MySpecificRemoteApiDataSource), and passing it into the RunSynchronizationService.php module as SynchronizationDataSourceInterface. If there are multiple versions, the application layer would likely be responsible for choosing which one (from a configuration, perhaps), and using a factory.
But this again highly depends on the scope of that sync service. If you have external projects relying on it, you might want that factory part of the service layer itself so each of the other projects operate with the same choosing method.
Domain -
Model - // my set of entities and repository interfaces are here
....
Synchronization -
RunSynchronizationService.php // domain service
SynchronizationDataSourceInterface.php // used to define the contract associated with a sync service
SynchronizationDataSourceResponse.php // this would be returned by each call of SynchronizationDataSourceInterface method, and would contain data normalized, but not validated.
Application -
Synchronization -
SynchronizeData.php // application service - Uses a factory or some means of determining which version to use and introduce the domain to the data point.
Infrastructure -
MyConcreteImplementationOfModelEntityRepository.php
Synchornization -
VersionA -
MySpecificRemoteApiDataSource.php // Implements SynchronizationDataSourceInterface.php, inherits from SyncApiDataSourceBase.php
SyncApiDataSourceBase.php // Common logic for sync goes here, such as validation.

Related

PHP - Structuring a Slim3 web application using MVC and understanding the role of the model

I’m trying to create an authentication system in php with the Slim3 framework along with the Twig template system, and for the database I’m using MySQL with PDO. I’m also trying to implement it using a model view controller design pattern. However I’m having difficulty understanding how to use an MVC structure for a web application. I’ve looked at a plethora of explanations on the web and there doesn’t seem to be a clear cut answer. A lot of people say to to use a php framework such as Laravel, Symfony or CodeIgniter as they apparently employ an MVC like structure. However I would much rather keep things simple and to write the code manually rather than using a framework.
Currently there are two interpretations of MVC that I see. The first one being depicted in this diagram:
The other interpretation I’ve seen is this: (which is taken from this YouTube video)
I have done my research. Questions and answers such as this and this have been helpful. But I’m still not sure how I might structure my own applications, specifically indentifying and understanding the model aspect of MVC. I’ll now explain the register process of my authentication app. So you have an idea how my code is works.
Firstly I have an SQLQueries class that simply puts a series of SQL statements into functions. I then have a SQLWrapper class that has functions that can for example store a new users details inside the database. This class also calls functions from the SQLQueries class. I also have a ValidateSanitize class that has functions that cleans user input as well as checking if user input is valid in the form. These three classes I think are part of the model aspect of MVC but I'm not sure. I see a lot of other tutorials using a ‘User Model class’ but I can’t find the need for one in my application.
My views are simply Twig templates that display html, such as the homepage, register, login etc. I then have controllers. I intend to have multiple controllers that do different things. For now I’ve only implemented the AuthController which is responsible for Registering and Signing a user in.
So the first thing the AuthController does is to display the register form in a function called getRegisterForm. Once the user has submitted the form the postRegisterForm function takes that user input and assigns it to tainted variables.
public function postRegisterForm($request, $response)
{
$arr_tainted_params = $request->getParsedBody();
$tainted_email = $arr_tainted_params['email']; it a variable
$tainted_username = $arr_tainted_params['username'];
$tainted_password = $arr_tainted_params['password'];
$tainted_password_confirm = $arr_tainted_params['password_confirm'];
Next all of the three previous classes as well as the database details are instantiated so their functions can be used in the AuthController:
$sanitizer_validator = $this->container->ValidateSanitize;
$sql_wrapper = $this->container->SQLWrapper;
$sql_queries = $this->container->SQLQueries;
$db_handle = $this->container->get('dbase');
The tainted user details are then cleaned with the sanitize_input function. The cleaned user details are then fed into the validate functions to make sure they don’t trigger any validation violations. The password is also hashed here:
$cleaned_email = $sanitizer_validator->sanitize_input($tainted_email, FILTER_SANITIZE_EMAIL);
$cleaned_username = $sanitizer_validator->sanitize_input($tainted_username, FILTER_SANITIZE_STRING);
$cleaned_password = $sanitizer_validator->sanitize_input($tainted_password, FILTER_SANITIZE_STRING);
$cleaned_password_confirm = $sanitizer_validator->sanitize_input($tainted_password_confirm, FILTER_SANITIZE_STRING);
$hashed_cleaned_password = password_hash($cleaned_password, PASSWORD_DEFAULT);
$sanitizer_validator->check_email_exists($cleaned_email);
$sanitizer_validator->validate_email($cleaned_email);
$sanitizer_validator->validate_username($cleaned_username);
$sanitizer_validator->validate_password($cleaned_password);
$sanitizer_validator→validate_password_confirm($cleaned_password_confirm);
Finally there is an if statement that checks to see if all validation error messages are empty. If they are we provide the SQLWrapper class with the database details as well as a SQLQueries class object. We then insert the users details into the database by calling the SQLWrapper classes store-details function. Finally we direct the user to the login page, so the user can sign into their newly registered account.
if ($sanitizer_validator->get_validate_messages('email_error') == ' ' && $sanitizer_validator->get_validate_messages('username_error') == ' '
&& $sanitizer_validator->get_validate_messages('password_error') == ' ' && $sanitizer_validator->check_passwords_match($cleaned_password, $cleaned_password_confirm ) == true
&& $sanitizer_validator->check_email_exists($cleaned_email) == false)
{
$sql_wrapper->set_db_handle($db_handle);
$sql_wrapper->set_sql_queries($sql_queries);
$sql_wrapper->store_details($cleaned_email, $cleaned_username, $hashed_cleaned_password);
return $response→withRedirect($this→container→router→pathFor('login'));
}
However if any of the validate error messages are not blank, then we call the SanitiseValidate display_validate_messages which simply sets the messages into a session to be displayed on the register twig template. We then redirect back to the register page so the user can see the validation error messages.
else
{
$sanitizer_validator->display_validate_messages();
return $response->withRedirect($this->container->router->pathFor('register'));
}
}
So based on this structure of a user registering an account. Does this adhere to a clean simple MVC structure or do some changes need to be made? Do any of my classes take the role of a model? Any suggestions and tips regarding my structure will be appreciated.
The full application can be seen on my GitHub if that would be helpful. Note that this version is slightly older than the sample code I used in this question.
Indeed, there are multiple approaches regarding how the MVC pattern should be applied in web applications. This multitude of variants is the result of the simple fact, that the original MVC pattern - developed for desktop applications (by Trygve Reenskaug, in 1979) - can not be applied as is to the web applications. Here is a little description. But, from this set of approaches, you can choose one which best complies with your requirements. Maybe you'll try more of them before you'll make your mind. Though, at some point, you'll know which one fits to your vision.
In the following diagrams I tried to present my chosen approach on the web MVC workflow - mainly inspired by Robert Martin's presentation Keynote: Architecture the Lost Years (licensed under a Creative Commons Attribution ShareAlike 3.0).
In general, you could think of a web MVC application as composed of the following parts:
Domain model (e.g. model, e.g. model layer);
Service layer (optional);
Delivery mechanism;
Other components (like own libraries, etc).
1) The domain model should consist of the following components:
Entities (e.g. domain objects) and value objects. They model the business rules in terms of properties and behavior and, being application-independent, can be used by multiple (types of) applications.
(Data) mappers and, optional, repositories. These components are responsible with the persistence logic.
External services. They are used to perform different tasks involving the use of external/own libraries (like sending emails, parsing documents, etc).
Further, the domain model could be split into two parts:
a) Domain model abstraction. This would be the only space of the model layer accessed by the components of the delivery mechanism, or by the services of the service layer - if one is implemented:
Entities and value objects;
(Data) mapper abstractions and, optional, repository abstractions;
Abstractions of external services.
Note: By abstractions I mean interfaces and abstract classes.
b) Domain model implementation. This space would be the one in which the implementations of the different domain model abstractions (see a) would reside. The dependency injection container (as part of the delivery mechanism) will be responsible with passing instances of these concrete classes as dependencies - as constructor arguments, for example - to the other components of the application (like controllers, views, services, etc).
2) Service layer (optional): Technically, the components of the delivery mechanism could directly interact with the elements of the domain model. Though such interactions involve (a lot of) operations, specific only to the model, not to the delivery mechanism. Therefore, a good choice is to defer the execution of these operations to service classes (e.g. services), as part of the so-called service layer. The delivery mechanism components will then use only these services to access the domain model components.
Note: The service layer can, actually, be seen as part of the model layer. In my diagrams bellow I preferred to display it as a layer residing outside the model. But, in the file system example, I put the corresponding folder in the domain space.
3) The delivery mechanism sums up the constructs used to assure the interaction between the user and the model layer's components. By user I don't mean a person, but an interface with which a person can interact - like a browser, a console (e.g. CLI), a desktop GUI, etc.
Web server: parses the user request through a single point of entry (index.php).
Dependency injection container: provides the proper dependencies to the different components of the application.
HTTP message (e.g. HTTP request and HTTP response) abstraction (see PSR-7: HTTP message interfaces).
Router: matches the request components (HTTP method and URI path) against the components of each route (HTTP method and pattern) in a predefined list of routes and returns the matched route, if found.
Front controller: matches the user request against a route and dispatches it to a certain controller and/or view action.
Controllers. They write (e.g. perform create, update and delete operations) to the model layer and (should) expect no results. This can happen by directly interacting with the components defined in the domain model, or, preferably, by only interacting with the service classes.
Views. They should be classes, not template files. They can receive a template engine as dependency. They only fetch data (e.g. perform read operations) from the model layer. Either by directly interacting with the components defined in the domain model, or, preferably, by only interacting with the service classes. Also, they decide which result (like a string), or template file content, will be displayed to the user. A view action should always return a HTTP response object (maybe as defined by the PSR-7 specification), whose body will be before-hand updated with the mentioned result or template file content.
Template files. Should be kept as simple as possible. The whole presentation logic should happen only in the view instances. So, the template files should contain only variables (be they pure PHP ones, or presented with the used template engine syntax) and, maybe, some simple conditional statements, or loops.
Response emitter: reads the body of the HTTP response instance returned by the view and prints it.
4) Other components. As wished. For example some libraries developed by your own. Like an implementation of the PSR-7 abstraction.
How I chose to dispatch the user request:
As you see in the diagrams above, the front controller dispatches the user request not only to a controller action (in order to update the domain model), but also to a view action (in order to read and display the updated state/data from the model layer). Kind of a splitted dispatch. This can be relatively easy achieved by assigning the controller action and the view action to each route (like bellow), and telling the front controller to call them successively:
<?php
use MyApp\UI\Web\Application\View;
use MyApp\UI\Web\Application\Controller;
// Note: $this specifies a RouteCollection to which the route is added.
$this->post('/upload', [
'controller' => [Controller\Upload::class, 'uploadFiles'],
'view' => [View\Upload::class, 'uploadFiles'],
]);
This approach gives flexibility in regard to the user request dispatch. For example, the name of the view action can be different from the name of the controller action. Or, in order to only fetch model layer data, you don't need to dispatch the user request to a controller, but only to a view. Therefore you don't need to assign a controller action in the route at all:
<?php
use MyApp\UI\Web\Application\View;
$this->get('/upload', [View\Upload::class, 'listFiles']);
File system structure example:
myapp/domain: folder containing the domain model classes and the services. This directory could be brought into the "myapp/web/src" folder, but it shouldn't, because the model layer and the service layer are not part of the delivery mechanism.
myapp/web: folder containing the delivery mechanism classes. Its name depicts the type of application - can be a web app, a cli app, etc.
myapp/web/src:
Resources:
*) Sandro Mancuso : An introduction to interaction-driven design
*) The ones listed in an older answer of mine.
*) The tutorials presented by Alejandro Gervasio:
Building a Domain Model – An Introduction to Persistence Agnosticism
Building a Domain Model – Integrating Data Mappers
Handling Collections of Aggregate Roots – the Repository Pattern
An Introduction to Services
*) The example on the Slim 3 page: Action-Domain-Responder with Slim.
There is a course where you get walked through making MVC with slim 3. Ill link it here : https://codecourse.com/courses/slim-3-authentication . Hope this helped, its a really easy to follow course and you learn alot.

State machines and framework

I'm trying to understand bits and pieces of how frameworks are meant to be used. I'm working on a custom framework i.e. built by using essential components of Symphony2.
So are we understand MVC there is a controller that handles our routing methods. Beside this we have models & repo ( incase of Symphony2 type implementation ).
What i'm confused at is how do i integrate or implement state machines. I would like to know what part goes where.
I would like to use following library,
https://github.com/yohang/Finite
Now my current state is persisted in the table column.
So where do i implement state machine interface, models? Where do initialise state machine, controller?
As far as the model goes, you simply have your model object implement the StatefullInterface. If, for example, you are using Doctrine 2 then your model object is just a plain php object. Implement the interface per your link and you are done.
For your state machines I would make custom state machines:
class MyStateMachine extends StateMachine
{
public function __construct()
{
$this->addState(new State('s1', StateInterface::TYPE_INITIAL));
$this->addState('s2');
$this->addState('s3');
$this->addState(new State('s4', StateInterface::TYPE_FINAL));
$this->addTransition('t12', 's1', 's2');
$this->addTransition('t23', 's2', 's3');
$this->addTransition('t34', 's3', 's4');
$this->addTransition('t42', 's4', 's2');
And then you could create and initialize the object in your controller. As an alternative use dependency injection and make a factory service.
I suppose you could also embed the state machine directly in your entity. Probably not a good idea.
The state machine you linked to seems a bit basic. Only supports one state per object? I have not checked the code but the transitions also seem pretty primitive. Make sure it fulfills your needs before investing too much time in it. I always just create custom machines.
You can implement your entity using a state machine, meaning the state machine will be placed in model layer and rest of the application will interact with it - read its state and invoke transitions.
The entity will provied API to invoke transitions, read its state and enumerate available transitions (like reflection, but with regard to current state). The rest of the application can ask individual instances of the entity what can be done next and show relevant parts of user interface. For example it can show a button to delete an entity which has delete transition available in its current state. And when the delete button is clicked, it will invoke the delete transition on given state machine. I found this approach very universal.
Some time ago I created Smalldb framework which implements such state machines. It implements model layer of a web application and lets you define state machines for individual entities and implement their transitions in PHP. It also checks which user is allowed to invoke which transitions and has few nice features like state machine visualization using Graphviz and REST API to directly interact with the state machines from JS (nice for SPA applications).

Can Domain Driven Design Application layer have Models

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.

Abstraction of external service / API request and response

TLDR: Writing a service (in the model layer). It talks to ffmpeg. Where should validation go? Should I create a service response object so it is testable? How should it be structured?
Background: I'm designing some classes to retrieve data from an external service. It could be an API, but in fact it's calls to ffmpeg cli, which in effect is an API to the conversion tools themselves.
When talking to an external service, where the data retrieved may not always be the same, how is it best to go about maintaining at least a consistent application state on your end so your application doesn't depend on the external service to work?
I have already separated out the classes thus far, trying to maintain SRP within them:
class CommandDispatcher { }
The Command Dispatcher's sole job is to make a request for data (to ffmpeg) and retrieve the response for that data back.
class Converter { }
The converter's sole responsibility is to take user requests (like convert 1 to 2), and send the basics to the command dispatcher which handles the exec() calls.
Here are my questions:
When talking to an external API / service, should I be creating an APIRequest and an APIResponse object (in this case an FFmpegResponse object)?
I have seen examples of this for OAuth, where there is an OAuth response object. However, that's simple enough because calls to this are done over the HTTP protocol which tends to give back at minimum an error code and a message. Calls to something like ffmpeg don't guarantee a similar response (ffmpeg may not be installed, for example). Is this object merely a domain object (i.e. an entity: some class members and setters and getters)?
Validation. If I am creating an FFmpegResponse object, whose job is it to put the data into the right members of the Response object?
Imagine ffmpeg isn't installed and the CommandDispatcher gets the response back empty. Is it up to the CommandDispatcher to then populate the FFmpegResponse object with an "ffmpeg not installed" error? Should I have a validation object do this?
Remember, I'm trying to stick to the Single Responsibility Principle here, so I'm thinking that the CommandDispatcher shouldn't care about whether the data is valid or not - it should merely ask for data and retrieve it. Where does my validation fit within the model layer for this service?
This isn't only for FFmpeg but will help for future external service calls. What is the best [practice] way to structure your code and classes to maintain SRP yet also a consistent application state regardless of whether or not the external service responds in an expected way?
In your current structure, CommandDispatcher should be either an interface or an abstract class (depending on the necessity of abstract code). You would then create a concrete implementation: FFMpegCommandDispatcher which would encapsulate the understanding of ffmpeg specific responses.
Response objects will then take on a similar structure: CommandResponse would be an abstraction with the concrete implementation FFMpegCommandResponse.
It would be best to create a set of common error conditions (serviceNotAvailable, serviceNotInstalled, serviceDiedAHorribleAndBloodyDeath, etc). Your dispatcher implementation can then set a common error code on the response object and provider implementation specific details. ('Error 1984: FFMpeg is watching you')
If you're concerned (and I would be) about validating input as well. You could create a CommandRequest abstraction, and FFMpegRequest implementation, that will take user input and make sure that it's okay to be sent to the command line.

How to store model state when model is a layer

How are you meant to store the state of the model in MVC when the model is a layer, and accessed via services. Do you give the service class a state? How would that state be communicated to the View, when the View may or may not use that specific service?
I currently have a model entity to store different states, all my services log their issues, successes and state in this entity. I store this entity in the session, but the whole thing feels wrong...
I am considering that state is more than error/success.
If your views never know which service has been used by controller to alter the state of model layer, then your best approach would be instead implement classical MVC (or close to it) with current view observing the model. In that case each used service would inform the view, when it has been acted upon by controller. If that's the case, then content below does not apply.
The bad idea ..
The views and controllers should share the factory, which is responsible for initializing the services. this means that if you controller has used a particular service, then you can add an ability to query this factory about services that it has initialized already.
if ( $this->serviceFactory->hasCached('recongnition') )
But that should not be necessary and IMHO, that would be a really harmful thing to do. You would be forcing the factory to become a vital part of UI logic.
Note: the factory in this case enforces, that each service is create only once, without dependence on global state.
Different approach/perspective
For some reason, you start out with a premise, that every view has to be omniscient. That's what causing you current confusion.
Instead of knowing everything about everything the two fictional services:
Accounting: for dealing with invoices
Library: for managing documents
When you are looking at the page, which list the current document, why would the view care, that there is an error state in Accounting service? How would you actually achieve that error state?
Would an error state in any of those services affect how the "login page" looks like?
So. The bottom line here is this: even if controller does something, which causes an error state somewhere in the model layer, the view should only know about it, only if the view needs that particular service.
Note:Of course since in web applications the views and controllers tend to form pairs (if there is controller for handling "Document List", then there probably will also be a corresponding view), it will be and extremely rare occasion, when controller utilizes some service of which the current view is not aware of ... I actually cannot think of a use-case for such occurrence.
P.S.
Actually the state of model layer is not held in the services themselves, but in the domain objects which they manipulate.
If you use a shared factory, which can make sure that each service is initialized only once, then the service, that view uses, will be the same. It also means, that the domain objects, with which service worked, can still be there (depends on your implementation, of course).
For example, if you try to create user account, with an email that already exists, the domain object for representing the account details will acquire an error state, when storage abstraction gets an exception about violating UNIQUE constraint. To show a good "registration failed" page, the service will need that domain object with both its data and its error state.
I hope it helps

Categories