我发现自己编写了许多以许多前提条件开头的函数,然后我必须弄清楚如何处理所有无效输入并为它们编写测试。
请注意,我工作的代码库不允许抛出异常,以防与此问题相关。
我想知道是否有任何C ++设计模式,而不是有前置条件,输入参数通过保证不变量的包装类传递。例如,假设我想要一个函数在int的向量中返回最大值。通常我会做这样的事情:
// Return value indicates failure.
int MaxValue(const std::vector<int>& vec, int* max_value) {
if (vec.empty()) {
return EXIT_FAILURE;
}
*max_value = vec[0];
for (int element : vec) {
if (element > *max_value) {
*max_value = element;
}
}
return EXIT_SUCCESS;
}
但我想知道是否有设计模式可以做这样的事情:
template <class T>
class NonEmptyVectorWrapper {
public:
static std::unique_ptr<NonEmptyVectorWrapper>
Create(const std::vector<T>& non_empty_vector) {
if (non_empty_vector.empty()) {
return std::unique_ptr<NonEmptyVectorWrapper>(nullptr);
}
return std::unique_ptr<NonEmptyVectorWrapper>(
new NonEmptyVectorWrapper(non_empty_vector));
}
const std::vector<T>& vector() const {
return non_empty_vector_;
}
private:
// Could implement move constructor/factory for efficiency.
NonEmptyVectorWrapper(const std::vector<T>& non_empty_vector)
: non_empty_vector_(non_empty_vector) {}
const std::vector<T> non_empty_vector_;
};
int MaxValue(const NonEmptyVectorWrapper<int>& vec_wrapper) {
const std::vector<int>& non_empty_vec = vec_wrapper.vector();
int max_value = non_empty_vec[0];
for (int element : non_empty_vec) {
if (element > max_value) {
max_value = element;
}
}
return max_value;
}
这里的主要功能是避免在函数中进行不必要的错误处理。一个更复杂的例子,这可能是有用的:
// Finds the value in maybe_empty_vec which is closest to integer n.
// Return value indicates failure.
int GetValueClosestToInt(
const std::vector<int>& maybe_empty_vec,
int n,
int* closest_val);
std::vector<int> vector = GetRandomNonEmptyVector();
for (int i = 0; i < 10000; i++) {
int closest_val;
int success = GetValueClosestToInt(vector, i, &closest_val);
if (success) {
std::cout << closest_val;
} else {
// This never happens but we should handle it.
}
}
每次浪费检查向量是否为空并检查失败,
// Returns the value in the wrapped vector closest to n.
int GetValueClosestToInt(
const NonEmptyVectorWrapper& non_empty_vector_wrapper,
int n);
std::unique_ptr<NonEmptyVectorWrapper> non_empty_vector_wrapper =
NonEmptyVectorWrapper::Create(GetRandomNonEmptyVector());
for (int i = 0; i < 10000; i++) {
std::cout << GetValueClosestToInt(*non_empty_vector_wrapper, i);
}
这不会失败并摆脱不必要的输入检查。
这种设计模式是不是一个好主意,是否有更好的方法来实现它,并且有一个名称吗?