reading note for:
CppNow 2015 - Details Matter Alisdair Meredith BloombergLP
Documentation
- Documentation is a Contract
- What Happens if a Contract is Violated?
- Undefined behavior?
- throw an exception?
- terminate the program?
- log and return?
- Ultimately, the library author chooses how to support their
customers
- *Personal preference: use assertions with customizable
handler function
---------
Narrow vs. Wide Contract:
Reference : [Defensive Programming]
- A wide contract has no preconditions, and so accepts
all input
- A narrow contract is one with any preconditions, that the
user is responsible for validating before making a call
- Such validation may be working with known inputs
rather than strictly writing checking code before each call
- Often, pre-conditions bubble up through layers of contracts
Narrow vs. noexcept:
- Design rule for std library specifications
- *noexcept only on wide contracts
- conditional noexcept only when noexcept is vital, e.g., move or swap
- Implementations have freedom to strengthen specification
- and always have, since 1998 standard
- Preserves implementors ability to respond to out-ofcontract calls
Is Narrow or Wide Better?
- Narrower contracts are often easier to implement
- Wider contracts are often easier to use
- Unless they result in a larger set of failure
post-conditions to test
- Exercise engineering judgement
----------
Avoid Breaking Changes
- If your next release is not compatible with the previous releases,
users need to audit their whole code base before they can safely update
- If you must break something, prefer a breakage that is loud and clear,
so is found easily and early
- API breakage - fails to compile
- ABI breakage - fails to link
- Silent behavior change - end users report bugs, oops!
- behavior change is undefined behavior - all bets are off
----------
C++11 Memory Model
- Making concurrency a well specified concern for
the language introduced some compatibility concerns
- Some compiler optimizations became illegal
- basic_string banned CoW, enabled short string
- ‘begin’ no longer invalidates iterators
- ‘swap’ can now invalidate iterators
----------
Enriching Exceptions
- Potentially unsafe idiom from C++11 onwards
- catch(Type& exception), update the exception object
- *C++11: Same exception object can unwind in several
threads in parallel
- *Modifications are potential race conditions
- *Preferred idiom: always catch by const &, use
nested_exception or similar to throw an enriched
exception if necessary
http://en.cppreference.com/w/cpp/error/nested_exception
http://en.cppreference.com/w/cpp/error/rethrow_if_nested
----------
Racing Exceptions
- If we control whole code path, we know whether we risk joining the
thread that might throw - low risk (code changes under maintenance)
- If we call user code, then we have no control over which exceptions
might throw
- function pointer
- virtual function call
- template specialization
- user function found via ADL
- Can limit damage by writing a contract that disallows exceptions from
other threads - but any bugs from violations will be subtle.
----------
Guidelines:
- Document contracts clearly; they define your library
- Testing will reveal incomplete contracts as well
as broken implementations
- It is generally easier to fix an implementation
than a contract on a live system
- Exception classes should have no throw copies
e.g., std exceptions may be immutable ref-counted strings
- Class templates frequently store data in tuples
- Beware of (unexpected) ADL
- Learn the safe idioms, especially for generic code
- T var{}; // default a value this way
T var1(var2); // copy an object this way, (i.e for explicit constructor)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.