The Bestest of Practices

“It is possible to commit no mistakes and still lose. That is not a weakness; that is life.” Jean Luc Picard

Hot take incoming – I’m not a fan of best practices.

Let me back up.. I’m not a fan of the overuse of the term ‘best practice.’ Oftentimes, it’s a lazy appeal to authority and short circuits conversations that are intended to result in opportunities for improvement. When abused like this, it’s about as meaningless as claiming something is ‘common sense.’

Rather than referencing a crib sheet of recommendations or release notes without context, I think it’s important to cultivate the conversation and what you’re attempting with a particular approach and consider why you’re doing something in the first place. Did you just copy pasta someone else’s code without really understanding it? Do you know why it works? Do you know what you’re trying to achieve? Did you really need to indulge in yet another refactor or are you just doing tech for tech’s sake or maybe finding excuses to defer deployment? Could you have just ‘used a pencil?’ (More on useful apocrypha later)

I get it. We’re all learning. Having an enabler for our crazy ideas is reassuring. We all second guess ourselves at times and having some rule book or sacred text that affirms our approach as more than ‘just good enough’ is comfortable. What I’m suggesting is that it’s easy to cede your own judgment and pragmatism by just following suit with what everyone else is doing. We owe it to ourselves to frankly engage with our peer groups early and often to ask questions while still retaining ownership and responsibility for what what we build. Without this, today’s best practice can just as easily become tomorrow’s bad habit.

Here are few lessons I’ve learned along the way:

Preoptimization – Know what you’re optimizing and why

This is one of my first experiences around ‘unlearning’ what I was taught. When I was a wee first year dev, I was so excited to embark on my career and build useful things. One of my very first tasks on my very first project was to build out a data model for a new app. I spent a non-trivial amount of time diving into the options around specific data types for various columns and choosing the most efficient option based on the existing requirements.

The feedback I got in this case was that it was ok to just use the default datatypes for now and save the optimization for a later version or if it was identified as necessary for performance. What was more important to focus on at the time was getting the basic foundation in place so that we could start working on features. Sure, optimized datatypes are efficient and important at scale, but just not vital enough at the time to merit too much focus.

Gold plating – Voluntary Scope Creep

Speaking of focus, how many of us have spent time building something that seemed like a good idea at the time but no one really ever asked for or actually wanted? It’s easy to do this when you’re working on a feature and we start making assumptions or predictions about what users want or need. Sometimes we justify this to ourselves by assuming our user community will value a particular feature or approach. Before you know it, you’ve partially or completely reworked your work in progress around something out of scope (and for you freelancers – unpaid.) I still catch myself doing this.

Do you know what your Minimum Viable Product is? How about your Definition of Done? Who on your team needs to sign off on changes to either?

‘The New Shiny’Do you have time to be someone’s beta tester?

Above I used the expression, ‘Doing tech for tech’s sake.’ What this means is not insisting on using the latest and greatest bleeding edge tech at the expense of stability or reverse compatibility. In our modern world of CI/CD, platforms and middleware have new versions and releases almost daily. Compounding this are our myriad of (sometimes) useful libraries and frameworks with their own release cycles and end of life considerations. In this case, insisting on the latest and greatest without cause can be it’s own bad habit.

The scenario I’m reminded of here is when I hear about something cool or new & improved and I’m looking for an excuse to try it out. “New version X just went live, so let’s just embrace it now.” while forgetting that your existing standard is still supported for another few years. By all means, consider end of life and new features in a particular version, but make sure you’re actually being honest about why you’re pushing forward. Sometimes it’s ok to just wait for Service Pack 1, right?

Don’t forget to actually have the conversation

One might look at any of the above and as, ‘Hey John, didn’t you just basically outline a bunch of best practices?’ Maybe. I think what was more important to point out was how things might’ve gone negative if I and the people I worked with didn’t actually take the time to sit down and hash out the rationale for doing things one way v. the other. I like the idea of cultivating a ‘culture of proof‘ and not short circuiting these important learning discussions for the sake of expediency or even consistency.

As always, if you have any questions or comments, please feel free to add them here or address them to