On Fri, Sep 10, 2021 at 06:48:42PM -0400, Juancarlo Añez wrote:
I agree that assertions can be and are abused.
And I'm not too interested in DBC, nor in preconditions, nor in contracts.
In your first post you said:
[quote] This is in the context of "Design by contrast" (DBC) as a useful companion to "Test-driven development" and other forms of external tests. [/quote]
I presume the "contrast" was a typo for contract.
I'd like to make it easy to assert invariants and postconditions
Invariants and postconditions **are** contracts. Both are part of DBC.
It seems very odd that you are taking only two thirds of DBC. Why do you think that preconditions are not important?
over critical pieces of code to guard against failures caused by:
- bugs in the design or the implementation
- third party software violating its contracts
- the environment
You just said you're not interested in contracts. Now you say you want to enforce third-party software's contracts.
The first item you give (bugs in design or implementation) is part of DBC.
The second is not something you can enforce. You don't know what, if any, contracts a third-party library may be enforcing internally. The only thing you can even *attempt* to enforce is the third-party external API, but you don't need anything more than a bare assert for that.
You can use assert as it is to validate your arguments that you pass to libraries:
assert isinstance(count, int) and count > 0 result = some_library.func(count)
so no change needed there. To verify that the third-party library is returning what it promises to return can also be done with assert:
assert result is not None and hasattr(result, 'spam')
Why target *assert*? Because invariants are clearer when the expected condition is what's asserted.
If all you want is to be able to flip the sense of a test without using `not`, then it sounds like you need an "unless" keyword:
unless condition: # block raise MyError(msg)
That avoids abusing assert for things that aren't assertions.
But adding a new keyword just so you don't have to write `not` seems like a high cost for a low benefit. Although now that we have soft keywords, the cost is somewhat less.
Why specify an ExceptionType? Although in theory an assertion should never fail, reality is that they will fail,
If your assertions are regularly failing in production, then either your application is full of bugs and you put it into production too soon, or you are misusing assert by using it for things which aren't assertions.
In any case, you don't need to raise different exception types in order to assess the failure. You need to know *where* the failure occurred.
and it's useful for outer layers of a software system to be able to assess the severity of a failure to know which actions are appropriate.
- preserve major state and HALT
- rollback and halt
The first three are what I would call "exit gracefully" (if possible, but if an error is so severe you can't exit gracefully, then all you can do is exit).
If an error can be resolved by retrying, then it is not an assertion that was violated. You cannot *assert* that (e.g.) a web server will respond with the expected amount of data, or that a user will input exactly 'Y' or 'N' at the prompt.