Hacker News new | ask | show | jobs
by karmajunkie 3551 days ago
> Imagine tooling that allowed an event stream to be used to create state for testing modules, crudlike helpers to allow crud-familiar developers to think that way at first, and workflows based on snapshots, rewind, etc.

i know where you're going with this, and i honestly believe its a terrible idea (not to be discouraging or rude—just experienced.)

if your event streams contain mostly CRUD (possibly ANY) then you're most likely applying it incorrectly. Its not just a version history of your data. The event type itself is data, which provides context and semantics over and above the notion of writes and deletes. If you're falling back to crud events all you're doing is creating a lot more work for yourself and deriving almost no benefit from the use of ES—in that case, you should just use CRUD and the ORM of your choice.

3 comments

> if your event streams contain mostly CRUD (possibly ANY) then you're most likely applying it incorrectly. Its not just a version history of your data. The event type itself is data, which provides context and semantics over and above the notion of writes and deletes.

Right. A good way to think about this is that as with rows in an RDBMS, events in an ES system are facts, and just as tables in an RDBMS define a category of facts with a particular shape, event-types in ES do the same thing. The difference is that whereas in an RDBMS the facts represented by rows can be general (and are often, in many designs, facts about the current state of the world), events are facts about a specific occurrence in the world rather than the state of the world (and the "state of the world" is an aggregate function of the collection of events.)

Right^2: Good events are facts that occur at a higher level of abstraction, trying to capture more of the "why" behind what goes on. It's not about describing the effect on data, but the business-decision itself. (Which, when reapplied to a set of rules, will do the actual data-change.)
> A good way to think about this is that as with rows in an RDBMS, events in an ES system are facts, and just as tables in an RDBMS define a category of facts with a particular shape, event-types in ES do the same thing.

Thank you for this, it has cleared many of my troubles with understanding event sourcing completely.

> if your event streams contain mostly CRUD (possibly ANY) then you're most likely applying it incorrectly. Its not just a version history of your data.

Thanks for that. I'd made that mistake: I have a system which now needs to become distributed (a copy of it goes offline for a couple of weeks, and has to merge back into the main datastore) and keep a history of changes. It's currently CRUD backed by MySQL, and I'd latched onto event sourcing as what I'd need.

> The event type itself is data, which provides context and semantics over and above the notion of writes and deletes.

OK, going to have to get my head around that :)

See the presentation by Greg Young I linked to in another comment. One thing he talks about towards the end is the application for occasionally connected clients, which is one I'm looking to tackle myself in the next several months. ES may very well serve your needs, but I'd take a step back from the CRUD model and really think about the domain model. Something I do a lot of times when I'm looking at moving away from CRUD in an app is creating a bunch of domain-based command classes, which take over the persistence job, and move the app layer towards talking only to those commands. Still CRUD under the covers, but now there's an abstraction layer above it, and as you get a better delineation of boundaries you start to see where the services will fall out of it and what areas might benefit from ES the most.

[1]https://www.youtube.com/watch?v=LDW0QWie21s

There's nothing wrong with having a system that uses immutable events to represent data, IMO it's mainly a terminology issue: "Event Sourcing" often implies you're recording rather abstract, high-level events that try to capture something about a particular domain. As opposed to, say, a straight diff between two data-dumps.
I was thinking of making CRUD a specific event type that had meaning only in the context of changes to an instance of some schema. Of course, the most interesting events will not be CRUD oriented, but does this mean it's a mistake to include them at all, particularly if interacting with other systems that do use a CRUD metaphor for interaction and state must be synchronized?
I don't know if I'd be strong enough in my words to call it a "mistake" (there are few absolutes) but its a big stinky code smell, and it likely falls into that bucket of things you're going to regret one day sooner than you realize.

The thing is, DDD isn't easy. You're going to end up with someone on your team at some point that's inexperienced with it, and having a bunch of CRUD events in the schema already is going to entice them to add a few more because its easy and they're already there and oh hey what's a few more amongst friends?

Something else I've learned about this stuff is that because it works best in stable domains, it is also going to work best in domain services that have low code churn. Once you get it right, it tends to stay that way. But if you try to model with non-domain events, you're dramatically increasing the surface area that is subject to churn.

YMMV but I wouldn't do it.

> particularly if interacting with other systems that do use a CRUD metaphor for interaction and state must be synchronized?

This is also an antipattern, btw—events between bounded contexts should be somewhat limited, and well-defined behaviors when doing so. What you're doing with a scheme like that, sharing CRUD events between external services or systems, breaks all kinds of conceptual and logical encapsulation (in addition to the aforementioned CRUD thing.)

Why is it an antipattern? What does it make more difficult?

Pattern matching? Creating useful state snapshots? Curious to hear more about your experience.