7

Among other things, the CQRS has a rule that each of the methods has one responsibility. So we can't have this in the model:

public class Store {
    public Item getOrCreateItem(int id)
    {
        //logic
    }
     //....
}

and this in the controller:

Store store = new Store();
Item item = store.getItem(1);

We must have this in the model:

public class Store {
    public Item createItem()
    {
        //logic
    }
    public Item getItem(int id)
    {
        //logic
    }
     //....
}

which leads to this in the controller:

Store store = new Store();
Item item = store.getItem(1);
if (item !== null) {
    Item item = store.createItem();
}

But now we have a lot of code in the controller...

Is there any better way to seperate the methods than to have the extra code in the controller, which should contain little code?

20

Oh for crying out loud.

The controller has no business knowing what your implementation of getThingy() has behind it. Whether getThingy() creates or passes out a cached copy is none of it's business. The only reason this implementation detail leaked out of the store and into the controller was because you didn't trust the store to just "somehow" get you a thingy. Once you start thinking you know "how", from outside, suddenly you're trapped doing what's expected. That's not abstraction.

If you're thinking "but getters aren't supposed to be factories" then fine. Name it thingy().

If you're thinking "but I have other things that need to get thingy different ways" then fine. Name it controllersThingy().

If all I ask for is a thingy then just give me my thingy. I don't care how. Stop telling me how.

  • In other words, @losasafo, what CandiedOrange is saying is that your controller is using both Store.createItem and Store.getItem to get your item. Your controller is using both of them for the same exact purpose. In this case, yeah, it should be able to just call Store.getItem, and the model can create the item first if it needs to. It's still getting the item either way. If you really do have a separate need for your model to explicitly create the item, at which point your model is doing something really different with item creation, that's a different situation. – Panzercrisis Feb 23 '18 at 16:31
  • Something similar to the example in your question is "upserting": That's when you try to save something to a database or whatever, and you don't particularly care if it's already in there or not; you just want its current state to be saved either way. So you pass in the information to save from one layer or client, and the server or other layer will save it. To save it, it will create it brand new if necessary, or if there's already an old record of it in there, it will just update it instead. Either way, you don't care, so you "upsert" it. – Panzercrisis Feb 23 '18 at 16:50
  • 1
    @panzercrisis Hehe, yes upsert is a good example of abstracting away details you don't care about. – candied_orange Feb 23 '18 at 17:26
2

Typically, one would have a Service which would provide this sort of functionality. The Controller would call something like StoreService.EnsureItemExists(1).

The model should probably not do much either - most of the business logic should reside in the service.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.