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
@davetron5000 stateless are...objectively better, lack of mutable state gives you simpler reusability and less code paths that can go wrong 🙂
@solnic You are not worried about coupling between "doit" objects and "result" objects? Or the extra effort needed to create structured result classes separate from the "doit" class?
@davetron5000 oh and I don't create result classes, I just use plain data or stuff from dry-monads

@solnic How do you capture why an operation could not be completed in order to advise the user of the problem and how to fix it? I find "validations attached to a record" insufficient in a lot of cases.

For example, draft blog post -> validate title, publish blog post -> validate title + body & require approvals, e.g.

@davetron5000 dedicated validation contracts, every use case may have its own contract, validation happens before anything else happens
@solnic But not all checks for “can this be called" can be fit into data validation, right? Often you have to consult external services/data stores to figure out if an operation can be performed and, if not, provide the user an explanation.
@davetron5000 yes I do that in contracts

@solnic It sounds like a "contract" has logic for “can the operation be invoked?” as well as some structured data to describe all possible things that can go wrong, such that the user can be told what went wrong.

And then a separate (stateless) "doit" class to perform the operation, that is coded under the assumption that the contract has been checked first?

Thus, the contract and the "doit" are coupled, despite being separate classes?

[just trying to understand how it would all work]