In 2006 I worked briefly on an air-traffic control system (ERAM) that was eventually delivered 5 years late and $400M over budget.  I was a small cog in a giant government-contract-software machine, but it was easy to see the project was going to be a disaster.<p>There are some pretty basic strategies to make building &quot;large&quot; software easier.  All of them were attempted, but in an entirely broken way:<p>- Break the architecture down into smaller components <i>that can be tested independently</i>.<p>- Break the functionality down into smaller features <i>that can be released independently</i>.<p>- Develop automated tests <i>at the system level</i> (i.e. integration tests, not unit tests).<p>The software took 2-4 minutes to launch in development, and very few of us knew how to meaningfully test it.  This meant that any change that compiled (and passed code review) would ship.<p>Oh yeah - and the system used binary structures in shared memory to communicate across processes, which were running code written in two entirely different languages.