An important aspect of personal growth is making mistakes and learning from them.
In my first ever job I worked at a small publishing company alongside one senior developer. We maintained a multitude of websites that generally used one of a few PHP templates with the branding and MySQL-backed content being all that distinguished them. To manage this, we had a distinct CMS for each of them. This had happened quite organically; the business initially only had a few of these websites, but over time it had grown quite substantially, and I suppose they deemed it cost-effective not to develop a bespoke design for each of them.
When I joined as a fledgling apprentice, one of the long-term goals was for these CMS’ to be consolidated into a single unified experience. It would mean less work for developers and improved UX for content authors. Work began on this, with me handling the frontend in its entirety and large portions of the backend, all priceless experience as a novice. Then came time to test deploying one of the sites from the UI of this new CMS.
For context, these sites were deployed by FTP. There was no version control either. It was an old school shop.
I hit deploy, check my browser, and it looks like it worked. Awesome! Until a few minutes later when folks in the office start reporting that they’re seeing the website I’d deployed not only at its intended domain, but also across most of our other domains as well. Once my panic subsided, and my boss manually restored some backups, it was time to diagnose how this had happened.
It was a painfully rookie mistake, even for someone with so little experience. I’d missed
break statements across a switch statement. When one of the cases matched, it would deploy a pre-prepared package not only to that matching branch of the switch statement but then to all of the following branches as well. Face, meet palm.
What’s my take away from this? One is obviously to be a bit more careful around switch statements, but I think there’s a whole host of personal and organisational flaws that enabled this to happen.
Personally I should take more care and double check what I’ve done. I’ve had a habit of not doing so since primary school, at which I’d finish tests in half the alotted time but get one or two questions wrong that I’d have trivially caught had I had the patience to check my answers. Those who work with me will have caught me regularly speed-editing messages I’ve just sent on Slack. It seems to be a character trait.
Organisationally - putting aside FTP deployments et al - we should have been doing code reviews. I’m an evangelist of code reviews for knowledge-sharing but they’re also helpful for gatekeeping from silly mistakes like this.
I’d posit that the language too was part of the problem, particularly as of PHP 5.x. Languages and styles of programming that offer so much flexibility and power provide too much room for lapses in concentration or judgement like this. It is my firm belief that we are all fallible and should utilise tooling and paradigms that best acknowledge and accommodate this constraint. I think the industry is increasingly recognising this and you can see this in some of its trends:
- We’re moving away from dynamic and towards static typing, as in the cases of TypeScript, PHP, and Sorbet.
- We’re exploring alternatives to manually managing memory pointers without a GC, as in the case of Rust.
- We’re embracing many of the more transferrable lessons functional programming has been preaching, as in the increasing accord upon immutability by default and expressing our problem domains in sum types, each of which were foundational features of Rust, a modern, imperative language.
I may not have entirely stopped mistakenly setting fire to things, but I think (hope) I’m improving in this regard. I try to take lessons away from any such mishap. The same approach can equally be applied to job hunting, which has generally gone well for me but in which I made a poor choice in 2021.
I opted to leave Adaptavist in late spring as my passion for pure functional programming was pulling me away from a team and business predominantly rooted in Java and imperative TypeScript. I’m proud of the work I did there and was sorry to leave behind a great team and working environment, but I was no longer feeling intellectually stimulated. It has been and remains very important for me not to stagnate. This I consider one of the luxuries of working in a field in which after only a few years of experience you can expect to be a >95th percentile earner.
I started interviewing and it came down to a few options, all of which were with intentionally-functional languages, one of which was Haskell. Haskell! Although I’d been writing Haskell in my free time for nearly two years, including quite aggressively during lockdown, I was taken aback by the fact that I might be able to write Haskell for a living. Not long later I accepted the offer and celebrated that evening with a generous helping of special edition Lagavulin.
The offer came from Standard Chartered, a bank and renowned Haskell employer. Well, technically Mu, their in-house flavour of Haskell, but it’s essentially an old, strict fork of GHC, the de facto Haskell compiler. Haskell, Mu, PureScript - I’m not really fussed. I knew with it being a bank that it was a risk and that there’d certainly be things I didn’t like. For one, I wouldn’t be able to use my own machine for development. Additionally, large institutions like this are known for their bureaucracy. I hadn’t experienced this yet, so I accepted the risk and took a leap into the unknown.
As you’ve doubtless guessed by now, this didn’t go very well. I handed in my resignation in under a month.
The machine was high spec but slowed to a crawl by needless overbearing enterprise software. The corporate firewall would on occasion block all traffic outside the intranet. When I wasn’t fighting the firewall I’d be fighting the network whitelist. Free and tinker-friendly software like Vim became anything but.
But this wasn’t the mistake. This was an accepted risk and something I could have tolerated, such is my love of Haskell. The mistake was not adequately vetting the codebase and organisation I’d be working on and within.
I didn’t appreciate the scale of tech debt I was walking into. More importantly, I failed to recognise the organisational flaws that would in my view prevent this tech debt from ever meaningfully being taken on. It’s one thing to walk into a role knowing there’s a lot of work to do to improve a codebase, it’s a whole other ball game knowing that you’ll only ever be adding to that debt over time. I believe I could have avoided this mistake had I asked more probing questions during my interviews. This, and an experience of working at a business at this scale, is what wisdom I’ll take away with me for the future.
I want to make clear that this post isn’t about bashing my former employer. The people as in most walks of life are nice, they’re one of the few major Haskell employers, and as I understand it the codebase I landed on was uniquely challenging, something that’s been passed around for a long time and now rather dumped upon my former team. It just wasn’t a good match.