I have been working as a software developer for many years now. It has been my experience that projects get more complex and unmaintainable as more developers get involved in the development of the product. 

It seems that software at a certain stage of development has the tendency to get "hackier" and "hackier" especially when none of the team members that defined the architecture work at the company any more.

I find it frustrating that a developer who has to change something has a hard time getting the big picture of the architecture. Therefore, there is a tendency to fix problems or make changes in a way that works against the original architecture. The result is code that gets more and more complex and even harder to understand.

Is there any helpful advice on how to keep source code really maintainable over the years?

The only real solution to avoid code rot is to code well! 

How to code well is another question. It's hard enough even if you're an excellent programmer working alone. In a heterogeneous team, it becomes much harder still. In outsourced (sub)projects... just pray.

The usual good practices may help:


Keep it simple.
Keep it simple. This applies especially to the architecture, the "big picture". If developers are having hard time to get the big picture, they are going to code against it. So make the architecture simple so that all the developers get it. If the architecture has to be less than simple, then the developers must be trained to understand that architecture. If they don't internalize it, then they shouldn't code in it.
Aim for low coupling and high cohesion. Make sure everyone in the team understands this idea. In a project consisting of loosely coupled, cohesive parts, if some of the parts becomes unmaintainable mess, you can simply unplug and rewrite that part. It's harder or near impossible if the coupling is tight.
Be consistent. Which standards to follow matters little, but please do follow some standards. In a team, everyone should follow the same standards of course. On the other hand, it's easy to become too attached with standards and forget the rest: please do understand that while standards are useful, they are only a small part of making good code. Don't make a big number of it.
Code reviews may be useful to get a team to work consistently.
Make sure that all tools - IDEs, compilers, version control, build systems, documentation generators, libraries, computers, chairs, overall environment etc. etc. - are well maintained so that developers don't have to waste their time with secondary issues such as fighting project file version conflicts, Windows updates, noise and whatever banal but irritating stuff. Having to repeatedly waste considerable time with such uninteresting stuff lowers the morale, which at least won't improve code quality. In a large team, there could be one or more guys whose main job is to maintain the developer tools.
When making technological decisions, think what it would take to switch the technology; which decisions are irreversible and which are not. Evaluate the irreversible decisions extra carefully. For example, if you decide to write the project in Java, that's a pretty much irreversible decision. If you decide to use some self-boiled binary format for data files, that's also a fairly irreversible decision (once the code is out in the wild and you have to keep supporting that format). But colors of the GUI can easily be adjusted, features initially left out can be added later on, so stress less about such issues.

