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