Tag: Invent And Simplify

When Everyone Is Super

When Everyone Is Super

By name, at least, I’ve now worked at six different vendors of government solutions. There’s a fundamental tension that arises when building for state governments especially, that I’ve seen over and over again:

  • On one hand, vendors want to build products that can be deployed repeatedly across states for cost-effectiveness at scale and rapid per-project implementation
  • On the other hand, states have wildly-divergent policy landscapes and political realities, even in seemingly similar domains, demanding highly customized solutions

This tension creates numerous challenges. First, how should the system be architected to support configurability in the first place? It adds cost and risk to do so. And then, how should vendors approach communication of configurable features to a paying customer who doesn’t need the options? If you’re collaborating closely during development (as you should) it’s going to come up in planning and status meetings.

A case I’ve made that usually resonates is that having configurable options enables us as a vendor to maintain a (mostly) common codebase across customers. And that means when an improvement is made for any customer, everyone benefits. More succinctly: forks are bad. I can tell at least one tale of a high profile private customer that initially insisted on having their own radically customized copy of our company’s core product line, only to regret it a few years later when it took months to back port newer features to it.

Here’s a few considerations for product and engineering folks to consider when developing a solution for scale through repeated implementations:

  • First Project: have scalability in the back of your mind, but don’t fall prey to YAGNI and overbuilding otherwise you’ll price yourself out of your first customer; just do basic foundational configurability and focus primarily on your immediate requirements
  • Second Project: don’t make the mistake of thinking you can discount your pricing, you’ve yet to hit economy of scale, and you’ll need any budget saved from reuse to expand your configurability capabilities and begin thinking long-term scaling strategy
  • Third Project: this all-important moment is where you can now truly begin thinking about productization, having full configurability (going beyond mere look and feel to business logic) and rapid, repeatable deployments
  • Fourth Project: now you should be reaping the efficiency benefits of your configurability and repeatability; if you haven’t yet, act fast and make investments at speed, or it’ll be too late

Finally, an anti-pattern:

if customer == 'Customer 1':
    doAThing()
elif customer == 'Customer 2':
    doADifferentThing()
elif customer == 'Customer 3':
    doYetAnotherThing()

The above might be fine for your first couple projects, but if it’s still in your code by project 3 or 4, you’re doomed.

Covering the Bases

Covering the Bases

Dropdowns in web forms are generally good; they make it simpler for users to input options correctly and ensure back-end data integrity. They can be limiting at times, though, so I have to respect an event registration website I used yesterday that tried to be all-encompassing in the selections for “Title”:

Henceforth I expect to be addressed as “Lord Neer”

I have to imagine this list came from some out-of-the-box form generation tool. Or created by GenAI, perhaps? I’m curious what it could have been. And was it not modifiable? Suffice it to say several of the choices are fairly pretentious given the event I was buying tickets for, so I feel like maybe the developer should have looked into culling the list.

Headquarters (Part 3)

Headquarters (Part 3)

Just when you thought there couldn’t be more (oh trust me, there’s more), here’s comes another round of my series on computer setups (earlier posts are here and here).

Years: 2005-2010
Machine: The box in the closet from my last post but with a snazzy new LCD monitor (my first flat panel), wireless peripherals, and my wife’s great-grandmother’s writing desk.
What I was doing: writing daily on Xanga; applying to family camp; traveling to Tennessee to watch Revenge of the Sith with a high school friend; hosting LAN parties for Age of Empires III; traveling a lot for work.

Years: 2006-2007
Machines: A plethora of cast-off parts coalesced into a couple functional boxes in the garage.
What I was doing: running a NAS for storing all my media; trying to get Gentoo Linux to compile; realizing that running a bare web server on the Internet is asking for trouble.

Years: 2008-2010
Machines: A beefed up HTPC rig in a rackmount case with a whole bunch of amps to power my Magnepan speaker system, plus the plethora of beige boxes from before, but better arranged.
What I was doing: shivering in the garage when using this desk in the winter, listening to Comfortably Numb at peak volume, hosting movie-watching parties.

Year: 2011
Machines: Same rack mounted setup, but relocated from our old garage in Ohio to a closet in our new garage in San Diego, plus a random beige box (those just won’t go away).
What I was doing: Playing with some audio recording gear; streaming Game of Thrones; stocking up on printer paper, apparently.

