Sure! I have a ton of thoughts on this, so I'll just touch on a handful of higher level things that I think matter:

- Avoid rules and tools

Until you understand why someone came up with them originally. My biggest blind spots came from reliance on things like React Dev Tools. Every time I had to sort out a bug, I would start poking through React Dev Tools immediately without thinking, find the issue, and then patch it. The closest thing I can equate this to now is using a GPS to navigate. You'll get to your destination, but you won't learn the roads you drive on every day. Throw out the GPS, and you find pretty quickly that you know the roads, which is a faster + easier way to navigate. Same thing with debugging. You can still use the GPS once you know the roads if you need to get somewhere unusual, but you shouldn't usually need it. Same thing with debugging tools. Big time saver.

Rules are in a similar camp. Strict global rules are always bad. "Don't repeat yourself" is a horrible as a strict law in a codebase. I repeat myself all the time intentionally to avoid prematurely abstracting things. That being said, there are times it's absolutely mission critical to abstract something or risk massive difficult-to-unfuck technical debt moving forward. Knowing the "spirit" of these rules (which is difficult to garner via anything other than experience) is incredibly important in using them effectively, which in turn also saves a ton of time.

- Use a tool from your toolbox

As much as you can, don't make/use new tools. The law of the instrument[0] can actually work to your benefit in engineering if you use it correctly. The fewer tools in your coding toolbox, the more proficient you'll be at using those tools. The bugs that arise from that limited set of tools are more predictable and become easier to avoid and easier to diagnose. Your code ends up naturally looking more consistent when you're trying to treat every problem as if it's from the same set of problems (and in my experience, very few problems are not from a very small set of types of problems). The less unique problems you're solving, the less time you're spending learning how to use new tools. This effect compounds as time goes on, and ends up being incredibly powerful over time.

- Be even more explicit than you think you need to be

Implicit functionality is the beginning of the end of any codebase. If you think comments are necessary, the code is too implicit. If you have to ask the author what the code does, the code is too implicit. Code should make intuitive sense like a great UI makes intuitive sense. Non-engineers with an understanding of your product should be able to traverse your folder structure and find something if they want to (most members on our team are able locate and modify copy in emails/notification/interface files without much trouble). But it's not for them, it's for you. Trying to remember what you did on a feature you built 6 months ago is borderline impossible, so don't try. Write it so that you don't have to, and that'll guarantee other engineers working on it at any time can dive in without talking to you about it first. A lot of time is saved in not having to bring yourself or anyone else up to speed on anything.

- "Think slow"[1] about everything

Your brain is going to want to "think fast" all the time. Brains weren't made to code, so they're really bad at knowing when to rely on instinct and when to consider something more thoroughly. It likes to think fast more than it likes to think slow, so you'll end up coding instinctually if you're not intentional about it. That will result in code that looks like the most significant project you worked on before this one, and that code probably doesn't make any sense in whatever you're coding right now. So you have to force yourself to think slow about literally every single little detail of the code you're writing at first. Every styling detail, every filename, every semicolon, literally everything. Consider it, make sure you understand exactly why you're doing it, and make sure it makes sense to you in this specific scenario. Be able to explain why you do everything the way you do.

This is immensely tiring up front, it feels impossibly unsustainable. And it would be if you had to do it every time you wrote code, but you don't. Once you understand exactly why you're doing each thing you're doing, it's incredibly quick to understand if it still makes sense in each following scenario. Once you've gathered most of the reasons for the way you write code the way you do, the process starts to fade into the background - you can start to "think fast" again. And even better, you've trained your brain to stop and "think slow" when you don't have an explicit reason for doing something a particular way, thus preventing any "relapse". It's locked in. Engineers who have this figured out can avoid writing unpredictable/difficult-to-debug code with clinical precision and save themselves days of pain per month.

I think this last step is actually the core of "having the right habits from the get-go". I think every great engineer can explain every tiny little nuance of why their code is the way it is. I don't think that comes from being a great engineer, I actually think that's how you become one in the first place.

My pet theory is that this list is part of how one becomes a so-called "10X engineer". You don't have to code 10X faster, you just have to use clever compounding tricks to spend 10X less time on the noise in between.

[0]https://en.wikipedia.org/wiki/Law_of_the_instrument

[1]https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow