I do agree they do complement each other… to some extent. My point was rather that if you write a good code, keeping logical arguments in your head should be reduced to the minimum. To the point that only testing edge cases and a happy path in your mind should be sufficient.

To give a more concrete example: I have recently seen a very complicated piece of logic checking whether a subsequent code should be even invoked, but it was hidden in a debris of core logic and other verification. It easily could have been separated and rewritten as a series of early returns and this is what a precondition is. I’m sure someone who wrote the code had it in their mind but was not familiar enough with the early return technique to embed this in code. Had they been, their brain power could’ve been utilized more efficiently.