Years: 2012-2014
Machines: Moved inside, and rebuilt the guts from the rack mount case into a traditional one (albeit black and silenced), also got my first Mac laptop (from which I’ve never looked back).
What I was doing: writing election software; creating hand-made guitar effect pedals (that were terrible); developing back problems thanks to a crummy chair.

Figuratively Speaking

Figuratively Speaking

Speaking effectively to non-technical people can be a challenge for technical folks, but it’s an essential task for all but the most mundane (read: least-effective) of roles. One mechanism that I’ve found helpful is the use of metaphor. I’m a huge fan of trying to describe complex topics by mapping them to more broadly understood concepts. Being able to come up with such mappings fluently is a powerful skill. There may be many ways to develop it, but I suspect one is cultivating a wide set of interests.

While I was writing Tuesday’s post, it occurred to me that today’s Generative AI tools are to software what today’s 3D printers are to physical objects. On one hand, it’s incredible to be able to provide a specification and have it manifested in near real-time. Printers can make a variety of solids: toys, some kinds of replacement parts, that sort of thing. GenAI can create chunks of useful code, quick user interfaces, and basic apps, like my Pinochle scoresheet. But there are limits. Can either of these tools produce high tolerance, precision parts / highly secure, performant code? Can they build complex solutions like electronics / web browsers?

A 3D printer creating a figurine

I could be wrong, but just like we’re a long ways from 3D printing an iPhone, we seem a ways away from vibe coding Microsoft Word or an entire government system of record.

Old Dog, New Tricks

Old Dog, New Tricks

Over two years ago I bought a few domains with the intent of building a tool for keeping track of card game scores. Like many of the best laid plans, I didn’t get around to doing so. Until now.

With the advent of GenAI and “vibe coding” I figured there was no longer any excuse. I spun up Lovable and started prompting. The results? Not bad. Not bad at all. With maybe a dozen prompts and half an hour, you can see the results at onlinescoresheet.net. What was most impressive for me is that I was able to simply ask the model to do Pinochle scoring, and it was able to understand what that meant and implement it without me explaining the rules.

What’s up next? I’d like to generalize the scoring system to be configurable, or at the least add explicit support for a few more game types. I’d also like to dig into the source code to evaluate quality. Should be fun!

In Brief

In Brief

I like Github gists. They’re perfect for long-term publishing of any code snippet you might want to refer to later, without the overhead of a formal repository. I’ve used them as backing storage for a number of blog posts as well, and will do so again today:

Need to bulk update the contact information across a set of domain names you own in Route 53? I got you. Need to do it across a whole slew of AWS accounts (or anything across a number of accounts)? No problem.

Happy scripting!

Lightning vs Lightning Bug

Lightning vs Lightning Bug

For many organizations (mine included), November is performance review season. I know it’s not everyone’s cup of tea, but I quite enjoy both getting and giving of constructive feedback. So much so that apparently I like writing about how I like performance reviews every November as well.

Today’s post is about specific questions for collecting feedback from stakeholders about a person you’re reviewing. Giving such feedback is uncomfortable for many people; it can feel like tattling or speaking ill of someone behind their back. But as a manager, my perspective is inherently limited (and usually biased). I require input from those who are working with my team day-to-day in order to fairly evaluate them and give them the feedback they need (both growth opportunities and especially praise they may not otherwise hear).

I’ve used a variety of approaches in the past, with mixed success. But I recently formulated a pair of questions in conversation with a career coach that I think can coax out the desired information without making stakeholders have too icky a feeling about giving it. They’re delightfully simple, and can be answered quickly and discreetly via BCC-ed email or even DM:

  • What do you appreciate about them?
  • What advice would you give them?

Question phrasing matters. I’ll be giving these ones a spin this year, we’ll see how it goes!

Tunneling Through

Tunneling Through

From time-to-time I have need to connect to VPNs, usually when doing work directly for one of my government partners. For a reason that utterly escapes me, Cisco hides its AnyConnect client behind a login that requires a license. And it’s a heavyweight install to boot. Ugh. I’d rather use a CLI; enter openconnect.

It can be a bit tricky to get the parameters right, so I put together a little helper script that abstracts some details, not the least of which is storing the VPN password in the local keyring for quick retrieval.

Posting it here for posterity. Enjoy!