Q:

What are the most effective techniques to stop a codebase from becoming difficult to maintain as it grows?

I am a software engineer of 10 years and wondered what other people have found effective in stopping a codebase from degrading over time. For example, some of the issues I have noticed are:

large technical debt 
loss of knowledge from companies due to personel changes 
complex upgrade and migration strategies between product versions 
multi site teams with different values
large requirement of knowledge to understand the product and component parts
difficult to understand design due to cumulative development over a number of years
large and diverse code paths
mixed technologies eg: oracle/sql server
different departments with differing levels and areas of code responsibility

My main area of interest is to learn what strategies a technical lead could employ in a new project to minimize degradation of the codebase over time?

A:

What are the most effective techniques to stop a codebase from becoming difficult to maintain as it grows

Obey the Law of Demeter.  It teaches you that not only values in objects should be encapsulated but objects should be encapsulated by their friends.

large technical debt

Start by fixing whatever is making it larger.  Killing crocs can be fun but draining the swamp is more effective.

loss of knowledge from companies due to personnel changes

Mentoring. Cross training. If you have only one go-to-guy for something it's time they trained another guy.

complex upgrade and migration strategies between product versions

Make developers do what they're asking users to do.  Developers are good at automating what they care about.  Get them to care about it.

multi site teams with different values

Having different values isn't a problem.  Not understanding those different values could be.  Visit the sites if need be.

large requirement of knowledge to understand the product and component parts
  difficult to understand design due to cumulative development over a number of years

Where are your requirements?  If you're like most they're in the code. If you had requirements documents you trusted you could simplify around what you know you really need.  
Since it's in the code the best thing to add now are regression tests that prove your application is still doing what you need it to do.  With the tests in place you're now free to simplify, decouple, and modernize the design.

large and diverse code paths

Did I mention Demeter?

mixed technologies eg: oracle/sql server

If your design requires you to care who built your DB it's no wonder things have turned ugly.  Kick your DB out of your domain and treat it like a plugin.  Only a few things should talk to the DB directly.  Did I mention Demeter?

different departments with differing levels and areas of code responsibility

...is a good thing.  Do one thing and do it well.  Don't interface with everyone.  Talk only to your friends.  Provide useful abstractions so your friends don't have to talk to your other friends. Did I mention Demeter?

