...методы — величайшее изобратение в области компьютерных наук. Методы облегчают чтение и понимание программ в большей степени, чем любая другая возможность языка программирования (с. 159)
- Самая важная причина — снижение сложности (без абстрагирующей силы методов сложные программы было бы невозможно охватить умом)
- Самая популярная причина — желание избежать дублирования кода
- Удачно названный метод формирует понятную промежуточную абстракцию, что облегчает чтение и понимание кода
- Небольшой и понятный метод можно легко переопределить, что поможет при работе с наследованием
- Сокрытие порядка выполнения действий
- Сокрытие операций на указателями
- Улучшение портируемости за счёт изолирования непортируемого кода в отдельных методах
- Упрощение сложных логический проверок за счёт сокрытия деталей проверки в методе с простым, описательным именем
- Методы позволяют выполнять оптимизацию кода в одном месте, повышая быстродействие всех фрагментов, которые его используют
Но методы используют и для простых операций. На практике технически простая операция может быть сложной для понимания, а метод с понятным именем решает эту проблему (например, метод convert_pixels_to_points()
при чтении кода будет понятнее, чем его содержимое, даже если это всего одна строка кода). К тому же простые операции имеют свойство усложняться со временем.
На уровне методов важнейшим принципом проектирования является стремление к функциональной связности (cohesion).
...цель в том, чтобы каждый метод эффективно решал одну задачу и больше ничего не делал (с. 164)
Существует несколько видов связности. Некоторые из них неприемлимы и требуют исправления.
Вид | Описание | Оценка | Лечение |
---|---|---|---|
Функциональная |
Метод выполняет одну и только одну операцию | 😆 | — |
Последовательная |
Метод содержит операции, которые выполняются в определённой порядке, и используют данные предыдущих этапов | 😃 | Разделить на несколько методов |
Коммуникационная |
Метод содержит операции, которые используют одни и те же данные, но больше никак друг с другом не связаны | 😃 | Разделить на несколько методов |
Временная |
Операции объединены в метод, потому что выполняются в один интервал времени | 😃 | Заменить операции на вызов отдельных методов |
Процедурная |
Операции объединены в метод, потому что выполняются друг за другом, но не связаны одной задачей или же решают её не полностью | 😞 | Вынести операции в отдельные методы; на их основе создать метод, который будет решать задачу целиком |
Логическая |
Метод содержит несколько операций, а выбор выполняемой операции происходит на основе условной логики | 😞 | Разделить на несколько методов |
Случайная |
Выполняемыми в методе операциями никак не связаны | 😡 | Спроектировать и реализовать новые методы с нуля |
Имя метода должно ясно описывать всё, что он делает (с. 167)
Есть несколько советов о том, как выбрать удачное имя для метода
Совет | Пример |
---|---|
Наименование метода = выразительный глагол + возвращаемый объект | order.calculateDeliveryTime() |
Опишите в имени метода все выходные данные и все побочные эффекты, а лучше вообще избегайте побочных эффектов | order.createAndNotifyCustomer() лучше, чем order.process() |
Избегайте невыразительных глаголов | order.sendNotificationEmail() лучше, чем order.performNotification() |
Если метод что-то возвращает (т.е. является функцией), учитывайте тип возвращаемого значения | order.getCustomer() лучше, чем order.customerProfileData() |
Дисциплинированно используйте антонимы для наименования методов с противоположной функциональностью | — |
Договоритесь о конвенции именования часто используемых операций | Единообразие лучше, чем order.getCustomer , cart.customer() , payment.customer.get() и так далее |
Не ограничивайте длину методов искуственно; лучше длинное, но точное наименование, чем короткое и бессмысленное | — |
В теоретических работах длину метода часто советуют ограничивать числом строк, помещающихся на экране монитора (с. 169)
- Многие методы в объектно-ориентированных программах будут короткими методами доступа
- Обычные методы могут занимать до 100-200 строк
- К методам, занимающим более 200 строк следует относиться с осторожностью
Интерфейсы между методами — один из основных источников ошибок (с. 170)
Вот несколько советов по их предотвращению.
- Всегда используйте все параметры класса
- Не используйте параметры как переменные внутри метода
- Передавайте переменные статуса или коды ошибки последними, потому что они являются второстепенными по отношению к главной цели метода
- Если вы предполагаете, что передаваемые в метод данные должны иметь определённые характеристики, сразу же документируйте эти предположения (пишите комментарии, не дожидаясь завершения работы)
- Ограничивайте число параметров метода примерно семью (см. магическое число семь плюс-минус два)
- Передавайте в метод те объекты или переменные, которые нужны для поддержания абстракции интерфейса
- Если абстракция метода подразумевает, что он ожидает несколько элементов данных, которые чисто случайно принадлежат одному объекту, передавайте эти элементы по отдельности
- Если абстракция метода подразумевает, что он работает с частью данных определённого объекта (т.е. объект важен для асбтракции формируемой методом), передавайте объект целиком, а не его отдельные элементы
- Используйте именованные параметры, чтобы не перепутать порядок агрументов при вызове метода
- Убедитесь, что тип фактических параметров соответсвует типу, указанному в значениях по умолчанию (строго типизированные языки защищают от этой ошибки на уровне предупреждений компилятора)
Методы могут быть представлены функциями и процедурами. Функции возвращают значение, а процедуры — нет (но во многих языках они синтаксически возвращают void
).
При использовании функций есть риск того, что она не вернёт нужное значение. Чтобы избежать этого, следует:
- Проработать все пути выполнения функции и проверить, что во всех случаях возвращается то, что нужно
- Инициализировать возвращаемое значение в начале функции значением по умолчанию
- Не возвращать ссылки или указатели на локальные данные