Invest in Tooling
Adapted from a talk given at HopHacks 2022.
Thesis
Investing a (small) amount of time on how you work pays dramatic dividends in terms of future effort-to-value.
If you find yourself frequently thinking:
- Ugh I never remember the flags I need for
- I wish I didn’t have to do <repetitive, boring task>
- Why do my commits always have that “no newline at end of file” warning?
then you probably have a use-case which would benefit from thinking about how you build tools for yourself. The key distinction here being, for yourself. The stuff we’re talking about here isn’t “I’m building a web-scale, production grade service” or “this has to be an open-source project I’m proud to include on my resume.” The kinds of things we’ll look at here aren’t sexy, and they aren’t winning any awards. But maybe they can help you get stuff done, so you can get on with the other things you’re trying to accomplish.
Start Simple: The Low Hanging Fruit
Leverage tools that are built for quick bootstrapping:
- Awesome dotfiles
- Custom Connection Options for SSH
- EditorConfig
- Plugins for whatever IDE you use (e.g., https://hyr.mn/gofmt/)
Level Up: Shell Aliases & Use-Case Tooling
- Write shell aliases to make your terminal work the way you want it to.
- Seek out tools designed to support things you do in your day-to-day; for example, if you write a lot of SQL, check out SQLFluff
An real-world example from my ~/.bash_aliases
:
alias gitl="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
Keep Going: Learn Your Language’s Templater
Templaters like Jinja and Go’s text/template
are a great way to be able to build repeatable workflows and documents quickly. They’re often useful, but have lots of ins and outs which can make them tricky to pick up on the fly when you need them.
Advanced Mode: Containerized Micro Applications
… which is really just an advanced way of saying “containerize that command.”
A toy example is illustrative here.
~/.bash_aliases
hello-world/
├── Dockerfile
├── run.sh
Dockerfile
:
Dockerfile
FROM ubuntu:20.04
WORKDIR /src
COPY run.sh .
RUN chmod +x run.sh
ENTRYPOINT [ "/src/run.sh" ]
run.sh
:
#! /bin/bash
echo "$1 to you"
and adding alias example='docker run --rm example'
to your aliases means you can (after building the container image) run something like example hello
and have it echo back hello to you
.
That’s a pretty trivial example, but the pattern can help you with:
- Isolation: other changes to your operating system don’t break your program
- Consistent Images: it can be much faster to pull a container image than it would be to run the same pre-work on your machine; plus, you don’t have to keep track of what’s installed in case you re-image your machine. The
nginx
image will always installnginx
correctly in a container based on it - Composibility: makes it easier to use small steps to decompose the work into smaller components while keeping a simple entrypoint
- Portability: (re)builds when you change machines, reimage your machine, etc.