Clinic time!
I know OO programming is slightly out of fashion but in my experience it's the only good way to build flexible, extensible systems, especially in large, complex software projects.
Here are some of the best pieces of advice I can give based on decades of experience:
- think conceptually, not functionally
- decompose and encapsulate
- small abstract APIs at touch points
- mock, isolate, and unit test the shit out of all your little components
- always put readability above all