The “lone developer” problem: when a single programmer builds something, it’s often hard for others to maintain later. This seems to affect everyone, myself included. See https://evanhahn.com/the-lone-developer-problem/
Tweaking my setup has limited benefits. It’s really fun to customize my dotfiles, pick the perfect editor, and tweak my dev setup. But I don’t think it’s a huge time saver. There are some great tools that have helped, and tinkering can be a great way to learn about how things work. But choosing the right colorscheme isn’t usually productive, and I haven’t observed a correlation between “good programmer” and “cares a lot about their editor”. (…it’s still fun, though, and I do it a lot!)
Try using the tools I already have before reaching for new ones. Instead of installing a fancy Zsh package, see if I can set $PROMPT and be happy. Instead of installing a dependency, see if the standard library has something similar.
HTTP status codes aren’t worth fussing over. There's usually an obvious choice. Some distinctions are useful, but others are not. If it takes more than a minute to pick the status code, I worry.
“Learn X in Y minutes” is a great resource for quickly learning the basics of programming languages (and a few other things). See https://learnxinyminutes.com/
Use the positive version of a variable. Variables like use_widget are better than skip_widget because they help avoid confusing double-negatives. (I’ve seen this confusion cause a significant security bug!)
There are lots of ways to document my code. Some ideas: explicit documentation; good names for functions and variables; breaking up code sections into named functions; comments; log messages.
The functional programming people can be quite smug, but they’re often right. It’s harder to do a good job with object-oriented programming, and easier to do a good job with functions that operate on immutable data.
The distinction between “simple” and “easy” is important. Simple is the opposite of complex. Easy is something else; it’s familiar. Understanding this distinction has helped me develop simpler software (though I still have a ways to go on this front). See https://www.infoq.com/presentations/Simple-Made-Easy/
When presented with a difficult task, I ask myself: “what if I didn’t do this at all?”. Most of the time, this is a stupid question, and I have to do the thing. But ~5% of the time, I realize that I can completely skip some work.
Do a “spike”. Sometimes, I try implementing a feature in the smallest possible amount of time, with awful code, horrible hacks, and lots of TODOs. Once I have something working, I clean it up. I’ve found this to be a useful way to see where the challenges lie, and a pretty good way to build things quickly. See https://ntietz.com/blog/throw-away-your-first-draft/
Different approaches for different tasks, teams, and projects. For example, it would be irresponsible to build a pacemaker with no automated tests; people could get hurt! But it would also be wrong to stress about automated tests during a weekend game jam. “Good code” means different things in different contexts, and I need to tailor my approach to the problem at hand.