I would expect that dons is talking about a 1M codebase which already consists out of manageable pieces. It's only, that the pieces have to work together, talk to each other, know about each other (but not too much).
Sometimes software solves problems which provoke incidental complexity because of sheer size and my experience (albeit not above 500k) tells me that indeed, all bits help, also compiler enforced type checks. I would never bet my life on tests. As you write: "because the tests should catch the unanticipated parts", that's the point: tests never catch unanticipated parts by their very nature. Sometimes, by sheer luck, yes.
A compiler can only go so far. It'll happily compile:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("outfile", "w");
fclose(fp);
do_something(fp);
return 0;
}
int do_something(FILE *f)
{
fprintf(f, "This should work if you know what you're doing");
}
And then you are back to dynamic typing again, except that, when the integer you send points to something fprintf doesn't like you'll get a segfault instead of a doesNotUnderstand.
The compiler will happily compile that because C's standard library thinks it's a fantastic idea to just throw type-safety out the window. Even C libraries can protect themselves from this via strong typing instead of overloading what FILE* effectively means.
I think you mean contracts or defensive coding. If someone calls my code wrong they will have to think to test that particular case themselves, which is hard. Unless I've written contracts; then when it blows up they'll know what they did wrong.
The question we have to answer to properly understand what went wrong is where did the argument originate. If it's being generated inside function A that then calls function B with it, a test of A should fail when it calls B with the wrong argument. In any case, I would imagine the test coverage in the A-B system is lower than it should.
Sometimes software solves problems which provoke incidental complexity because of sheer size and my experience (albeit not above 500k) tells me that indeed, all bits help, also compiler enforced type checks. I would never bet my life on tests. As you write: "because the tests should catch the unanticipated parts", that's the point: tests never catch unanticipated parts by their very nature. Sometimes, by sheer luck, yes.