260 likes | 403 Views
Static modeling (& lifetime). Using types to test, document and reduce system complexity . Welcome. This talk/debate. Static modeling Lifetime given time Interrupt at any time!. Safety nets. Design/code reviews, pair programming Compiler Static modeling Unit tests/module tests
E N D
Static modeling (& lifetime) Using types to test, document and reduce system complexity
This talk/debate • Static modeling • Lifetime given time • Interrupt at any time!
Safety nets • Design/code reviews, pair programming • Compiler • Static modeling • Unit tests/module tests • Pipeline tests • Developer testing • Continuos integration • Static analysis tools (PCLint etc) • Dynamic analysis tools (Boundschecker, valgrind, etc) • QA testing • Design by contract • Assertions Bold = expressed in code
Fail fast • Minimize turn around time – minimize waste • Bug found => ”Possible to catch earlier?” • Review => ”Possible to catch earlier?”
Failing fast in C++ Build time Code generation Macro expansion Template instantiation Translation unit compilation Linking Installation/configuration Run time Load time Static initialization Bootstrapping/Initialization code Level load ... Specific/rare situations
Static modeling • Model invariants and tests with (static) types • Either compile time or instantiation time int x=-10; bounded<int, -1, 99999> i(x); quantity<speed> v = 1*meter/second; quantity<time> t = 2.0*minute; quantity<length> l = v/t;
Value of static modeling • Type up ASAP - fail fast • Documentation • Reduces complexity / state space
Code based tests Static modeling, assertions, design by contract, automated test hooks, unit tests etc. - Add ”weight” when prototyping + ”Easy” to add to existing/legacy code
How to reduce the state space • Init/set/modify -> constructor/factory • Split objects into smaller pieces • Lock down dynamics ASAP
Demarshalling • Type up immediately
Indices • Indices only needed when de-/serializing • Look up immediately, pass around instance
Use typed ids struct foo_id { int id; }; bool operator==(...);
Distuinguish invalid ids by type enum error {err1, err2}; class result { bool has_id(); const /// @pre valid() foo_id get_id() const; /// @pre !valid() error get_error() const; private: int data; }; result get_id(...); // Using boost boost::variant<error, foo_id> get_id();
Optional optional<X> find_closest_x(); void do_stuff(const X& x); • Isolate inited/not inited state • Clear semantics, all-or-nothing bool find_closest_x(X& x);
Right/left hand system Either compile time, runtime or combined Better granularity than math asserts on/off
RAII • new/delete • aquire/unaquire • connect/disconnect • lock/unlock • subscribe/unsubscribe • register/unregister • open/close Need to match call pairs AND know if an object is initialized or not
RAII example void foo(int x, int y); signal<void(int x, int y)> sig; signal_connection con(sig, foo);
Side note: RAII pillars • Exceptions • Deterministic destruction
Static modeling and lifetime • More work in constructor/destructor • Object lifetime becomes very important
Lifetime primitives • scoped_ptr (not copyable) • shared_ptr • weak_ptr • move_ptr (not copyable) • reference (not assignable)
Interfaceless objects /// @param foo is guaranteed to outlive /// return value move_ptr<void> create_stuff(const function<void()>& onBar, shared_ptr<GuiFactories> gui, const SomeFacade& foo, move_ptr<const ResourceX> x);
Summary • Static modeling pros: Fails fast, documentation, minimizes total logic • Static modeling increasingly important in longer and larger projects • Static modeling increases need of clear lifetime semantics
Static modeling vs. DbC Catch errors that must be checked at runtime by typing up or DbC/assertions? • Is the invariant local? • Duplicate preconditions => time to type up! • S.M. only applicable to single variables
Opposite of static modeling class message_channel { void send(const string& key, const string& value); void listen(const string& key, listener& l) const; }; Dynamic modeling good for prototyping/iterating Optimal: Lock down invariants in code by typing up incrementally. No major language supports this well.
Don’t get lured by ”power” • Dynamic components are very powerful but can also be abused • Specialized, less powerful = easy to understand and test, smaller state space • Think reflection, introspection, tuple spaces