How would one apply command query separation (CQS), when result data is needed from a command?

后端 未结 10 1983
慢半拍i
慢半拍i 2021-01-30 06:25

In wikipedia\'s definition of command query separation, it is stated that

More formally, methods should return a value only if they are referentially t

10条回答
  •  被撕碎了的回忆
    2021-01-30 07:09

    Oh that's interesting. Probably I have something to say, too.

    During recent time I've been using non-orthodox CQS (maybe not CQS at all for somebody, but I don't really care) approach which helps to avoid messy Repository (because who uses the specification pattern, huh?) implementations and Service layer classes which grow up absolutely enormously over time, especially in huge projects. The problem is it happens even if everything else is fine and developers are pretty skilled, because (surprise) if you have a big class it doesn't always mean it violates SRP in the first place. And the common approach I see in such projects very often is "Oh, we've got huge classes, let's divide them", and that division is mostly synthetic rather than evolving naturally. So, what do people do to cope with this? They make several classes out of one. But what happens with DI in a huge project when you suddenly have several times more classes than before? Not really nice picture since DI is probably already pretty loaded with injections. So there come workarounds as facade pattern etc. (when applicable), and the implications are that we: don't prevent the problem; deal with consequences only and spend much time for it; often use "synthetic" approach to refactoring; get less evil instead of more evil, but still that's evil.

    What do we do instead? We apply KISS and YAGNI to CQS as a first step.

    1. Use Commands/CommandHandlers and Queries/QueryHandlers.
    2. Use generic return object for both queries and commands which contains result and error (ouch!).
    3. Avoid standard service and repository implementations by default - only if it's strictly necessary.

    What problems are solved with this approach?

    1. Early prevention of code mess, much easier to work with and scale (future proof).
    2. Believe it or not, for medium size project we had neither service classes nor repositories at all. The bigger the project, the more beneficial such approach is (if we assume that CQRS and ES aren't needed and compare only to standard service + data layers). And we're extremely happy with it since it's more than enough for most medium-sized projects in terms of costs and efficiency.

    So what would I suggest you to do?

    1. Use right tool for the right job. Use the approach which solves your problems and avoid doing everything by the book if it comes with unnecessary complexity for your case "just because that's why". How often do you see fully RESTful Level 3 APIs, by the way?..
    2. Don't use anything if you don't need it and especially if you don't understand it since if you really don't, it will do more harm than good. CQRS is good for some cases and is still pretty easy to understand, but comes at a price of development and support; ES is rather difficult to understand and even more difficult to build and support.

提交回复
热议问题