Ich glaube, du verschmelzest, wenn Typen überprüft werden, wie sie überprüft werden. Die Typisierung von Runtime ist nicht unbedingt schwach.
Der Hauptvorteil von statischen Typen ist genau das, was Sie sagen: Sie sind erschöpfend. Sie können sicher sein, dass alle Call-Sites dem Typ entsprechen, indem Sie dem Compiler erlauben, das zu tun.
Die Hauptbeschränkung von statischen Typen besteht darin, dass sie in den Beschränkungen begrenzt sind, die sie ausdrücken können. Dies variiert je nach Sprache, wobei die meisten Sprachen relativ einfache Typsysteme (c, java) und andere mit extrem leistungsfähigen Typsystemen (haskell, cayenne) haben.
Aufgrund dieser Einschränkung sind Typen allein nicht ausreichend. Zum Beispiel sind in Java-Typen mehr oder weniger darauf beschränkt, dass Typnamen übereinstimmen. Dies bedeutet, dass die Bedeutung jeder Einschränkung, die Sie überprüfen möchten, in ein Benennungsschema irgendeiner Art kodiert werden muss, daher die Fülle von Umleitungen und Kesselblechen, die für Java-Code üblich sind. C++ ist ein wenig besser, weil Templates ein bisschen mehr Ausdruckskraft erlauben, aber nicht so weit kommen, wie man es mit abhängigen Typen machen kann. Ich bin mir nicht sicher, was die Nachteile der leistungsstärkeren Systeme sind, obwohl es eindeutig einige Leute geben muss, die sie in der Industrie verwenden.
Auch wenn Sie statische Eingabe verwenden, ist es wahrscheinlich nicht aussagekräftig genug, um alles zu überprüfen, was Ihnen wichtig ist. Sie müssen also auch Tests schreiben.Ob die statische Typisierung Ihnen mehr Aufwand erspart, als es im Textbaustein erfordert, ist eine Debatte, die seit Ewigkeiten tobt und von der ich glaube, dass sie keine einfache Antwort für alle Situationen hat.
Was Ihre zweite Frage:
Wie können wir wieder Faktor sicher in einer Runtime-typisierte Sprache?
Die Antwort ist Tests. Ihre Tests müssen alle wichtigen Fälle abdecken. Tools können Ihnen helfen zu messen, wie umfassend Ihre Tests sind. Coverage-Check-Tools zeigen an, ob Codezeilen von den Tests abgedeckt sind oder nicht. Test-Mutations-Tools (Jester, Heckle) können Sie wissen lassen, ob Ihre Tests logisch unvollständig sind. Acceptance Tests lassen Sie wissen, was Sie geschrieben haben, stimmt mit den Anforderungen überein, und schließlich gewährleisten Regressions- und Leistungstests, dass jede neue Version des Produkts die Qualität der letzten Version beibehält.
Eines der großen Dinge über das richtige Testen statt über aufwändige Typ-Umleitungen ist, dass das Debuggen viel einfacher wird. Beim Ausführen der Tests erhalten Sie bestimmte fehlgeschlagene Assertions innerhalb von Tests, die klar ausdrücken, was sie tun, anstatt stumpfe Compiler-Fehleranweisungen (denken Sie an C++ - Template-Fehler).
Egal, welche Tools Sie verwenden: Code zu schreiben, der Ihnen vertraut, erfordert Aufwand. Es wird wahrscheinlich erfordern, eine Menge Tests zu schreiben. Wenn die Strafe für Bugs sehr hoch ist, wie Luft- und Raumfahrt oder medizinische Steuerungssoftware, müssen Sie möglicherweise formale mathematische Methoden verwenden, um das Verhalten Ihrer Software zu beweisen, was eine solche Entwicklung extrem teuer macht.
Sie würden immer noch refactor, Sie würden nur Unit-Tests als Ersatz für den IDE/Compiler verwenden. Es ist wirklich nicht so schlimm, wenn man sich einmal daran gewöhnt hat. –