Thanks for a great article!
I love the idea of Result objects, there are nice gems dry-container + dry-transaction + dry-monads that allow you to write service objects as a sequence of steps and run it. The chain of these steps gets aborted once some step returned false-like result. It’s much, much better than controlling your flow using exceptions.
Also your idea of making services to act as functions (`YourService.call(params)`) is an existing thing called “Function object” or “Functional object”, can’t remember for sure :)
Also a quick note: your example with “other_service” is parameterized and has memoization inside. Either make a hash-based memoization (`@hash[param] ||= compute_for_param(param)`) or remove parameter (since it’s a part of the state anyway).
Thanks again for a nice post!