Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IEventHandler #19

Open
zachariahyoung opened this issue Jan 9, 2014 · 14 comments
Open

IEventHandler #19

zachariahyoung opened this issue Jan 9, 2014 · 14 comments

Comments

@zachariahyoung
Copy link

Should we include a marker for event handlers?

@mhinze
Copy link
Owner

mhinze commented Jan 9, 2014

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
Copy link

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
Copy link
Owner

mhinze commented Jan 13, 2014

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
Copy link

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):

  • A command tells the system to do something.
  • Commands are indicated by the marker interface ICommand
  • Commands are named something like SubmitOrder
  • A command has exactly one handler, and it is send on the bus via Send()
  • An exception is thrown if a command has more a number of handlers != 1.
  • Command handlers are best tested via what events are published on the bus, not by any state changes. This keeps your tests from changing as often as you're testing behavior (messages) rather than internal state.

Events:

  • An event is something that has happened in the system
  • Events are indicated by the marker interface IEvent
  • Events are named something like OrderSubmitted
  • An event has 0 to many handlers, and is published on the bus via Publish()
  • In the project I work on, event handlers issue commands and never change state directly. They are tested via the commands they issue (again, aiming to test behavior rather than state). Not entirely sure this is the optimal way to do it, but it works pretty well in my experience.

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
Copy link
Owner

mhinze commented Jan 14, 2014

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
Copy link
Author

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
Copy link
Owner

mhinze commented Jan 14, 2014

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
[email protected]:

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//issues/19#issuecomment-32276281
.

@zachariahyoung
Copy link
Author

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

@mhinze
Copy link
Owner

mhinze commented Jan 14, 2014

Correct.

On Tue, Jan 14, 2014 at 10:47 AM, Zachariah Young
[email protected]:

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//issues/19#issuecomment-32282344
.

@jkodroff
Copy link

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
Copy link
Owner

mhinze commented Jan 16, 2014

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
Copy link

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
Copy link
Owner

mhinze commented Jan 17, 2014

If successful, we return a 204.

@patroza
Copy link

patroza commented Mar 29, 2014

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.
#27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants