Coding 2021-07-15
I'm not going to try to do anything about it yet, but I've figured out a few things about the prototype task runner file that I was so annoyed about the length of. First off, the length is mostly due to the fact that it has helper functions that I really want in a library instead of the config files.
The bigger realization I had is that the interfaces get a lot simpler if I wrap everything in a generator function. Basically, the template that everything is kind of fitting into is that there are helper functions that return a list of generators and possibly some extra value. If I relax the idea of "returning multiple generators" (which then get evaluated in sequence), then I can rework these helper functions into generators that expect to be yielded from.
This would allow me to do some... somewhat questionable things.
First, background:
Decomposing the various registry modifications into the smallest units of work made it easier to reason about when they should be idempotent. By implementing idempotence at the lowest level, I can bubble it up higher without actually doing anything at any intermediate level. This means, and I have automated tests for this, that playing back the same sequence of modifications, which before was often an error, is now a no-op. So, this means I don't need to worry about "repeating" modifications, as long as the original modifications are executed in order. I mean, from a correctness perspective. From a performance perspective, I am... not quite sure what I'm setting myself up for.
As far as what this allows me to do, this means that, supposing I make a helper class for representing virtual environments, I can turn the helper method to retrieve the path to a binary into a generator that establishes the link to the pip upgrade command that installed the binary.
I'm realizing now that I probably want to have some kind of wrapper around the generator to divert exceptions from the for-loop into the generator, so the traceback can bring together the code that hit the error and the code that caused the error to be hit. This would probably be a bit squirrelly to call, but I only have to call it once. Or I could not bother, and say that continuing after an exception is undefined behavior. That's probably a better use of my time for now.
I don't want to actually touch any of this code for now, but talking through this has given me some good ideas. And some maybe-good ideas.
I don't think I have anything else to talk about right now, so I'm going to send this.
Good night.