Разумные причины создания методов:
- Снижение сложности. В методе скрывается информация, о которой можно не думать при работе над другими частями программы.
- Документирование. Выделение фрагмента кода в удачно названный метод - один из лучших способов его документирования.
- Предотвращение дублирования кода.
- Сокрытие очередности действий
- Упрощение сложных логических проверок.
- Повышение быстродействия. Скрытый в методе неэффективный код можно оптимизировать независимо от остальной программы.
- Улучшение переносимости. Внутри метода можно скрыть особенности работы с конкретной платформой и технологией.
Не следует бояться создания простых методов в 2-3 строки. Во-первых такой код может повторяться десятки раз, во-вторых при дальнейших изменениях его размер может резко увеличиться.
Важнейшим принципом проектирования методов является связность - соответствие выполняемых в методе операций единой цели. Например связность метода Cosine() (косинус) крайне высока, у метода CosineAndTan() (косинус и тангенс) она гораздо хуже. Каждый метод должен выполнять только одну задачу - это функциональная связность, самая важная и эффективная.
Менее эффективные виды связности:
- Последовательная связность. Операции внутри метода выполняются в определенном порядке. Например сначала вычисляется возраст сотрудника по дате рождения, потом срок до ухода на пенсию по возрасту. Такой метод можно разделить на два функционально связных - методы вычисления возраста по дате рождения и метод вычисления срок ухода на пенсию по возрасту.
- Коммуникационная связность. Выполняемые в методе вычисления имеют общие данные. Так же может быть разбита на несколько методов.
- Временная связность - операции выполняются в один и тот же момент времени. Например метода Startup(), выполняющийся при загрузке программы. Такой метод можно превратить в контейнер для функционально связных методов - например чтение конфигурационного файла, инициализация вспомогательных файлов и вывод на экран первого окна.
Вредные виды связности, которые ведут к плохому коду и в большинстве случаев не должны использоваться:
- Процедурная связность. Операции выполняются в определенном порядке по независящим от них причинам и не имеют иной связи между собой.
- Логическая связность. Метод выполняет несколько не связанных между собой операций, делая выбор между ними по передаваемой внутрь метода метке в операторах вроде if или switch.
Такие методы стоит заменить набором разных методов. Единственный возможный вариант - сведение всего его кода к вызову других методов, диспечеру событий.
Правильные имена методов
- описывают все, что метод выполняет. Если имя получается слишком длинное и несуразное, например ComputeReportTotalsAndOpenOutputFile, переделайте плохой метод.
- не содержат невыразительных глаголов вроде HandleOutput() которые надо заменить на что-то вроде FormatAndPrintOutput()
- не должны отличаться только номерами вроде Part1() Part2()
- не ограничиваются по длине искусственными правилами. Главная задача имени - ясное и понятное описание сути метода, удовлетворяющее этой цели имя может иметь любую длину.
- при наличии возвращаемого значения (метод-функция)описывайте его в имени, например customer.Next(), pen.CurrentColor()
- для именования процедуры, не возвращающей значение, используйте выразительный глагол, дополненный именем объекта, например PrintDocument()
- следите за использованием антонимов, хороший пример - first/last, плохой - FileOpen()/_lclose()
- заключайте соглашения по именованию часто используемых операций, например в одном проекте не было соглашения по именования кода объекта, в результате получился следующий зоопарк:
employee.Id.Get()
dependent.GetId()
supervisor()
candidate.id()
Размер методов
Насчет размера методов существует множество различных мнений и исследований. Более-менее общее правило - стоит проявлять осторожность при создании методов более 200 строк, меньшие по размеру методы мало отличаются по количеству ошибок.
Параметры методов
- передавайте параметры в порядке "выходные значения, изменяемые значения, возвращаемые значения, переменные статуса/коды ошибок
- если несколько методов используют похожие параметры, передавайте их в согласованном порядке. Плохой пример: в C методы fprintf() и printf() отличаются только необходимостью передать в fprintf() файл в виде дополнительного первого аргумента. Методы puts() и fputs() имеют схожие отличия, но файл необходимо передать последним аргументом. Такие различия только ухудшают код.
- используйте все параметры, неиспользуемые параметры стоит убрать из интерфейса метода
- не используйте параметры в качестве рабочих переменных, вместо этого копируйте их значения в локальные переменные. В ходе дальнейших модификаций вам может понадобиться снова использовать входной параметр в какой-то из частей метода, если в его переменной будут содержаться измененные данные, вы получите трудновыявимую ошибку.
- документируйте предположения относительно параметров
- ограничивайте число параметров примерно 7, согласно психологическим исследованиям люди не могут следить за большим числом объектов одновременно
- для возвращаемых параметром проверяйте все возможные значения, который могут быть возвращены при различных вариантах выполнения кода