We’ve got a lot of classes following this general command pattern:
class SomeCommand import ['subcommand_a', 'subcommand_b'] def call(args) dependency_a.(...) # ... processing specific to this command ... dependency_b.(...) # ... end end
There are a lot of things I like about this pattern. It’s easy to test with dependency injection, I can re-use the subcommands elsewhere cleanly, and because there’s no per-call state in the object, dry-system can (could?) memoise and re-use it.
subcommand_b will both call the same expensive operation (e.g. a remote API request). Ideally I’d like to run this once, and use the result in both places.
I could add an argument, like so:
def call(id, args) cached = expensive_operation(id) dependency_a.(..., cached) # ... dependency_b.(..., cached) # ... end
But if there’s a lot of existing arguments, this gets quite verbose. It also breaks abstraction: if A calls B, B calls C, and C’s implementation changes to need
expensive_operation, all of them need extra parameters.
I’ve also considered a full-fledged cache in the
expensive_operation code, but that raises the spectre of cache expiry. Right now I only keep the expensive data for one call so I haven’t had to worry about that.
How have other people handled this situation? Is there some principle or tool I’m missing that would help?