Live data from Hacker News

Show HN: Learn what DDD, CQRS, and event-sourcing are all about

docs.wolkenkit.io

61–70 of 86 posts

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#61
post #42

Earlier quoted context omitted.

Starting from fresh these days I would use something 2 way for commands, queries like HTTP REST. But a messaging system for events. If i'm using event sourcing use a dedicated event sourcing database with catchup subscriptions etc

> a dedicated event sourcing database with catchup subscriptions etc Can you recommend any?

We're rolling our own: https://github.com/Lokad/AzureEventStore

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#62

The DDD/CQRS/ES topic appears on Hacker News every so often, and never fails to stir a strong debate. In fact, I was going to "Show HN" an Event Sourcing library I open sourced yesterday, but I guess I'll wait until everything dies down a bit :-) I believe that the core principles of DDD/CQRS/ES are flawed and are the cause of a lot of pain. If your team plows forward and ignores the pain, you will have a bad experie…

hi - could you explain the implementation of this "Materialized views for each aggregate are kept in-memory at all times" ? i have been considering a heretical flavor of CQRS/ES as well, where the command returns data.... and i synchronously build the latest state before I return (rather than building through the whole event stream). when you say "materialized views" - do you really mean the current state of an Order…

What we would do is have a single aggregate representing the entire state of a micro-service. For instance, for the "Orders" micro-service, it would contain all orders in the system, with events such as OrderCreated, OrderPaymentReceived, OrderShipped, OrderCancelled, and so on.

Then, we would have a materialized view that would be a single C# immutable object (canonically called `State`) that contains a dictionary of every order, and maybe a few indices (such as "identifiers of orders currently waiting to be shipped out" or "list of orders by customer"). Everything fits in memory, so every query is simply a bit of C# code that traverses the in-memory graph of objectd rooted at the `State`.

