Two OO ways to design something, curious what everyone's thoughts are? This is w/out context of a framework, just purely OO perspective.

Option 1 - Stateless object w/ Rich Result

Option 2 - Stateful object (e.g. command pattern + internal state to store results)

https://gist.github.com/davetron5000/19aa850df641be6c334e9b64a944b6c8

My thoughts follow, but I am not sure which is the "best" pattern - again all things being equal/not in Rails/etc.

stateful.rb

GitHub Gist: instantly share code, notes, and snippets.

Gist

Stateless code seems easier to test and operate, since it's basically just a function. Certainly, it can affect the world around it (e.g. in a database), but it's a long-lived object that performs a function, and this is pretty simple.

The downside is that the results of the action require a separate object to describe, requiring either an inner class to help manage or coupling between two classes.

This can also lead to architecture astronautics if you try to generalize the result class.

Stateful, on the other hand, keeps all concepts together: the operation and its possible results are all in one class, which feels cohesive and easier to manage/evolve the code.

The downside is that the object, once invoked, cannot/should not be invoked again. Thus, you'd probably need some safeguards to help avoid that.

The stateful approach also could be awkward if you wanted multiple "doit" methods. You then get a convoluted object with lots of optional values for results.

The "lazy mode" of these approaches is woerth considering:

lazy devs applying the stateless approach will use boolean return value, which suck

lazy devs using the stateful approach will overload existing objects with more methods.

I believe that the way in which a design decision plays out under stress is important.

@davetron5000 I seldom think about this? My go-to (heh) is generally something like:

def self.call(**kwargs)
new(**kwargs).call
end

and then #call can return whatever it likes

@geeksam That's a lot of code to avoid calling new - unless I'm missing something?

But the question is more "what should call return?” and "should the class have internal state that is inspected to understand what call did”

@davetron5000 I usually deploy that pattern for things that need to act like a "static function" on the outside but that have complex/stateful internals. (Feel free to read this as "I spam Extract/Inline Method and change my mind a lot", lol)
@davetron5000 actually, that is kind of an answer to your question: I will go to at least some lengths to avoid having to reset state on an object, preferring instead to throw the whole thing away and construct a new one.
@geeksam @davetron5000 so much nicer with 3.1 arg forwarding too!