I did some heavy refactoring on Disk Clock over the weekend. I haven’t made a release of it, since 1. packaging is kind of a pain 2. there was only one very minor bug fix for user visible features 3. I don’t think anybody cares. The code is in BitBucket if somebody does.
Viva La Revolution
The first module to be extracted was some small revolution/radian calculation functions, but I had to lift them out of the local scope so that I could extract the code which depended on them.
The Ties That Bind
Revolutions was the easy case. Pulling out the Disk ‘class’ was a little like pulling teeth, though it was more straightforward than I feared. Some of it was tracking down dead code and simply removing it. The rest was mostly other small refactorings and code shuffling.
Poor Mans Dependency Injection
One cheap trick for pulling the class out was to assign necessary values to items in the prototype, which get set after the fact from the calling code. An interesting possibility here would be to derive intermediate prototypes, each configured differently. Perhaps something to add to the presentation on using prototypes that I have in the works.
I still consider all the wiring a little hacky. On the upside, now the dependencies are explicit. On the downside, I haven’t fully explored that prototype juggling yet, so it won’t be instanceable in it’s current form.
Playing With Time
One module that got extracted was the code that handled running time at variable speeds – I called it TimeMachine of course.
Time for a Purge
Starting with the time module, I also started dropping things out of my ‘generic library’ that have never found a use outside Disk Clock. I can always put them back if and when I find a use. The time module got broken up in the process, and I may do the same to the others, subject to a review of how much actually gets shared between projects.
An Acute Case Insanity
Along the way I’ve decided that I’m not so sure about using the ALL.CAPS.MODULES, so I’ve been translating things as I touch them.
One of the injected dependencies that put up quite a fight was the animation control. There was a marginally specialized system which managed the rate at which disks needed to update. Many will go once a second, others might need to update only once a day, but the whole thing needs to spring into action if there is an animation to run. I thought perhaps I could extract this into an animation manager (or Anima), but there was some deep-seated coupling going on.
For one it was deeply stateful. When something requested the animation step size, it triggered the animation frame rate. I thought it might make sense to treat the disks as generic animatable objects and pull in the update loop, but that loop also calculated and passed in the disk’s scale. There is a small nod to functional methods here wherein the target-state (time and size) is passed in instead of being held as state. (The animated response to changes still makes it rather stateful, however.)
In the end, by the time I puzzled out a joint to make the cut (putting animation detection into the disk’s delay method and polling), the code I was looking to extract evaporated during the course of refactoring. I guess the best code is no code?