I had a discussion recently with a manager who was concerned about his developers meeting their milestones. “We have “Code Complete” as a milestone. The developers say they meet it, but that just means they wrote code until the milestone date. The code isn't complete. I can't even tell how complete it is.”
Ah, the hazards of a functional milestone. Functional milestones occur when a functional group says they're done with something, not when a particular piece of the product is done (including review and integration with the rest of the product).
“Code complete” should be based on a bunch of feature deliverables (Feature 1 implemented, tested, integrated, Feature 2 implemented, tested, integrated, and so on), but we tend to use “Code Complete” (or my favorite, Code Freeze)as a milestone itself, instead of a roll-up of interim milestones. When project managers don't have feature-by-feature (or architectural milestones if you insist) milestones, with developer testing and integration built in, the developers don't remember or don't feel they have the time to do the testing and integration. (Too often, developers are correct, they don't have enough time because the original estimation was off, or they're multi-project multi-tasking, or someone decided to add more features and not change the schedule.)
So if you're a project manager, consider what you want to call the end of scheduled development. If you want a Code Complete or a Code Freeze, make sure that's rolled-up task, consisting of individual tasks that include development, testing, and review. If you don't, you'll end up with Code Incomplete or Code Slush. “Code Complete” as a stand-alone task means the code won't be complete.