Harsh refactoring
It’s a bit ironic but I remember being unimpressed with Go when I first saw it. One of my senior devs, very enamoured of the new language, drew my intention to it, but I was less then impressed. I found it ugly and verbose (especially compared to Ruby, which was what I was mainly using back then), and for the type of work I was doing at the time, didn’t really see advantages picking it up.
I wish I had listened to him much earlier. It’s been miles of bumpy road, but it’s probably the main tool I reach for now despite its verbosity. I taught myself the same way I’ve always taught myself new languages, applying it to some actual use cases I had, and wading in head-first to code in it.
One of the earliest things I felt good enough to open source was harsh , a minimalist CLI habit tracker, which was orginally an educational exercise, but also actually scratched my own itch for a serious problem I had.
Looking back at the code palimpsest now, I did what I knew at the time, which was more about constructs I understood from general programming, like maps and hashes, rather than doing thing in more idiomatic Go, leveraging structs, interfaces, and goroutines as much as I could have.
Fast forward a couple years with a bit of time I had that it, and a bunch of other long back-burner-ed projects, needed updating and improving.
While I’ve been slowly improving it and making it more efficient in the background and as feature requests rolled in, an architecture and design overhaul for the underlying app as well as better testing and modularity was long overdue.
(and yes, I still use harsh every day to track my habits. I’m not kidding in the README when I say it was the only thing that seemed to work for me. I do own that it is probably in need of a mobile app to keep the CLI and on-the-move tracking in sync.).
So, what did I do?
- Moved the underlying cli framework over to Cobra
- Improved data structures for speed, efficiency, and caching
- Abusing goroutines where parallel processing made sense for speedups
- More structured, modular, and testable code (with actual real tests) and better separation of concerns
- A more hackable framework to make some UI changes looking at things like Bubble Tea and friends
So, the 0.11.0
release is a fairly major overhaul that happily coincides with
Go 1.25.0’s release. So, a lot more code craftmanship and a better architecture
for the future. Quality of life improvements for users in terms of speed and
efficiency should be noticeable (well, it was fast before, but now it’s very
fast.).
In any case, I hope you enjoy and get as much out of using harsh as much as I do. The refactoring was actually fun and went way faster than i thought it would. harsh has been a strangely calming and centring influence in my life allowing me to realize when I’m drifting too far over the yellow median on any particular thing.
So, I hope you’ve found harsh useful. If it has been, or this post was useful to you, and you do end up making habits stick with it, lemme know via mail or elephant below. Feel free to mention or ping me on @awws on mastodon or email me at hola@wakatara.com .