Great question.<p>For me one of the biggest shifts was test-driven development. That is, I start with a test, write a few lines of test code, make it pass, perhaps refactor, and write a few more lines of test. It took me a year or so to get from test-last to test first, but I love it now; it forces me to look at code from the external perspective. One way to put it is that it shifts my focus from internal mechanism to real-world meaning.<p>Another breakthrough was pair programming. The larger a code base gets, the more important readability and easy comprehension get. But at least for me there&#x27;s a real limit on how comprehensible I can make a piece of code on my own. I just know the internals too well to usefully model the reaction of somebody who neither knows the internals nor wants to. But pairing gives me (and allows me to give) continuous feedback on what makes sense and what doesn&#x27;t.<p>A third favorite is known as Domain-Driven Design [1], where one organizes the code around the actual concepts of a business domain. The larger a code base gets, the more possible places one might look for a particular piece of code. Organizing the code by the real-world notions is a great check on entropy.<p>[1] <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Domain-driven_design" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Domain-driven_design</a>