When I left my last job, some of the big lessons I learnt in software development were:
1) Rely on dependency injection, from a design perspective, I don't mean using an IoC container like Spring. This meant avoiding singletons at all costs.
2) Compile a large system out of many small modules (jars) rather than compile the system into a monolithic jar. This was vital to prevent circular dependencies.
On my current project I would add a few more lessons:
1) Write unit tests, these may slow you down earlier, but they become a god-send three years down the line, when some of the original team members have left and been replaced by others. You want new members of the team to be able to get into and refactor any part of the system. At this point you must rely on unit tests, not on the memory of an old developer on the team telling them, "you'll have to watch out in that package, there is this issue you must remember or that issue you must ensure you don't break".
2) In the same vain as testing more documentation of packages, classes, methods and fields. You don't need much, as good naming of artifacts is often enough. But I probably could have documented a bit more.
3) Use more composition to change the behaviour of objects rather than inheritance. Using composition more occurs naturally through a dependency-injection approach, however it is still possible to overuse inheritance, which reduces reusability.
4) Be more strict about ensuring most classes are immutable, rather than making them mutable for performance reasons. I got some big gains in performance but I think I sacrificed more in terms of "gotchas" other developers face with mutable classes, e.g. storing an object in a set and then wondering why it is different later. Anyway some of the performance gains disappeared by the need to clone mutable objects.
5) Using libraries for units right from the beginning and pervasively. For units I mean something like Joda from dates/times/periods and classes for other measures such as monetary amounts.