One of the last projects that I worked on, while in AliveCor was that of a massive movement of the URL router of a large go monolith (which served more than 1000 APIs actually) while keeping the old one during the transition. The old one was using a router project whose last commit was somewhere in June of 2018 (if I remember correctly). I was tasked to move all those routes to a newer, more popular router from the famous gin framework.
The Ordeal
For each handler function (which were also numbered in the same range, more or less), a new wrapper function had to be created. After doing so for a few dozen handlers and getting tired, I noticed the pattern around naming, formatting, placement and variable extraction and assignment which could be used to fit the current actual handler and the new routes.
Was it boring? Of course, it was! And what do we do to boring processes? We automate!
The Order
How do you automate a coding task that is repetitive? There used to be one way: creating some kind of script or plugin for your editor. Now we have one more - ask an AI. Since using AI for something like this would open a new can large drum of worms, I chose the first path. I set out to write a small plugin which could actually get it done.
The IDE that I used was Goland. Now, Goland, like all other IDEs from Jetbrains is a fantastic piece of art. But when it comes to writing plugins? Well, it wants me to write one in Groovy. That’s a new language the skills of which are mostly useless. So, I turned to vim, rather neovim which I was already using at times. I thought “maybe a vim marco could save me time”.
The Ordinance
If you have known how to use neovim, you would know that writing a macro or a small function using lua to automate something like that should not be a big deal. You gotta use a bit of care and some clever sequencing of your keystrokes and you would be able to automate such a work. I tried. It took me almost 5-6 hours but it started working.
All that I now had to do was place my cursor at the line where the function was defined, hit a keystroke and a new function right above it, compatible with the new router would appear. It reduced the work of about 2 minutes to 2 seconds. That’s 60x the gain, using a tech that was invented before I was born.
Java
Java is hated by many. Including me. I mean all tech has its place. And Java does way too many things well on so many fronts that you can’t ignore this thing. It is one of those technologies, which are looked down upon by cool dudes but still delivers. There are two things I sincerely dislike about Java:
- The amount of code I have to type. I like mountains but not mountains of code.
- The mess it feels like for doing simple things. e.g. I would much rather prefer the way go handles time than how I need to pick the right class and then do things in that class in Java. And yet all classes feel incomplete at certain places.
Recently I got to work on a Java project after years. I had forgotten why I hated the language. This new experience made me realize how true the words by Maya Angelou are. I had forgotten why I really hated Java but I never forgot how Java made me feel. This time though, I realized that I had a new reason to hate Java:
- You could bloody well write all sorts of spaghetti-looking syntax and that thing still compiles.
Been working with golang for years where go fmt
bound to your editor auto-formats your code to make it look sane and uniform had made me forget that other languages allow random spacing, 20 blank lines between two meaningful ones, field types and names need not be indented in a class, the braces can be far and wide from where they should be and whatnot!
I guess this is the case with most languages that were invented before go - enforcement of syntax is so low, you can write freeform looking code. Each person’s syntax could be wildly different from another and each of those styles would work.
The Ordinance… continued!
What I stated about the work at the beginning, was one of the smaller parts. Similar amount of work was needed for router-to-handler registration for the new handlers. Significantly more was required to handle path variable names inside the handlers for the new routing system while maintaining the compatibility with the old one.
Had it not been for the wisdom of these oldies who don a beard in various styles ranging from a goatee to a gandalf, who thought of allowing macros in an editor and enforcing a syntax in go, it would have been a nightmare handling 3 repetitive tasks, each 1000+ times across a 10-year-old monolith where the ratio of mistake-to-menace is nearly 1:2.
Although I could not complete the entire task before I left, the significant amount of work that got done was purely because of the “my way or the highway” approach of go towards syntax. Sometimes it’s a good thing.
I can’t imagine writing macros that could perform the same set of actions reliably enough for a Java codebase of a similar size. It felt like the people who built go somewhere did have vim in mind and how being repetitive, enforcing and boring was brought together for the greater good for the programmer.
The sequence
The keystroke sequence for one of them looked something like this though:
vim.fn.setreg("u", 'yy"yp5jpjddk0f:dl_yiw2k_vepyiw4k_wvep6j0f"lyiw2k0f"lvep4j0f#')