-
Notifications
You must be signed in to change notification settings - Fork 5
Conversation
Thanks for the elaborate description of your problem. Several things come to mind:
I hope this helps! |
I agree, although I would like my domain logic to be completely decoupled as opposed to the loose coupling you talk about. I think overall this is my solution though, to move my commands and handlers outside of my domain in to some kind of command handling layer, or ports layer as I've heard it described elsewhere.
Yeah I didn't really expect it to get merged, just wanted to open up the conversation :)
Yeah I was uncomfortable with it too. In just seemed odd injecting a handler into a handler. Cheers for the response, as mentioned I think my solution is to have a dedicated command handling layer which is only loosely coupled to this command bus. |
Thanks. This would have been a nice case for "duck-typing", where having a handle method is quite enough to be considered a command handler and having a name() method is sufficient to be considered a command :). Okay, if you stumble upon any other issue, just let me know! |
Just for reference - my problem here is more or less the same as this Stack Overflow question: http://stackoverflow.com/questions/26699118/hexagonal-architecture-clean-code-problems-implementing-adaptor-pattern |
@jenkoian Thanks for pointing this out. About adapters: they are not meant to implement both interfaces, they are merely meant to bridge the gap between one interface and another. So, in the case of the console output, I still think that you wouldn't need to go as far as you are doing now. The idea of hexagonal architecture (which this library is meant to support), is that you separate adapter code from core code, or technical details of the input and output of your application from your domain code. It's not bad if you use third-party code in the core of your application - you can not write everything yourself. It is however important to make your core point inwards with regard to external system, like a database, or a web browser. It should not be aware of any of those. |
@matthiasnoback thanks for the reply :)
Unless I'm mis-understanding, I'm not sure I agree here. Doesn't it make more sense to depend on your own interface and adapt to the third party interface (in this case This seems right to me. You want to rely on your own interface and use adapters to 'adapt' outside interfaces to fit. I'm not sure I see the need to create an adapter in the other direction, i.e. EDIT: Having spoken to some colleagues I think I was mis-understanding you here and now see what you mean and can see how that can solve the issue. When I get time today I'm going to put a gist together to clarify it in my own head, but thanks for the hint.
I think this depends on how seriously you are taking the dependency rule and also if you care about loose coupling vs de-coupling |
This is the case, right? In the example the dialog helper explicitly needs such an instance. So then you just have to wrap it again (only problem is the amount of methods that you won't be able to support). The Dependency rule is interesting, but I'm not sure if the dependency on interfaces of SimpleBus is really in the wrong direction. As I said, you still apply to the Dependency inversion principle by depending on an interface which models a very abstract concept as well. Also, code from a library isn't necessarily part of an outer ring. If you recreate the code in your own project, then it will be in the same ring and you would still not be allowed to depend on it. This would lead to the conclusion that it's no problem to use |
Yeah, as mentioned int he edit I think I was mis-understanding initially. This makes sense. In fact I've been talking to Chris (author of the SO post) and we've come up with something like https://gist.github.com/chriscollinsboxuk/c5aa552cdfa8bb55c870 which I think is the point you were trying to make. Still digesting your second point, but thanks for your input with all this, appreciate you taking the time on essentially a non issue :) |
Exactly, that was what I meant :) Thanks to you too. I think it's important to explain/defend certain design choices. If I can't do that, then I should try harder/rethink things. And that actually happens a lot, so I always try to follow the reasoning of people commenting to find out if there is a new concept/solution hidden behind their questions. |
Hear me out..
I'm working on an example hexagonal app using commands and handlers. I wanted to introduce a command bus into the equation and liked the look of this.
One of the big concepts I want to put across in the application is the dependency rule and ensuring that we're only depending on inner dependencies.
So I'm creating adapters for any outer dependency. Therefore to use this library, I have something that looks like the following:
Example Command:
Notice it's extending the adapter, which looks like this:
Pretty straight forward so far. So then I wanted to do a similar thing with handlers:
Example Handler:
The Adapter:
Now obviously this doesn't work because of the type hint for
Command
. AsSimpleBus\Command\Handler\CommandHandler
is expecting aSimpleBus\Command\Command
instance, I must type hint for that in my handlers. Thus, coupling my handlers to theSimpleBus\Command\Handler\CommandHandler
. Type hinting to my adapter doesn't work unfortunately, as the method signature must match exactly of the interface.I'm unsure if the commands and handlers should be part of my domain or if they are deemed part of the infrastructure (where I care less about decoupling so much).
So, sorry for the long PR, but I guess it's kind of an RFC with the following questions:
I tried to look at what similar libraries do, but didn't come to any conclusion really. Broadway doesn't require a type hint (https://github.com/qandidate-labs/broadway/blob/master/src/Broadway/CommandHandling/CommandHandlerInterface.php) nor does (https://github.com/tabbi89/CommanderBundle/blob/master/Command/CommandHandlerInterface.php) but then other similar libs do so ¯_(ツ)_/¯