Pull to refresh

Длина функции

Reading time2 min
Views20K
Original author: Martin Fowler


На протяжении своей карьеры я слышал множество аргументов о длине функции. Более глубокий вопрос — когда код нужно выносить в отдельную функцию? Иногда рекомендации основаны на размере, например, функция должна помещаться на экране. Другие основаны на повторном использовании — любой код, используемый больше одного раза, должен быть вынесен в отдельную функцию. Но если код используется лишь один раз, то можно его оставить на месте. Мне кажется, что большим смыслом обладает аргумент о разделении намерения и реализации. Если нужно потратить время на поиски фрагмента кода чтобы понять, что он делает, то нужно вынести его в функцию и дать ей такое имя, которое отвечает на вопрос "что". Тогда в следующий раз смысл функции сразу будет очевидным, и в большинстве случаев вас не будет волновать то, как функция выполняет свою работу. Иными словами — что происходит в теле функции.


Когда я стал применять такой принцип, я развил в себе привычку писать очень маленькие функции — обычно не больше нескольких строк. Любая функция длиннее шести строк уже попахивает. Вполне обычное дело для меня — иметь функцию с одной строчкой кода. Кент Бек показал мне когда-то пример из оригинальной системы Smalltalk, и это помогло мне по-настоящему понять, что размер — это не важно. Smalltalk в те годы работал на черно-белых машинах. Если нужно было подсветить текст или графику, то приходилось реверсировать видео. Класс в Smalltalk, отвечающий за графику, содержал метод 'highlight', и в его реализации была лишь одна строка — вызов метода 'reverse'. Название метода было длиннее реализации, но это не имело значения, потому что между намерением и реализацией этого кода — большое расстояние.


Некоторые люди волнуются по поводу коротких функций, потому что их заботит влияние вызовов на производительность. Когда я был молод, это иногда имело значение, но сегодня это редкость. Оптимизирующие компиляторы часто работают лучше с короткими функциями, потому что их легче кэшировать. Как обычно, в оптимизации производительности имеют смысл в первую очередь рекомендации общего характера. Иногда правильное решение это вернуть код из функции обратно в прежнее место. Но зачастую наличие маленьких функций позволяет найти другие способы оптимизации. Я помню, когда люди были против наличия метода isEmpty для списков. Стандартным способом было aList.length == 0. Но здесь как раз тот случай, когда название функции указывает на намерение, и это может помочь с производительностью если существует более быстрый способ определения пустоты коллекции, нежели проверкой длины.


Маленькие функции вроде этой работают только если названия достаточно хороши, так что нужно уделять внимание этому. Со временем ваш навык будет улучшаться, и такой подход может сильно повышать само-документированность кода. Функции более высокого уровня могут читаться как история, и читатель выбирает, в какие функции углубиться если нужно узнать подробности.

Tags:
Hubs:
+29
Comments46

Articles