One additional aspect of the philosophy, which can probably shake out of “Type enforce everything?”, that I (and others I’ve interacted with) adhere to is “compiler-oriented programming”. In Haskell, that involves writing type signatures first, and building the program down from there, relying on ghc to let me know when I did something wrong. With Rust I take my best guess at the semantics and let the compiler/rust-analyzer tell me when I missed something. I find this often to strike a great balance between a test-frequently approach and one that puts most of the design work upfront and reserves actual coding until later.
One additional aspect of the philosophy, which can probably shake out of “Type enforce everything?”, that I (and others I’ve interacted with) adhere to is “compiler-oriented programming”. In Haskell, that involves writing type signatures first, and building the program down from there, relying on
ghc
to let me know when I did something wrong. With Rust I take my best guess at the semantics and let the compiler/rust-analyzer
tell me when I missed something. I find this often to strike a great balance between a test-frequently approach and one that puts most of the design work upfront and reserves actual coding until later.