«Сущности не должны умножаться сверх необходимости».
- Бритва Оккама
Код должен быть максимально простым. Ошибки любят скрывать между сложностями, потому что их трудно обнаружить там. Так что же делает код простым?
Небольшие единицы (файлы, функции, классы) - хорошая идея . Маленькие юниты легко понять, потому что вы должны понимать меньше вещей одновременно. Нормальные люди могут жонглировать только ~ 7 понятиями одновременно. Но размер измеряется не только в строках кода . Я могу написать как можно меньше кода, «играя в гольф» (выбирая короткие имена переменных, выбирая «умные» ярлыки, разбивая как можно больше кода на одной строке), но конечный результат не прост. Попытка понять такой код больше похожа на реверс-инжиниринг, чем на чтение.
Одним из способов сокращения функции является извлечение различных вспомогательных функций. Это может быть хорошей идеей, когда она извлекает отдельную часть сложности . В отдельности этой частью сложности намного проще управлять (и тестировать!), Чем когда она встроена в не связанную проблему.
Но у каждого вызова функции есть когнитивные издержки : мне нужно не просто понимать код в моем текущем фрагменте кода, я также должен понимать, как он взаимодействует с внешним кодом . Я думаю, будет справедливо сказать, что функция, которую вы извлекли, вносит в нее больше сложности, чем извлекает . Это то, что ваш начальник имел в виду под « маленькими функциями [это] боль», потому что это заставляет вас переходить к каждой маленькой функции, чтобы посмотреть, что делает код. »
Иногда длинные скучные функции могут быть невероятно просты для понимания, даже если они состоят из сотен строк. Это обычно происходит в коде инициализации и конфигурации, например, при создании графического интерфейса пользователя без редактора с перетаскиванием. Там нет отдельной части сложности, которую вы могли бы разумно извлечь. Но если форматирование читаемо и есть некоторые комментарии, действительно нетрудно проследить, что происходит.
Есть много других метрик сложности: количество переменных в области должно быть как можно меньше. Это не значит, что мы должны избегать переменных. Это означает, что мы должны ограничить каждую переменную до минимально возможной области, где это необходимо. Переменные также становятся проще, если мы никогда не изменим значение, которое они содержат.
Очень важной метрикой является цикломатическая сложность (сложность МакКейба). Он измеряет количество независимых путей через кусок кода. Это число растет экспоненциально с каждым условным условием. Каждое условие или цикл удваивает количество путей. Есть основания полагать, что оценка более 10 баллов слишком сложна. Это означает, что очень длинная функция, которая может иметь оценку 5, возможно, лучше, чем очень короткая и плотная функция с оценкой 25. Мы можем уменьшить сложность, выделив поток управления в отдельные функции.
Ваше условное выражение является примером части сложности, которую можно извлечь полностью:
function bigFatFunction(...) {
...
phoneNumber = getPhoneNumber(headers);
...
}
...
function getPhoneNumber(headers) {
return headers.resourceId ? headers.resourceId : DEV_PHONE_NUMBER;
}
Это все еще очень полезно. Я не уверен, что это существенно уменьшает сложность, потому что это условное не очень условно . В производстве он всегда будет идти по одному пути.
Сложность никогда не исчезнет. Это можно только перемешать. Много ли простых вещей проще, чем несколько больших? Это очень сильно зависит от обстоятельств. Обычно есть какая-то комбинация, которая кажется правильной. Поиск такого компромисса между различными факторами сложности требует интуиции и опыта, а также немного удачи.
Знание того, как писать очень маленькие функции и очень простые функции, является полезным навыком, потому что вы не можете сделать выбор, не зная альтернатив. Слепое следование правилам или лучшим практикам, не задумываясь о том, как они применимы к текущей ситуации, в лучшем случае приводит к средним результатам, в худшем - к культу грузового культа .
Вот где я не согласен с твоим боссом. Его аргументы не являются недействительными, но и книга о чистом кодексе неверна. Вероятно, лучше следовать указаниям вашего босса, но сам факт того, что вы думаете об этих проблемах, пытаетесь найти лучший путь, очень перспективен. По мере накопления опыта вам будет легче найти хороший факторинг для вашего кода.
(Примечание: этот ответ частично основан на мыслях из поста в блоге « Разумный код» на The Whiteboard Джимми Хоффа , который дает общее представление о том, что делает код простым.)