-1

I've heard it said that you should keep query and modifier functions separate from one another, and I agree with the sentiment. When trying to apply it, I often run into two issues/questions:

  • What, if anything, should a modifier return? Should it not return an indicator of success/failure? Should it instead return nothing, but throw an exception upon failure?

  • Should constructors be treated as modifiers (is the creation of an object a side-effect)? I suspect not, since a constructor that created an object but didn't return a reference to it would be pretty annoying.

closed as too broad by Ixrec, GlenH7, Scant Roger, Matthieu M., user40980 Dec 23 '15 at 1:54

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    These questions are too broad to answer in their most general form with anything more useful than "sometimes" or "it depends". Could you provide a specific example of a class where you're not sure what return values the modifiers/constructors should have? If you do that then we can probably help you. – Ixrec Dec 21 '15 at 15:16
1

Actually answer to this is pretty simple, but not short.

What, if anything, should a modifier return? Should it not return an indicator of success/failure? Should it instead return nothing, but throw an exception upon failure?

First you have to ask yourself why you should not return anything from command (modifier). What we gain by that?

There is actually one advantage worth it - we can run that command asynchronously in a background, i.e. put command that creates new post to command queue, that is handled by other process, maybe written in another language. By that you can just put command to queue and return http response immediately not waiting for post creation to happen, big performance gain, right?

Don't mistake returning value from command and returning http response. You must do the latter to inform client that putting command to queue was successful or not, but only that. Raising exception from command is the same as returning value, so you cannot do that.

Now is the question, how to return id of the newly created post to client, because we want to let user edit that post immediately.

So, commands doesn't have return value, ok. But they have result, an effect. In example if call turnLightOn command it doesn't return true or false to indicate that it worked - it's silly, but we can see with our own eyes that lights are on and we can see at night. That is an effect of command. How do we represent effect in programming? By events of course. Command that turned lights on, also publishes event LightsTurnedOn (past time) and client is subscribed to that event.

Going back to our post creation example:

  • client sends request to http server that he wants to create post with title 'Super post'
  • server receives that request and put it into command bus (queue) and returns HTTP response with code 200
  • process that is handling commands collects our newly put command whenever it is able to (has free workers), do what is have to do - creates post and publish event PostCreated(userId, postId)
  • client has to somehow subscribe for that event, and there are several ways:

    • query event service from time to time, to check if new event is published for us using AJAX (worst option),
    • connect to websocket server and wait for event there,
    • connect to Server Sent Events(SSE) server and wait for event (the best option)
  • event service is subcribed to event PostCreated so it knows when to forward that event to client via choosen protocol, i.e. SSE,
  • client receives event that his post was created and he can do whatever he wants with that

Profit.

Should constructors be treated as modifiers (is the creation of an object a side-effect)? I suspect not, since a constructor that created an object but didn't return a reference to it would be pretty annoying.

Side effect is everything that is not referential transparent.

It means that if your constructor does nothing else, but only returns reference to newly created object, then there is no side effect. But if that constructor uses global values (get or set, doesn't matter) to create that object, then it's not referential transparent and it has side effect. Why?

import config

class Foo:
    self.bar = config.BAZ

foo1 = Foo()
config.BAZ = 'something different'
foo2 = Foo()

foo1 != foo2
1

What, if anything, should a modifier return? Should it not return an indicator of success/failure? Should it instead return nothing, but throw an exception upon failure?

You will usually see void returned when an object is expected to modify its own state. Idiomatically, this is somewhat useful -- the return value tells the developer to expect side effects in the operation.

Throwing an exception is the generally accepted practice for reporting the "failure" condition.

In event-sourced CQRS, you will sometimes see this alternative: that command methods return a (possibly empty) list of events that describe the changes in state that were made by the object in response to the command.

Should constructors be treated as modifiers (is the creation of an object a side-effect)? I suspect not, since a constructor that created an object but didn't return a reference to it would be pretty annoying.

Constructors are weird. In many cases, the constructor call can be replaced with a call to a factory -- this doesn't really answer the question by itself, but if you can persuade yourself that the two choices should at least share the same answer, it offers some constraints.

Clearly the creation of the new object is a side effect, if the object can be thought to create itself. But the factory doesn't necessarily change just because you have queried it for a new object.

Alternatively, you can think of each modification of an object as a change from the current state to the new state. If you consider the constructor to be establishing the first state, then it isn't a transition between states, and shouldn't be considered a modification. On the other hand, if you imaging all objects starting from the same "seed" state, then the constructor is the modification that takes an instance from the seed state to its first unique state.

Go not to the elves for counsel, for they will answer both no and yes.

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