This week I've been working on Author Intrusion. I needed a break from trying to get my novel out and I'm trying to maintain a once a month release schedule for the program, so it was pretty obvious I needed to spend some time on it.
The wishlist for Author Intrusion is fairly high. The next step is sizable and may actually take more than a month to complete. So, I figured I could get started with the framework and just start chipping away at the large task.
Before that, I decided to fix some "easy" bugs that were bothering me. The first one was
Select All command caused the system to crash. That shouldn't be too hard to fix, I'm sure its minor.
Six days later and I'm still not done fixing the mass destruction of that little command.
When I was trying to get Author Intrusion 0.1.0 out, I made a number of libraries to encapsulate logic. One of them was MfGames Commands CIL which was an abstraction for text editors. Mostly, I know that Author Intrusion will have different front ends and it has its own internal, text-editor-like state. Having a common code base for these things made my life easier, but there were some complexity involved with an abstracted system.
Abstracted systems always increase complexity.
The problem with
Select All came from how to identify a location in the document. In MfGames GtkExt Text Editor, I had a class-based implementation that used Int32.MaxValue for "end of line" and very little type safety.
The new commands version took what I learned in two years of writing a text editor and used a struct-based system that had symbolic values for "End" of a line or buffer and "Word" for character. These classes were also immutable (once created, they couldn't be changed).
Side note: The magic values was the preferred system because I encountered a couple "plus one" problems where I accidently added or subtracted one from MaxValue. With a number that large, I couldn't identify the problems easily. Now, I have -113 as the "end of line" and -1053 as the "word" symbol. This way, I know if there is a plus one problem because both -112 and -114 are always invalid.
Make it work
This change broke a lot of things when I integrated the two systems together (Author Intrusion and the text editor). Since I was running out of time for an arbitrary release, I wrote some hack layers to translate between the two layers and jammed it into the places that broke.
In programming terms, this is technical debt. I was writing crappy code on purpose. True, I didn't know exactly what I was doing (one common reason for debt) but also because I needed something done.
Sooner or later, I knew I'd have to fix it "properly" but I figured I could do it later once things were working.
Technical debt, in itself, isn't entirely bad. As I mentioned, when you are fumbling through the code, not everything can be elegant and pretty. The better it is thought out, the less work it takes to maintain, but I believe most programs have to "settle" before they can be cleaned up.
The nasty part comes when I wrote code on top of the lousy code. Every time I build on it, I'm adding to the effort to clean it up. Do it once, it's just a little bit more. A year of heavy development on a lousy base… almost impossible to fix.
Biting the bullet
This week is cleaning up some of the worst of that debt. A simple thing, a text position, that is critical to almost every part of the system. I know it needed to be done and I have a much better idea of how to do it (the code is much simplier now), but still isn't fun.
And this week was the week to clean it up.
I don't regret writing it in the first place. Sometimes, the software needs to ship because making it "right" will take too long. Other times, there isn't a good answer yet. The important part, more so with this 5-10 year project, is that I keep it mind and fix it before it becomes too integral to the system.
On the other hand,
Select All works again. Page Up, Page Down, Right Word (but not Left Word), selection operations, Control Home (but not Control End) broke, but at least Select All works. :)
Yeah, I'll have that fixed by the 1st.