Это мини-серия статей по написанию поддерживаемого объектно-ориентированного кода без лишней нервотрепки.
Предыдущие части: Часть 1, Часть 2, Часть 3, Часть 4 и Часть 5.
Элементарные функции
Должен признать: очень долгое время я и не подозревал, что написание функции требует такой кропотливой умственной работы. Для меня создание функции означало написание блока повторно используемого кода. Это простая идея, и я ей активно пользуюсь: функция == повторно используемый код
.
Я ничего не знал о структуре, длине или значении. Со временем, по мере разрастания проекта, код превращался в длинные сценарии. Появился даже шаблон для длинных функций с пластами кода и комментариев.
Длинные функции
Длинные функции обходятся очень дорого:
- их трудно прочесть и запомнить;
- сложности в тестировании и отладке;
- они скрывают предметную область;
- возникают трудности с повторным использованием, появляется дублирование;
- большая вероятность их изменения;
- нельзя оптимизировать;
- устаревание комментариев.
Изначально длинные функции обладают крайне низкой связностью, высокой связанностью и знают о системе слишком многое. Это идет вразрез с основами разработки ПО, согласно которым компоненты должны обладать высокой связностью, но низкой связанностью.
Принцип единого уровня абстракций (SLAP)
Крайне трудно отнести функцию к длинным только при подсчете строк. Считается ли длинной функция в 50 строк? А в 25 или 10? Насколько маленькой должна быть небольшая функция? Вот здесь и пригодится принцип единого уровня абстракций (SLAP).
Код внутри определенного сегмента/блока должен находиться на едином уровне абстракции.
Поэтому вопрос не в том, насколько длинная эта функция, а в том, какой у нее уровень абстракции. В функции не должны сочетаться разные уровни абстракции. Например, функция для проверки формы не должна выполнять вызовы ввода/вывода.
Как в эмпирическом правиле:
Функция должна выполнять что-то одно. И делать это правильно. — Роберт Мартин
Функция, выполняющая свыше одного действия, обладает теми же недочетами, что и длинная функция. Это утверждение становится еще правдивее по мере тестирования кода. Куда проще проверить функцию, выполняющую что-то одно. Таким образом не придется беспокоиться обо всех сложных перестановках и сочетаниях.
Составной метод
Довольно часто комментарии, поясняющие блоки кода, становятся кандидатами для извлечения функций.
При многократном использовании метода Extract, начальный метод становится составным. Он состоит из логических шагов, которые читаются также, как мы общаемся, и скрывают детали реализации.
Извлекайте, пока есть что извлекать. Извлекайте, пока можете — Роберт С. Мартин
Коротко о главном
Как однажды сказал Кент Бек, разделяйте программу на функции, которые выполняют конкретные задачи. Все операции внутри функции поддерживайте на едином уровне абстракции. Так вы неизменно получите программу с множеством небольших функций в пару строк кода.
Перевод статьи Arun Sasidharan: Object Oriented Tricks: #6 SLAP your functions