Building something new brings with it a burst of motivation and inspiration. As the project gets closer to the end goal and becomes “good enough” that motivation reduces proportionally. However, this “good enough” benchmark is rarely accurate. Instead, it's often a misinterpretation: good enough for you, the creator. When you begin to feel this reduction in motivation, inspiration, and momentum, it is time to collect feedback on what you've done so far. Once in the hands of users the cut corners, missing functionality, lack of documentation, and other flaws surface. These are the things that make your project truly “good enough.”
Software grows, adding new features and paradigms along the way. If you're not careful, it becomes less opinionated about how or what is done. One small feature to support dynamic configuration begets a system of loading various file types and executing arbitrary code. Where there could have been one clear way to support this feature, there are now several confusing ones. Instead of having fewer opinions for more use cases, software should be more opinionated to focus on its core use cases.
Opinions imply constraints on our projects. They limit what we can do with the tools we are given. However, they also reduce the work we need to do, letting the tooling pick up the slack. Strong opinions allow software to be more focused and built more quickly. Accounting for fewer things also allows programs to be simpler. In turn, opinionated tools allow us to develop more focused, smaller, more opinionated applications. Rather than extending to every use case, it's important to maintain the core focus of your project; it's important to be opinionated.
Applications and tooling continue to follow the same cycle: start small, inflate with features, and finally become so unwieldy or unusable that users flock to the next application that promises to be smaller and more focused. This cycle is not sustainable for creators, due to the ever-growing cost of new features and increased maintenance, as well as users, due to the constant fear that they will have to pack up and move to another service. As users, we can Mind What We Can Manage. As creators, however, we have the ability to solve this problem. How, then, do we avoid this cycle? How can we keep our software small, focused, and responsible only for the problems it was built to solve?
The ability to know when a product is finished is not only a crucial skill, but one that our industry severely lacks. Doing so saves time, money, and headaches for everyone involved. Instead of continuing to stuff features into a given product, it's important to stop and ask “Does this solve the problem this product was built to solve?” Each and every application or tool is created in an attempt to solve a problem. At some point, that problem is solved and no longer requires additional changes. If you ask yourself this question and your answer is an emphatic “Yes”, then that feature may well be a core part of your application or tool that was previously absent. However, any other answer is a great time to step back and try to understand why it doesn't. It's likely a great sign that you should seriously consider stopping.
Not every idea is great. Few will last for more than a moment. For this reason I don't write them down, save for a few exceptional circumstances. Instead, I wait. Good thoughts tend to stick around and great thoughts tend to be all-consuming.
Rather than saving every idea as it arrives, my strategy has been to let these thoughts free, expecting the best ones to return. Often I'll expect this “boomerang effect” to happen more than once, enabling me to better gauge the quality of a given idea and the motivation I have to pursue it. This strategy has also given me more time and freedom to construct those thoughts as I find putting ink to paper has a sort of finality to it that codifies this thought, disincentivizing further change.
From this strategy, I've produced:
And many more.
“Perfect is the enemy of good” is a surprisingly dangerous thing to say. Unprepared, it could cloud your judgement, encouraging you to produce something that isn't even good simply out of the fear of making something perfect. It's important to be prepared as this adage is bound to appear throughout the creative process. Constraints may force us to compromise or remove features outright, but the standards we have for the parts we do keep should not sway. As well, the parts we both add and remove should be scrutinized. Sometimes things need more time, other times we need to Know When To Stop.
What happens when a fundamental piece of your program no longer exists? When a service you rely on is discontinued? These are problems we've only seen increase with the high amount of churn in the software world. Rather than relying blindly (or hopefully) on an external service or project, we should be diligent in our search and assessment to determine the reasonable safety of our choices.
Assessing software before committing to a given project can be difficult. Some people rely on “popularity” or usage by a notable company as positive signals to determine the safety of their choice. However, these points of data can be, and are often, completely irrelevant to your ability to keep using a given piece of software for years to come. Instead, I've found, the most important factors are size, code quality, and language. Small projects, written well, in a language you specialize in are perfect candidates. Your ability to step in and (minimally) maintain the project is paramount, lest you be left out in the cold. With this in mind, before binding yourself to an external service or project, ask yourself: “Can I manage this?”
People say “Don't reinvent the wheel” a lot. But what about building a better wheel altogether? I mean, could you imagine if we stopped with wheel v1? It's quite rare that anyone gets things right on the first try. And, even then, in the world of tooling it's just as rare that your needs will align perfectly with a preexisting solution. Every person, team, and business will have its own special set of needs. Sometimes those needs line up well enough with what is available on the market. Sometimes they won't. So, instead of settling for second-best, what do we do? Build a better wheel. You already know what you like, what works, and what's missing. Instead of having to reinvent everything, you only need to come up with a v2.
Make things that already exist and make them better. Don't let others tell you that the status quo is good enough.
I've seen this mentioned quite a bit over the last year: “Don't use Kubernetes for your blog”; “Don't use Kubernetes for just one service”; “Don't use Kubernetes for _______, you don't need it”. Sure, you don't need a lot of things.
I've chosen to run my applications on Kubernetes and, if you were turned off by the naysayers, you might consider doing so as well. Here are a few reasons for why I've decided to introduce this extra complexity:
A learning opportunity, expanding domain knowledge
Rapidly develop and deploy new applications
Ownership and control over the whole system
The most important reason when making this decision for myself was “I want to learn this.” I spent the time learning how to create a Kubernetes cluster, deploy a blog, configure GitOps, etc. Because of that I built the skills to create some really useful infrastructure at my day job.
So yeah, you should host your blog on Kubernetes, you'll probably learn a lot.
Oh, and it also helps that Kubernetes is pretty fun to play around with.
I've been thinking a lot about the assumptions we make about domain knowledge when writing guides and documentation. Far too often, I've found myself needing to look up a host of terms and acronyms just to translate this jargon into plain English. Now, I've spent a lot of time doing this and gotten reasonably good at parsing text like this (often in the form of technical documentation). But, consider a developer with less experience and/or domain knowledge. They would be left not even knowing where to begin. All because the text preferred jargon over simple explanations.
I've found, where possible, complex terms should be accompanied by a simple explanation (or a link to one). That is, of course, if these complex terms are really necessary. It's not uncommon for them to be replaced with simpler, more intuitive ones. In fact, writing simpler documentation can benefit more than just novice developers. Simpler documentation can mean a faster turnaround time for newcomers to the project regardless of experience. It can also make referencing these documents easier, limiting time spent switching contexts to look up definitions/meanings. When you fail to describe things in simple, concrete terms, that burden falls upon the reader. This up-front cost to understanding your documentation should be as minimal as possible. If you force people to pay entrance fees, they'll start looking elsewhere for free admission.