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.
Related
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.
I started playing with DDD recently. Today I'm having a problem with placing validation logic in my application. I'm not sure what layer should I pick up. I searched over the internet and can't find an unified solution that solves my problem.
Let's consider the following example. User entity is represented by ValueObjects such as id (UUID), age and e-mail address.
final class User
{
/**
* #var \UserId
*/
private $userId;
/**
* #var \DateTimeImmutable
*/
private $dateOfBirth;
/**
* #var \EmailAddress
*/
private $emailAddress;
/**
* User constructor.
* #param UserId $userId
* #param DateTimeImmutable $dateOfBirth
* #param EmailAddress $emailAddress
*/
public function __construct(UserId $userId, DateTimeImmutable $dateOfBirth, EmailAddress $emailAddress)
{
$this->userId = $userId;
$this->dateOfBirth = $dateOfBirth;
$this->emailAddress = $emailAddress;
}
}
Non business logic related validation is performed by ValueObjects. And it's fine.
I'm having a trouble placing business logic rules validation.
What if, let's say, we would need to let Users have their own e-mail address only if they are 18+?
We would have to check the age for today, and throw an Exception if it's not ok.
Where should I put it?
Entity - check it while creating User entity, in the constructor?
Command - check it while performing Insert/Update/whatever command? I'm using tactician in my project, so should it be a job for
Command
Command Handler
Where to place validators responsible for checking data with the repository?
Like email uniqueness. I read about the Specification pattern. Is it ok, if I use it directly in Command Handler?
And last, but not least.
How to integrate it with UI validation?
All of the stuff I described above, is about validation at domain-level. But let's consider performing commands from REST server handler. My REST API client expects me to return a full information about what went wrong in case of input data errors. I would like to return a list of fields with error description.
I can actually wrap all the command preparation in try block an listen to Validation-type exceptions, but the main problem is that it would give me information about a single error, until the first exception.
Does it mean, that I have to duplicate my validation logic in controller-level (ie with zend-inputfilter - I'm using ZF2/3)? It sounds incosistent...
Thank you in advance.
I will try to answer your questions one by one and additionally give my two cents here and there and how I would solve the problems.
Non business logic related validation is performed by ValueObjects
Actually ValueObjects represent concepts from your business domain, so these validations are actually business logic validations too.
Entity - check it while creating User entity, in the constructor?
Yes, in my opinion you should try to add this kind of behavior as deep down in the Aggregates as you can. If you put it into Commands or Command Handlers you loose cohesiveness and business logic is leaking out into the Application layer. And I would even go further. Ask yourself the question if there are hidden concepts within your model that are not made explicit. In your case that is an AdultUser and an UnderagedUser (they could both implement a UserInterface) that actually have different behavior. In these cases I always strive for modelling this explicitly.
Like email uniqueness. I read about the Specification pattern. Is it ok, if I use it directly in Command Handler?
The Specification pattern is nice if you want to be able to combine complex queries with logical operators (especially for the Read Model). In your case I think this is an overkill. Adding a simple containsUserForEmail($emailValueObject) method into the UserRepositoryInterface and call this from the Use Case is fine.
<?php
$userRepository
->containsUserForEmail($emailValueObject)
->hasOrThrow(new EmailIsAlreadyRegistered($emailValueObject));
How to integrate it with UI validation?
So first of all there already should be client side validation for the fields in question. Make it easy to use your system in the right way and hard to use it in the wrong way.
Of course there still needs to be server side validation. We currently use the schema validation approach where we have a central schema registry from which we fetch a schema for a given payload and then can validate JSON payloads against that JSON Schema. If it fails we return a serialized ValidationErrors object. We also tell the client via the Content-Type: application/json; profile=https://some.schema.url/v1/user# header how it can build a valid payload.
You can find some nice articles on how to build a RESTful API on top of a CQRS architecture here and here.
Just to expand on what tPl0ch said, as I have found helpful... While I have not been in the PHP stack in many years, this largely is theoretical discussion, anyhow.
One of the larger problems faced in practical applications of DDD is that of validation. Traditional logic would dictate that validation has to live somewhere, where it really should live everywhere. What has probably tripped people up more than anything, when applying this to DDD is the qualities of a domain never being "in an invalid state". CQRS has gone a far way to address this, and you are using commands.
Personally, the way that I do this, is that commands are the only way to alter state. Even if I require the creation of a domain service for a complex operation, it is the commands which will do the work. A traditional command handler will dispatch a command against an aggregate and put the aggregate into a transitional state. All of this is fairly standard, but I additionally delegate the responsibility of validation of the transition to the commands themselves, as they already encompass business logic, as well. If I am creating a new Account, for example, and I require a first name, last name, and email address, I should be validating that as being present in the command, before it ever is attempted to be applied to the aggregate through the command handler. As such, each of my command handlers have not just awareness of the command, but also a command validator.
This validator ensures that the state of the command will not compromise the domain, which allows me to validate the command itself, and at a point where I do not incur additional cost related to having to validate somewhere in the infrastructure or implementation. Since the only way that I have to mutate state is solely in the commands, I do not put any of that logic directly into the domain objects themselves. That is not to say that the domain model is anemic, far from it, actually. There is an assumption that if you are not validating in the domain objects themselves, that the domain immediately becomes anemic. But, the aggregate needs to expose the means to set these values - generally through a method - and the command is translated to provide these values to that method. On of the semi-common approaches that you see is that logic is put into the property setters, but since you are only setting a single property at a time, you could more easily leave the aggregate in an invalid state. If you look at the command as being validated for the purpose of mutating that state as a single operation, you see that the command is a logical extension of the aggregate (and from a code organizational standpoint, lives very near, if not under, the aggregate).
Since I am only dealing with command validation at that point, I generally will have persistence validation, as well. Essentially, right before the aggregate is persisted, the entire state of the aggregate will be validated at once. The ultimate goal is to get a command to persist, so that means that I will have a single persistence validator per aggregate, but as many command validators as I have commands. That single persistence validator will provide the infallible validation that the command has not mutated the aggregate in a way that violates the overarching domain concerns. It will also have awareness that a single aggregate can have multiple valid transitional states, which is something not easily caught in a command. By multiple states, I mean that the aggregate may be valid for persistence as an "insert" for persistence, but perhaps is not valid for an "update" operation. The easiest example of that would be that I could not update or delete an aggregate which has not been persisted.
All of these can be surfaced to the UI, in my own implementation. The UI will hand the data to an application service, the application service will create the command, and it will invoke a "Validate" method on my handler which will return any validation failures within the command without executing it. If validation errors are present, the application service can yield to the controller, returning any validation errors that it finds, and allow them to surface up. Additionally, pre-submit, the data can be sent in, follow the same path for validation, and return those validation errors without physically submitting the data. It is the best of both worlds. Command violations can happen often, if the user is providing invalid input. Persistence violations, on the other hand, should happen rarely, if ever at all, outside of testing. It would imply that a command is mutating state in a way that is not supported by the domain.
Finally, post-validation of a command, the application service can execute it. The way that I have built my own infrastructure is that the command handler is aware of if the command was validated immediately before execution. If it was not, the command handler will execute the same validation that is exposed by the "Validate" method. The difference, however, is that it will be surfaced as an exception. Goal at this point is to halt execution, as an invalid command cannot enter the domain.
Although the samples are in Java (again, not my platform of choice), I highly recommend Vaughn Vernon's "Implementing Domain-Driven Design". It really pulls a lot of the concepts in the Evans' material together with the advances in the DDD paradigm, such as CQRS+ES. At least for me, the material in Vernon's book, which is also a part of the "DDD Series" of books, changed the way I fundamentally approach DDD as much as the Blue Book introduced me to it.
Does anyone know how to pass an instance of a custom Service Manager between 2 actions? As the Zend Framework 2 documentation says, a SM will preserve it's instance if the 'shared' option inside the Module.php class will not be set to false. However, getting the service manager via $manager = $this->getServiceLocator()->get('MyServiceManager'); in different actions will return different instances of the MyServiceManager class. What I want to achieve is: I use an API call to a third party service, which obviously returns a response with various information data, however, if the user heads to another action/page where the same data returned previously from the API request is needed would be nice to save it as a MyServiceManager property and being accessed whenever needed from the class instance if it's set rather that sending another API request every time.
If this is possible, I would be more than happy to listen and learn!
The request life cycle (using mod_php, fastcgi/fpm) usually prevent sharing resources. Unlike languages running on application servers, PHP has no built-in way of sharing object instances.
For each incoming request, the web server creates a "new" instance of the php runtime, executes the request and clean itself up.
You could use APC to serialize object instances or memcache to temporarily store results between requests.
I'm building a webapp in MySQL/PHP/Javascript.
In PHP, I've got all the classes from the domain od the problem which persist in the database.
In Javascript, there is a cache with objects from the last queries.
When an object in Javascript is updated by the user, it has to update itself in server-side. Which would be the best way to do this?
Should I create a class in PHP and Javascript for communication purposes? Should each object in Javascript send an AJAX query to a different php file depending on the class of the object it needs to update?
Are there any patterns to follow to solve this?
Creating a separate PHP file for each class would certainly be more maintainable if this is a project of any size at all. It would also allow you to do things like have different server-level authentication based on the classes.
On the JavaScript side, you definitely want some sort of AJAX library, whether you throw it together yourself (I did one once in about 50 lines of JavaScript) or use one of the ones out there. You may need a helper function or two that knows how to serialize the data (XML, JSON, delimited, whatever).
You can write object oriented code in JavaScript, and if you're doing that already, it makes sense to add a write() or updateServer() method to call the AJAX library with the right parameters for consistency. If you're not writing OO code, it still may make sense to have separate functions, but only if there's more than one place you need to persist these objects from.
Most AJAX frameworks (jQuery etc) will send an 'HTTP_X_REQUESTED_WITH' header set to 'xmlhttprequest'. I like to use this to decide which view to use.
This means the same url can be used to retrieve JSON, XML, or HTML snippet via JavaScript or to return a full document if a standard GET / POST request is made.
This means your app will simply revert to normal requests should the user have JS disabled.
I think you should have a look into the RESTful API with PHP and JavaScript. You address your domain model objects as unique resources (e.g. /application/books/1). If you only want to implement CRUD functionality a generic Controller that updates the corresponding domain model (e.g using an ORM tool like Doctrine) should be sufficient.
If you really want to have the same model on the client side in JavaScript depends on your Application. I like the idea of just managing a single JavaScript object on the client side which will be loaded via REST and then populated to HTML Forms and send back e.g. as JSON (or as a simple form submit) to the server. If the client side model idea appeals to you, I recommend to have a look at JavaScript MVC which has a quite interesting model implementation.
I have a web-app-database 3 tier server setup. Web requests data from app, and app gets its data from the db then processes and returns it to web for display. Standard.
Currently all the data I serialize from app to web gets put into custom defined data structs that the web side then parses for display. In other words, say I have an order that I want to retrieve and send to web. I don't serialize the whole object, but rather build an array with the appropriate data elements while on the app server, then serialize that array over to the web servers.
Now, I am looking into serializing the entire order object over to the web server.
What is the best method you guys have found to serialize objects while maintaining separation of appserver and webserver code? I don't want my webservers having any code which accesses the DB, but I want them to reuse the classes that encapsulate my order and other data as much as possible.
To further refine my question (thanks to Glenn's response), I don't want my webservers to have any of the business logic around say the order class either, that only the appserver needs to know. The objects already use separate serialization to/from the database, and to/from the webservers.
Using the order example, on the appserver, an order should be able to cancel: ie
$order->cancel();
but on the webserver that method should not even be found. It shouldn't simply proxy back (directly) to the appserver order's cancel method, because user action requests should flow through the application's authorization and permissions checking layer.
So how do I get an order object on my webserver that has some (but not all) of the methods and properties of the object on my appserver, with little to no code duplication. One thing I've been thinking is to create a base class with a limited set of properties and methods. It would use an inner class to hold its properties, and I would require all data access to pass in and out of getters and setters. These would in turn call the getters and setters on the inner class.
The web and app servers could then independently extend the base class, and use a custom inner class to hold the properties. Then on the app side for instance, the inner class could be an ORM class extention that can persist data to the DB, and on the web side the inner class could be a simple properties holder class.
But the whole inner class thing seems a little clunky, so I'm still looking for better solutions.
Factor out format specific
serialization code into separate
classes using the Adapter
pattern. Your problem domain
classes become backing store
neutral.
Use relational database specific adapter classes on the app tier to serialize objects to and from the data tier.
Use HTML specific adapter classes on the web tier to serialize objects to and from the web browser.
Use XML (or whatever wire protocol friendly format you deem most appropriate) specific adapter classes on both the web and app tiers to serialize the objects between the web tier and the app tier.
You get extra points if you are clever enough to figure out how to make these adapter classes generic enough such that you don't need a different set of adapter classes per problem domain class.
If I understand your question correctly, you want to serialize the data of your objects, but when they are re-hydrated, they should be so into a different type of object (With limited and/or different functionality)?
You can do this in different ways, depending on what protocol you prefer. For example, you could use SOAP. You should then hydrate the objects into a different class on the client-side, than on the server-side. You could also use PHP's native serialization and either a) Have a different code base on the client (Could get confusing) or b) mock a bit around with the serialized string (Eg. replace the class-name). A crude example can be found in the comments for the PHP manual.