шаблоны проектирования — C ++ Использовать предварительные условия функций или классы обертки с инвариантами?

Я пишу множество функций, которые начинаются со многих предварительных условий, а затем я должен выяснить, как обрабатывать все недопустимые входные данные и писать для них тесты.

Обратите внимание, что кодовая база, в которой я работаю, не позволяет генерировать исключения, если это становится актуальным в этом вопросе.

Мне интересно, существует ли какой-либо шаблон проектирования C ++, в котором вместо предварительных условий входные аргументы передаются через классы-оболочки, которые гарантируют инварианты. Например, предположим, что я хочу, чтобы функция возвращала максимальное значение в векторе целых чисел. Обычно я бы сделал что-то вроде этого:

// 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);
}

который не может потерпеть неудачу и избавляется от ненужной проверки ввода.

Является ли этот шаблон дизайна хорошей идеей, есть ли лучший способ сделать это, и есть ли название для него?

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]