digitalmars.D.learn - Suggestions how to use contracts
- Aarti_pl (27/27) Aug 30 2007 Hello!
- Deewiant (31/52) Aug 30 2007 I think the key point is that it depends on the user, which means it sho...
- =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= (5/40) Aug 30 2007 Preconditions are a conceptual contract that are set up for other parts ...
Hello! I have a difficulty with defining strict boundary between preconditions/postconditions and regular errors throwing by function. Can you share your strategies? How to divide checks in proper way, remembering that preconditions and postconditions are stripped from code in release mode. Example: class Evaluator { public: int evaluate(char[] expression) in { assert(expression !=""); assert(m_active); } body { } private: bool m_active; } Function evaluate can be called only when m_active is true. Should this condition be checked from preconditions block or from body block with if (!m_active) throw new Exception("Evaluator is not active."); "m_active" depends on some other logic, either set by user or by other classes. BR Marcin Kuszczak (Aarti_pl)
Aug 30 2007
Aarti_pl wrote:Example: class Evaluator { public: int evaluate(char[] expression) in { assert(expression !=""); assert(m_active); } body { } private: bool m_active; } Function evaluate can be called only when m_active is true. Should this condition be checked from preconditions block or from body block with if (!m_active) throw new Exception("Evaluator is not active."); "m_active" depends on some other logic, either set by user or by other classes.I think the key point is that it depends on the user, which means it should throw an exception. Contracts should be used only for internal checks, making sure that your functions do what they should do: float absolute_value(float x) in { assert (!isnan(x)); } out (result) { assert (result <= 0); } body { return x < 0 ? -x : x; } Or that your objects' states aren't corrupt: class Array { int* data; int length; int reserved_size; invariant { assert (length <= reserved_size); } } Contracts assert (forgive the pun) that your program doesn't mess itself up. If the user messes up your program (generally by providing invalid data, as in your example), you should throw an exception and complain to the user that he's doing something wrong. That's my view, anyhow. Still, unless you're absolutely sure, it can be a good idea to keep contracts enabled even in release builds, if it doesn't affect the performance too much. -- Remove ".doesnotlike.spam" from the mail address.
Aug 30 2007
Preconditions are a conceptual contract that are set up for other parts of the system to obey. If you can't assert the condition, well then it simply shouldn't be a one. In your example, the m_active check should not be a precondition if you can't rely upon it always being true upon invocation. Regards Hans-Eric Grönlund http://www.hans-eric.com Aarti_pl Wrote:Hello! I have a difficulty with defining strict boundary between preconditions/postconditions and regular errors throwing by function. Can you share your strategies? How to divide checks in proper way, remembering that preconditions and postconditions are stripped from code in release mode. Example: class Evaluator { public: int evaluate(char[] expression) in { assert(expression !=""); assert(m_active); } body { } private: bool m_active; } Function evaluate can be called only when m_active is true. Should this condition be checked from preconditions block or from body block with if (!m_active) throw new Exception("Evaluator is not active."); "m_active" depends on some other logic, either set by user or by other classes. BR Marcin Kuszczak (Aarti_pl)
Aug 30 2007