A command emits events, which are then applied by the system to create a new `State` from the previous one. Events emitted by other instances of the application are also fetched by the system every so often, and you can request a "force catch-up" to guarantee that the `State` you access takes into account all events appended so far (so that you're certain to see the results of your actions, even if the load balancer bounces you from one instance to another).

Here's what we use: https://github.com/Lokad/AzureEventStore

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#63
post #23

Earlier quoted context omitted.

Well that's the entire problem, you are not the one making the requirements, the solution of the problem does... You can't eat dinner before you have made it. Edit: I would argue that you can't write a system which is open (several domains) and believe that you will have entirely independent events throughout the system and claim that your system will be "bugfree"/correct.

I could be missing something but I feel like you are inventing an impossible scenario. You may not be making the requirements, but the requirements have to be technically feasible. CQRS/DDD give you a lot of flexibility on where to choose your boundaries/aggregate roots and these are designed around the business/requirements. If you can give a valid scenario where this model breaks down but others would succeed I'd b…

Here's an example from the Wolkenkit brochure:

> user.login({ login: 'user', password: 'secret'});

> const isUserLoggedIn = user.isLoggedIn();

If you look at this purely from an API design point of view, this stinks: by forcing the command to return void, the code ends up twisting its design to return the result of the command through an artificial channel (the state of the 'user' object). In the end, we are still interested in "the result of the login attempt", and the easiest way to do this would be a function that returns a value:

> const isUserLoggedIn = user.login({ login: 'user', password: 'secret' });

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#64
post #59

Earlier quoted context omitted.

Ah, well CQRS is only justifiable when you're selling the work if you couple it with the ES, and the more complex it is, the better the sales job and the budget. It's like peanut butter and jelly. My main point in replying to you was that you weren't selling me on whatever brand of CQRS you think you've got. Why? It seems like you're atomizing your business logic into a fine mist, why is that good? And you still have…

Well each command is a use case. Each use case can be tested independently without having setup controllers and their dependencies, or big service layers and their dependencies. Plus I can run the usecases from a console frontend for quick testing without much setup. I don't really do any transforms other than mapping domain objects into the dB or database results into a query result. Why do I need it? Because I prac…

If you're able to reuse (through encapsulation or extension) your domain object types in your commands and queries without transformations, then your pattern sounds sane to me.

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#66
post #59

Earlier quoted context omitted.

Well each command is a use case. Each use case can be tested independently without having setup controllers and their dependencies, or big service layers and their dependencies. Plus I can run the usecases from a console frontend for quick testing without much setup. I don't really do any transforms other than mapping domain objects into the dB or database results into a query result. Why do I need it? Because I prac…

If you're able to reuse (through encapsulation or extension) your domain object types in your commands and queries without transformations, then your pattern sounds sane to me.

The entire point of the Separation in CQRS is to avoid unnecessary coupling between reporting concerns, GUI concerns, and user concerns.

The act of starting an order does not look like an order. Asking for an order cancellation does not look like an order. Using GraphQL to pull an order summary with report-specialized drill down capabilities does not look like an order. These specialized domain objects should be modeled individually. By trying to encapsulate all these facets in a single object what you get is tight coupling, compromises, domain impedance, logical errors, and slow development.

In context: One of the root principles of DDD is that each domain represents its entities as is befitting that domain. Domain entities should be meaningful in their domain and _not_ corrupted by every niggling redigestion of the same facts through tens, or hundreds, of simultaneous conflicting views... Reporting concerns should be first-class citizens when solving reporting, for example.... View concerns and high-load systems often require denormalization, materialization, transformation, and replication that has very little to do with the user of origin while also _destroying_ the premises of traditional ORM driven RMDB interactions.

At scale, under load, while supporting multiple N-tiered applications and their accordant services, unified domain models break down. Aggregate boundaries map these epistemological distinctions.

CQRS on top of that is just good engineering. In the same way modern car-tunnel builders build two separate tunnels for traffic in each direction, CQRS isolates low-frequency user interaction from high-frequency reporting (or vice versa!), allowing independent scaling and direct delivery of features without impossible coordination activities between teams or finding silver-bullet technologies that may or may not exist.

That said: these are Enterprise solutions to Enterprise issues... Scale is the reason they exist. If you aren't looking at a horrible mess around a unified domain model then these solutions might not apply. If you aren't dealing with multiple simultaneous data delivery platforms (mixing SQL server and Oracle and Mongo DB and S3 and DocumentDB and DynamoDB all at once), these solutions may not apply. If you're not balancing multiple teams working on multiple products that have a constant need for harmonic data exchange, these solutions may not apply. If you're not juggling BigData, if you're not dealing with complex business logic, if scaling up an extra ten thousand users isn't something you deal with, if you're not supporting multiple client types, and so on: these solutions may not apply.

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#67

The DDD/CQRS/ES topic appears on Hacker News every so often, and never fails to stir a strong debate. In fact, I was going to "Show HN" an Event Sourcing library I open sourced yesterday, but I guess I'll wait until everything dies down a bit :-) I believe that the core principles of DDD/CQRS/ES are flawed and are the cause of a lot of pain. If your team plows forward and ignores the pain, you will have a bad experie…

> The author himself did a retrospective that covers a few issues: https://abdullin.com/lokad-cqrs-retrospective/

Having read the article: veeeeeery little of what is mentioned is related in any meaningful sense to CQRS...

Horse-before-the-cart framework design is always bad. Encapsulating untested theories in frameworks instead of lifting them from operational designs, always bad. Building frameworks as a learning exercise, bad. Abstracting away data decisions and then trying to provide opinionated answers to storage at the framework level, very bad. Conflating logical system architecture with supplier provided products (ie cloud services), is framework _cancer_.

That is simply not a reasonable starting point to provide value and scalable systems, and the end result was the same as all other similar attempts: an A for effort with a result that was at best 'close, but not quite...'

To be clear: I do not intend this as criticism leveled at the author or the company. The article is great. I very much agree with his analysis though:

> Lokad.CQRS was created with a very short-sighted design approach in mind, a reusable LEGO constructor...These days I'd try to limit the damage I inflict upon the developers and avoid writing any widely reusable frameworks

This is where all the issues lay... Premature framework development causing up-front decisions untethered to practicality based on conjecture and prognostication instead of experience in a challenging domain insufficiently understood by the framework architect.

From a high level perspective: neither CQRS, nor framework development, nor application development were sufficiently groked before being baked into a long-term production commitment. Those are organizational issues, not CQRS issues. In the same vein, coming from such an environment and basing judgment of DDD or CQRS on anything that came from that environment won't hold water.

The architectural problems you're talking about, the core principles you think are flawed, work stunningly well in other places that have not made the same underlying mistakes. CQRS advocates != CQRS experts != framework experts.

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#68
post #43

> In fact, not even credit institutes work with transactions, they too rely on eventually being consistent. Is this really the case? I was always under the impression that everything regarding financial transactions needed to be transactional.

Consistency here is CAP consistency[1], not ACID consistency. In short, if datum d is visible to Alice at time t1, it MUST also be visible to Bob at time t2 > t1.

So financial transactions are transactional, but there's no guarantee that every node has a fully up-to-date state at all times.

[1]: https://en.wikipedia.org/wiki/CAP_theorem

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#69
post #66

Earlier quoted context omitted.

If you're able to reuse (through encapsulation or extension) your domain object types in your commands and queries without transformations, then your pattern sounds sane to me.

The entire point of the Separation in CQRS is to avoid unnecessary coupling between reporting concerns, GUI concerns, and user concerns. The act of starting an order does not look like an order. Asking for an order cancellation does not look like an order. Using GraphQL to pull an order summary with report-specialized drill down capabilities does not look like an order. These specialized domain objects should be mode…

Sounds really complicated, like "usually badly designed and written code" complicated.

GraphQL and Falcor are interesting, and I like the sort of query-as-befits-the-view aspect to working with it. Taking a wait-and-see on those.

Re: Show HN: Learn what DDD, CQRS, and event-sourcing are all about

#70
post #66

Earlier quoted context omitted.

The entire point of the Separation in CQRS is to avoid unnecessary coupling between reporting concerns, GUI concerns, and user concerns. The act of starting an order does not look like an order. Asking for an order cancellation does not look like an order. Using GraphQL to pull an order summary with report-specialized drill down capabilities does not look like an order. These specialized domain objects should be mode…

Sounds really complicated, like "usually badly designed and written code" complicated. GraphQL and Falcor are interesting, and I like the sort of query-as-befits-the-view aspect to working with it. Taking a wait-and-see on those.

Commands are objects that express a command. A query is something that provides a value.

You can code it up in minutes, and most of the code is pure plumbing to connect to datasources. If that sounds complicated to buy independent control over data exchange then you're simply not exposed to the complex multi-layered and distributed applications that demand a structured approach to the issues CQRS handles. Unquestioned and implicit assumptions are great for small potatoes.

Domains should model domains and reflect the mental models of the people who work on, and with, the system. If that is experienced as complicating the only conclusion is that you're working with subject material neither complex nor interesting enough to warrant a considered architectural approach.

For someone who deals with computing (currying, monads, SOLID, etc), you should know that trying to meaningfully translate superficial domain complexity to generalizations of code quality or design quality of any given solution in all domains is laughable.

Post reply on HN