mhinze / ShortBus

In-process mediator with low-friction API
MIT License
210 stars 41 forks source link

IEventHandler #19

Open zachariahyoung opened 10 years ago

zachariahyoung commented 10 years ago

Should we include a marker for event handlers?

mhinze commented 10 years ago

I'm not going to advance this, but I won't discourage events in ShortBus. I think it is a common application abstraction that needs to be serviced in many apps. (along with Tasks) That being said, I haven't made it there yet with ShortBus, so I'm not going to push out uninformed functionality. You are welcome to submit a PR or even a more detailed issue with examples, use cases, etc.

jkodroff commented 10 years ago

Turns out I wrote something on my own a while ago very similar to ShortBus, so I could add the implementation pretty easily if @mhinze would like to assign this to me. I've been using it production for years and it's worked great. It really helps keep command handlers focused and promote business logic reuse.

Basically, you add IEvent to event classes (e.g. OrderSubmitted), add IEventHandler, and a Publish(params IEvent[]) method to complement Send().

Assign to me and I should be able to bang it out quickly.

mhinze commented 10 years ago

Besides params arguments, what is the difference between Publish and Send? They both look up a handler and invoke that handler. Is there more to it? Does Publish support multiple handlers for same event? (That would be like the "old" ShortBus Send)

Events, commands, queries.. these are semantic differences. I would like ShortBus to implement mediation and leave semantics to the client.

jkodroff commented 10 years ago

I think there's meaningful semantic difference. Here's my understanding (which comes mostly from using NServiceBus):

Commands (ShortBus and NSB look to be identical here):

Events:

Both IEvent and ICommand inherit from IMessage in NSB and Request/Response messages (which is what queries are) are simply IMessage in NSB. I like your model better for queries as I think it's more clear.

Let me know what you think. Hope this helps.

mhinze commented 10 years ago

I agree that there is a meaningful semantic difference. What I'm saying is that the semantics belong to the consuming application, mediation belongs to shortbus. So if we need a new mediation pattern, such as bringing back the "old send", I'm in favor of it.

In that case we would have two mediation patterns:

  1. Request/response (useful for things like HTTP GETs, HTTP POSTS, Queries, Commands)
    • one handler per message type
    • result is valuable or UnitType
  2. Notification (events)
    • many handlers per message type
    • result is void
zachariahyoung commented 10 years ago

The consuming application would need to use the mediation pattern to match an event to it's event handlers. I had started looking at MassTransit as an example of a consuming application framework. If a framework like MassTransit already has a way to do the mediation then ShortBus may not be require. But if someone has written a simple windows service to process message there could be some value in this case.

My thinking is that a command handler would create events for other sub-systems to be notified of changes. These sub-systems would handle these event by defining event handlers and ShortBus would be used to determine the correct event handlers.

Is this the correct thinking?

mhinze commented 10 years ago

I think where you are getting hung up is that ShortBus is for in-process, in-application mediation and NSB and MassTransit are for distributed messaging between applications.

On Tue, Jan 14, 2014 at 9:51 AM, Zachariah Young notifications@github.comwrote:

The consuming application would need to use the mediation pattern to match an event to it's event handlers. I had started looking at MassTransit as an example of a consuming application framework. If a framework like MassTransit already has a way to do the mediation then ShortBus may not be require. But if someone has writing a simple windows service to process message there could be some value in this case.

My thinking is that a command handler would create events for other sub-systems to be notified of changes. These sub-systems would handle these event by defining event handlers and ShortBus would be used to determine the correct event handlers.

Is this the correct thinking?

— Reply to this email directly or view it on GitHubhttps://github.com/mhinze/ShortBus/issues/19#issuecomment-32276281 .

zachariahyoung commented 10 years ago

So as soon as I starting thinking about putting the message on a queue it's not in-process or in-application?

mhinze commented 10 years ago

Correct.

On Tue, Jan 14, 2014 at 10:47 AM, Zachariah Young notifications@github.comwrote:

So as soon as I starting thinking about putting the message on a queue it's not in-process or in-application?

— Reply to this email directly or view it on GitHubhttps://github.com/mhinze/ShortBus/issues/19#issuecomment-32282344 .

jkodroff commented 10 years ago

So it sounds like all that would be needed is Publish(), which expects 0 to many handlers, and IEvent. (It's never appropriate to publish a command or query.) Does that sound right?

mhinze commented 10 years ago

Please review the referenced PR..

Depending on client consumption patterns Commands could use either Request or Notification (for example, in my API, commands have a result (HTTP 201 w/ Location header, but in previous applications I would have used the Notification method) Events would be Notifications Queries would be Requests

The goal here is to take ShortBus out of the CQRS lingo and be a general purpose mediator. While I think ShortBus is useful in CQRS-participating applications, it's not a plug and play CQRS framework.

jkodroff commented 10 years ago

That looks pretty good to me.

On another note, what do you return as an HTTP status code for a command that does a Delete? Seems like a 201 (Created) wouldn't be appropriate in that case.

mhinze commented 10 years ago

If successful, we return a 204.

patroza commented 10 years ago

I've made the Mediator a bit more plain again and then applied the model with Response and Exception handling in Extension methods, I consider this a more clean and flexible approach. https://github.com/mhinze/ShortBus/pull/27