Once upon a time when Gildenpfennig and I were porting a mainframe to .NET we received specifications for one of the integration points - to another mainframe that would still be running.
So we set forth and started implementing. More and more "protocol" ("services" in modern lingo) specifications came in - they took quite some time to dig out since the mainframe was not very well documented - in fact, the existing specification was so wrong that they had to have one of the mainframe hackers reverse-engineer the existing implementation.
Anyway, the overall project structure was quite waterfall’ish with the customer driving the specification process and the development team consuming it.
Needless to say, that approach did not work.
We found out soon enough.
Basically they got so hooked on reverse-engineering the mainframe that they spent quite some effort writing up all the possible query responses it implemented in the integration point.
However, when we asked, "well, uh, about this latest LU62 protocol... which query triggers it?" there was no good answer... In fact, after some searching it turned out that a lot of the protocols that existed in the legacy system were no longer in use - the queries that used them no longer existed. It was just a lot of dead code left in the mainframe.
So we learned an important lesson again:
When refactoring - remove code that is no longer in use.
And don't port the dead code.