I would prefer a model where there is a highly developed suite of test code
(actually, I find it is often best if one begins with the tests first - but
sometimes that is not practical), unit tests, integration tests and
usability tests, and nothing gets checked in unless the code base plus the
new code not only compiles, but the developer can show that with his
implemented changes, the system still passes all tests. And note, his new
code must come with a test suite of its own, and must pass through a code
review before we accept that his tests are adequate and thus before he can
run the full test suite. With this model, it happens that new code stresses
existing code in initially unexpected ways, revealing previously undetected
bugs. But at the same time, it makes it less likely that new code will
introduce a significant number of new bugs when it is approved to be
commited to the codebase. And this means that while the new code that is
approved to be commited will have the same number of bugs per thousand lines
of code that most other programmers experience in their code, the number of
bugs per thousand lines of code can only decrease. And where the version
control software in place does not support a given detail of this model (and
note, this model can be made to work even with something as primitive as RCS
or CVS), we need a manual process to make it work. In my practice, no
member of my team commits anything until we know it works with everything
already in the repository - no exceptions. This means that sometimes a
programmer will work on an assigned task for days, or even a week, without
commiting changes to the repository.
I agree with except for the latest phrase. This is exactly what DVCS shines at, BUT you can commit regularly. Why is this important? To have small increments that helps bisecting for bugs. Of course, you don't commit to the main repository each time, of course, it has to be reviewed, of course it has to pass all the tests... but in addition, you get the history, and I was saved many times by this feature (and of course, it has to compile each time, because without this, you can't bisect ;)).
Cheers,
Matthieu