I wanted to let you guys know about the fun I have been having with DCI, using mbrowne's trait based implementation in PHP. The idea I am persuing is inspired by UncleBob's statement that the Web is essentially an IO device.
Some of you may know that PHP has newish standard set of interfaces for handling HTTP requests and responese, called PSR7, so I defined: an IOContext class -> ContextHTTP, and a specialised subclass PSR7_JSON.
This context is created with a request (the Input) a response (the Output), and a controller. The controller is a role player within the IOContext. When the controller arrives in the context it is informed, and requests for itself an input_role and an output_role. The controller is then passed into a real business UseCase context.
When an activity in the UseCase sends a data response out via the controller, it calls the method $controller->respond($data) which is implemented in the Output_Role this then calls the IOContext PSR7_JSON context->reply( ).
The result is a three layer interface between the actual IO device and the domain code. Domain code just returns the data, the controller's output Role translates that into general HTTP terms, and the IOContext, maps this into the framework's PSR7 response object, which the Slim PSR7 based framework can then output.
Having used this pattern for a few weeks, I am really pleased with it. My first observation is that as you would expect it can really cleanup the code to have everything in the right place. A specific advantage is that you have complete control over both ends of the framework interface. When you use a typical framework, or class library, you are stuck with the interface that you are given. In this case, the context provides a place to map onto their interface according to your liking, and the role provides a place to define the interface that is appropriate for the domain.
In other words, your domain level code in the UseCase can remain stable, because the controller Output-Role interface can remain stable, while all of the specifics of dealing with a particular IO framework are handled by the IOContext, and Output-Role implementation code, all defined within a single file, in this case the PSR7_JSON IOContext.
Having seen a trace of the PSR7 request/response process in action it really doesnt look very efficient to me. It is somewhat hampered by the fact that the spec insists on these objects being immutable, and this new wave of PHP framework developers are a pretty perfectionist lot, as compared to the old days. With this architecture I could very easily switch out the new fangled PSR7Request and swap back in the old-school $_REQUEST, and all would be well, and fast(er).
Secondly as you would expect the IOContext provides the perfect place to mock up IO for testing, without needing to use a full HTTPClient like Guzzle. I have my own implementation of a mock Guzzle, called Guzzleless, and this works really well.
I am also looking forward to be able to swap out the PSR7_JSON IOContext for something more wizzy, like a Redis or Hadera communication protocol. Finally "the web really is a plugin".
As you can imagine, PHP isnt really designed for dynamic traits, and so this probably isnt the most efficient way of doing things. However I do think that it is the best way for "thinking about things" that I have come across, and the result is layered quite elegantly. It also occured to me that the DCI implementation of an IOContext like my PSR7_JSON can be optimised and provided as a single statically bound trait for the controller. Since it is unlikely that you would need multiple IOContexts in a single application, especially with the way that PHP works, starting afresh on each request.
The optimised version would simply turn the DCI version outside in, putting the input and output as instance variables encapsulated within the optimised trait. It think that this is worth mentioning in presentations, that in a simple interfacing situation like this DCI turns encapsualtion inside out, but there is nothing stopping you turning that back to outside in (in theory).
In conclusion I have also defined a DBContext, which is also looking good. The context handles the SQL, the Role handles mapping data into useful objects, and the UseCase just makes simple requests. This is also looking good for the plugin treatment.
So, I am thinking that DCI, while interesting as a scalable business level architecture, it also has the potential to solve much more basic interfacing problems in an elegant way. This being so, it might motivate language developers to provide more efficient mechanisms for dynamic behahiour modification in the future.