risorse | good unit tests
Questa parte (la dodicesima; qui la prima, qui la seconda, qui la terza, qui la quarta, qui la quinta, qui la sesta, qui la settima, qui l'ottava, qui la nona, qui la decima e qui l'undicesima) descrive un piccolo refactoring.
Analizzando il codice sorgente mi sono reso conto che la classe Expression, oltre a definire la strategia di logAndEvaluate, si occupa della gestione delle espressioni unarie. Conviene separare le due responsabilità introducendo una nuova classe, UnaryExpression:
// file gut.h // ... struct Expression { static std::string last; virtual ~Expression() { } virtual bool evaluate() const = 0; virtual std::string toString() const = 0;template <typename T> static bool logAndEvaluate(const T& value) { if (HasOperatorString<T>::value) Expression::last = StringRepr<T, HasOperatorString<T>::value>(value).str(); else Expression::last = gut::toString(static_cast<bool>(value)); return static_cast<bool>(value); }bool logAndEvaluate() { Expression::last = toString(); return evaluate(); } }; std::string Expression::last; template<typename T> class UnaryExpression : public Expression { protected: const T& value_; public: UnaryExpression(const T& value) : value_(value) { } virtual bool evaluate() const { return static_cast<bool>(value_); } virtual std::string toString() const { if (HasOperatorString<T>::value) return StringRepr<T, HasOperatorString<T>::value>(value_).str(); else return gut::toString(static_cast<bool>(value_)); } }; // ... template<typename T> class Term { // ... operator bool() const {return Expression::logAndEvaluate(lhs_);return UnaryExpression<T>(lhs_).logAndEvaluate(); } // ... };
Pagina modificata il 07/10/2014