При работе со сложными алгоритмами в языках с поддержкой вложенных функций (таких как Python и D) я часто пишу огромные функции (потому что алгоритм сложный), но смягчаю это, используя вложенные функции для структурирования сложного кода. Огромные (более 100 строк) функции по-прежнему считаются злыми, даже если они хорошо структурированы внутри благодаря использованию вложенных функций?
Редактировать: Для тех из вас, кто не знаком с Python или D, вложенные функции в этих языках также разрешают доступ к внешней области функций. В D этот доступ допускает мутацию переменных во внешней области видимости. В Python разрешено только чтение. В D вы можете явно отключить доступ к внешней области во вложенной функции, объявив ее static
.
Ответы:
Всегда помните правило, функция делает одну вещь и делает это хорошо! Если вы можете сделать это, избегайте вложенных функций.
Это мешает читабельности и тестированию.
источник
Некоторые утверждают, что короткие функции могут быть более подвержены ошибкам, чем длинные функции .
Лично я обнаружил, что хорошо прокомментированный прямой код легче следовать (особенно если вы не тот, кто его изначально написал), чем когда он разбит на несколько функций, которые никогда не используются в других местах. Но это действительно зависит от ситуации.
Я думаю, что главный вывод состоит в том, что когда вы разделяете блок кода, вы обмениваете один вид сложности на другой. Где-то посередине, вероятно, есть сладкое пятно.
источник
В идеале вся функция должна просматриваться без прокрутки. Иногда это невозможно. Но если вы можете разбить его на части, это сделает чтение кода намного проще.
Я знаю, что как только я нажимаю Page Up / Down или перехожу к другому разделу кода, я могу вспомнить только 7 +/- 2 вещи с предыдущей страницы. И, к сожалению, некоторые из этих мест будут использоваться при чтении нового кода.
Мне всегда нравится думать о своей кратковременной памяти как о регистрах компьютера (CISC, а не RISC). Если у вас есть вся функция на той же странице, вы можете перейти в кеш, чтобы получить необходимую информацию из другого раздела программы. Если вся функция не помещается на странице, это было бы равносильно тому, чтобы всегда выталкивать любую память на диск после каждой операции.
источник
Зачем использовать вложенные функции, а не обычные внешние функции?
Даже если внешние функции используются когда-либо только в вашей, ранее большой функции, это все же делает весь беспорядок легче читаемым:
источник
В данный момент у меня нет книги передо мной (чтобы процитировать), но согласно Code Complete «сладость» для длины функции составляла около 25-50 строк кода согласно его исследованию.
Есть моменты, когда нормально иметь длинные функции:
Время, когда нельзя иметь длинные функции:
Суть в том, что ремонтопригодность должна быть одним из самых высоких приоритетов в вашем списке. Если другой разработчик не может взглянуть на ваш код и получить «суть» того, что код делает менее чем за 5 секунд, ваш код не предоставляет достаточно «метаданных», чтобы сказать, что он делает. Другие разработчики должны быть в состоянии сказать, что делает ваш класс, просто взглянув на браузер объектов в выбранной вами IDE вместо того, чтобы читать более 100 строк кода.
Меньшие функции имеют следующие преимущества:
Список можно продолжить .....
источник
Ответ - это зависит, однако вы, вероятно, должны превратить это в класс.
источник
Я не люблю большинство вложенных функций. Лямбды попадают в эту категорию, но обычно не отмечают меня, если они не имеют более 30-40 символов.
Основная причина в том, что она становится очень локально плотной функцией с внутренней семантической рекурсией, а это означает, что мне трудно обернуть свой мозг, и просто легче перенести некоторые вещи в вспомогательную функцию, которая не загромождает пространство кода ,
Я считаю, что функция должна делать свое дело. Делать другие вещи - это то, что делают другие функции. Так что, если у вас есть функция из 200 строк, которая делает свое дело, и все течет, это нормально.
источник
Это приемлемо? Это действительно вопрос, на который только вы можете ответить. Достигает ли функция того, что ей нужно? Это ремонтопригодно? Это «приемлемо» для других членов вашей команды? Если так, то это то, что действительно имеет значение.
Редактировать: я не видел вещь о вложенных функциях. Лично я бы их не использовал. Я бы использовал обычные функции вместо этого.
источник
Длинная «прямолинейная» функция может быть ясным способом указать длинную последовательность шагов, которые всегда происходят в определенной последовательности.
Однако, как уже упоминали другие, эта форма склонна иметь локальные участки сложности, в которых общий поток менее очевиден. Поместив эту локальную сложность во вложенную функцию (т. Е. Определенную в другом месте внутри длинной функции, возможно, сверху или снизу), можно восстановить ясность потока основной линии.
Второе важное соображение - это управление областью действия переменных, которые предназначены для использования только в локальном отрезке длинной функции. Требуется бдительность, чтобы избежать того, что переменная, которая была введена в одном разделе кода, невольно упоминается где-то еще (например, после циклов редактирования), так как ошибка такого рода не будет отображаться как ошибка компиляции или выполнения.
В некоторых языках эту проблему легко предотвратить: локальный фрагмент кода можно обернуть в свой собственный блок, например, с помощью "{...}", внутри которого любые вновь введенные переменные видны только этому блоку. В некоторых языках, таких как Python, эта функция отсутствует, и в этом случае локальные функции могут быть полезны для реализации областей меньшего масштаба.
источник
Нет, многостраничные функции нежелательны и не должны проходить проверку кода. Я тоже писал длинные функции, но после прочтения Рефакторинга Мартина Фаулера я остановился. Длинные функции сложно написать правильно, трудно понять и сложно протестировать. Я никогда не видел функцию даже из 50 строк, которую было бы проще понять и протестировать, если бы она была разбита на набор более мелких функций. В многостраничной функции почти наверняка есть целые классы, которые должны быть выделены. Трудно быть более конкретным. Возможно, вам следует опубликовать одну из ваших длинных функций в Code Review, и кто-то (может быть, я) может показать вам, как ее улучшить.
источник
Когда я программирую на python, мне нравится отступать после написания функции и спрашивать себя, соответствует ли она «Zen of Python» (введите «import this» в вашем интерпретаторе python):
Красиво лучше, чем безобразно.
Явное лучше, чем неявное.
Простое лучше, чем сложное.
Сложный лучше, чем сложный.
Квартира лучше, чем вложенная.
Разреженный лучше, чем плотный.
Читаемость имеет значение.
Особые случаи не достаточно особенные, чтобы нарушать правила.
Хотя практичность превосходит чистоту.
Ошибки никогда не должны проходить бесшумно.
Если явно не молчать.
Перед лицом двусмысленности откажитесь от соблазна гадать.
Должен быть один - и желательно только один - очевидный способ сделать это.
Хотя этот путь поначалу может быть неочевидным, если вы не голландец.
Сейчас лучше, чем никогда.
Хотя никогда не бывает лучше, чем правильнов настоящее время.
Если реализацию сложно объяснить, это плохая идея.
Если реализацию легко объяснить, это может быть хорошей идеей.
Пространства имен - одна из отличных идей - давайте сделаем больше!
источник
Поместите их в отдельный модуль.
Предполагая, что ваше решение не более раздуто, чем необходимость, у вас не слишком много вариантов. Вы уже разделили функции на разные подфункции, поэтому вопрос в том, где вы должны их поместить:
Теперь и вторая, и третья альтернативы в некотором смысле являются вложенными, но для некоторых программистов вторая альтернатива не кажется плохой. Если вы не исключаете второй вариант, я не вижу особых причин исключать третий.
источник