I think the first thing that should be done is to go through each file of the project, one by one, looking at each top-level
defmacro and do the following:
Study the function:
Is the function, or any identifiable sub-function logic, general enough to be cut/pasted into a utility system/package?
Pay attention to input parameters (tightly coupled to engine internals), and also whether the function has side-effects (tightly coupled to global engine state, like recompilation hooks and their dependency functions).
Based on the previous step, decide on, and possibly move it to
We can just create a new package in the
vutils system, and put higher-level Virality utilities in there.
Benefits of this approach, and doing it first:
Firstly, we get to inspect the code and re-familiarize ourselves with how the different subsystems work.
We are moving functions which are self-contained and ancillary to the engine, into a utility library, giving more focus to the structure of the engine proper.
If these functions are small, stable functions with no dependencies on any engine state, we isolate intuitive, well-behaved behavior to a support library file less likely to be analyzed while debugging.
Also because these functions are small and stable makes them easily unit-testable, complementing the prior benefit: "The unit tests pass, so let's lower the priority for a place to look when a horrendous bug surfaces". In the off chance a bug is caused by one of our small, isolated utility functions, it's just one more unit test away from never occurring unnoticed again.
If we look at the innards of functions and happen to notice any common boilerplate across the codebase, we can isolate even more code, and make testing/debugging easier.
We might learn a thing or two on how to go about refactoring higher-level concepts as modular units. Higher-level, meaning the different levels of the guts, with a lot of tightly coupled subsystems. But that's for a future think.
I believe this can all be done in about 1.5-3 hours max, making it doable in 1-2 meetings. This is because we won't be looking at the examples or support libraries like
vorigin, which all make up a major chunk of the codebase.
Drawbacks of this approach:
It's tedious and manual work, when we could be doing other things.
What not to do:
Do not make this a cognitive exercise. We will be iterating over every top-level form, looking for syntactic patterns. That is all. We should not spend time thinking about the semantics of the context in which code is used. This task should be an almost purely mechanical exercise.
Since we are visually inspecting each top-level form's body, if some sub-region of code is the same or similar enough across multiple occurrences, and it is primarily describing a useful mathematics operation, we can instead start building higher-degree utilities for
vorigin in parallel with