No code development ever follows the classic model of lock down all requirements, design completely, code completely, integrate, test, release. Unexpected modifications happen to an existing codebase. New pieces are grafted in somehow. It's an incremental development cycle toward ever shifting goalposts.
Code growth happens by one of the following mechanisms, loosely ranked in order of disgust:
This is the most frightening way to make code, and far too common. Code that grows by luck never had any design. It was modified without thought. Its structure is down to happenstance, and it's a miracle it works at all.
Even if your code originally was designed carefully, maintenance modifications can follow this happy-go-lucky approach. ...