On Thu, Sep 09, 2021 at 12:02:13PM -0400, Juancarlo Añez wrote: > Steven, > > The purpose is to make it easier to make software more resilient.
Thank you but I understand the purpose of DBC and how it can be helpful for writing resilient software. If you search the archives, you will see that not only have Eiffel-style contracts been discussed before, but I am a great proponent of them. What I question is that allowing assert to raise non-assertions will lead to *more* resilient software rather than less. I know far too many people who insist on abusing assertions as a lazy way to validate caller- or user-supplied data, which is **not** a contract. Contracts apply only to calls between parts of your own application. Contracts do not apply to: - checking external data, which can be corrupt or invalid; - checking data provided by the end-user, who can never be trusted to keep to the contract; - checking input in library functions that may be called by other libraries or programs that are not a party to the contract; but I see too many people doing exactly that because it saves them a line of code. And because they are abusing assert, that means that their software is *less* resilient, because it will fail to perform those checks if the end-user runs it with assertions disabled. If `assert` can be used to raise *any* sort of exception, not just AssertionError, that will encourage that abuse and lead to less resilient software, not more. > IOW, my premise is that we should be using *_lots_* of assertions, > *_always_*, and that for that we need to make them easier to write, How can assertions be easier to write than they are now? assert condition You don't get any easier than that. That is the bare minimum needed for contract checking. > and easier to handle in the event of the unavoidable failures. If you believe that contract violations are *unavoidable* then you have misunderstood the purpose of DBC. Contracts apply between parts of your application. A contract violation is a *bug in your application* and so is completely avoidable. (Except in the sense that we are all imperfect and therefore all software contains bugs, nevertheless we can asymptopically approach the status of being free from bugs.) Contracts do not apply between libraries and their callers, or between software and end-users. That would be rude and hostile, and the opposite of resilient. *Data and input validation* errors are unavoidable: there will always be corrupt files, incorrect data, arguments passed in the wrong order, etc. But they are not contracts and should not be tested for using assert because we cannot ever safely disable that validation. The point of assertions and contracts is that you *don't catch them*. Assertions and contracts are hard requirements. If the contract is violated you have a bug in your software and the only safe thing to do is to log the error and gracefully exit. If you can catch and recover from an error, its not a contract violation. It's just using exceptions for flow control. # Exceptions as flow control. # LBYL if condition: do_this() else: do_that() # EAFP try: do_this() except ConditionFailure: do_that() > Seeking > unit-test coverage is not enough because unit tests don't run in production. If you do DBC correctly, contract assertions don't run in production either. It is up to the end-user whether the contracts run or not. (I believe that the Eiffel community tends to recommend that pre- condition testing remain in production, and that post-conditions, invariants and other contracts be disabled, but that's entirely under the control of the end-user.) One simple test for whether something can be a contract or not is this: Could it be safe for me to remove this test? Not necessarily today, but some day, in the future, when I am confident that the code is bug free. If your answer is Yes, then it could be a contract written with assert. But if the answer is No, or I Don't Know, then it cannot be a contract, and it should not be written using assert. -- Steve _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/76H7642S6DU4HDMMO5E44AASKVZG5FAD/ Code of Conduct: http://python.org/psf/codeofconduct/