Инкапсулируйте запутанные конструкции, а не разбрасывайте их по коду
Причина
Запутанный код с большей вероятностью скрывает ошибки и сложнее в написании. Хороший интерфейс проще и безопаснее в использовании. Запутанный низкоуровневый код порождает ещё больше такого кода.
Пример
int sz = 100;
int* p = (int*) malloc(sizeof(int) * sz);
int count = 0;
// ...
for (;;) {
// ... читаем int в x, выходим из цикла при конце файла ...
// ... проверяем, что x допустим ...
if (count == sz)
p = (int*) realloc(p, sizeof(int) * sz * 2);
p[count++] = x;
// ...
}
Это низкоуровневый, многословный и подверженный ошибкам код. Например, мы «забыли» проверить исчерпание памяти и присвоить новое значение sz. Вместо этого мы могли бы использовать vector:
vector<int> v;
v.reserve(100);
// ...
for (int x; cin >> x; ) {
// ... проверяем, что x допустим ...
v.push_back(x);
}
Примечание
Стандартная библиотека и GSL являются примерами этой философии. Например, вместо работы с массивами, объединениями, приведениями, хитрыми проблемами времени жизни, gsl::owner и т.д., необходимыми для реализации ключевых абстракций, таких как vector, span, lock_guard и future, мы используем библиотеки, спроектированные и реализованные людьми с большим временем и опытом, чем обычно у нас есть. Аналогично, мы можем и должны проектировать и реализовывать более специализированные библиотеки, а не оставлять пользователям (часто самим себе) трудную задачу раз за разом правильно писать низкоуровневый код. Это вариант принципа подмножества надмножества, лежащего в основе этих руководящих принципов.
Контроль
- Искать «запутанный код», такой как сложные манипуляции с указателями и приведения вне реализации абстракций.