Pull to refresh

Comments 47

Конечно наверное глупо спорить с корифеями и так далее, но вот правило про «5 строк кода на метод» вызывает у меня смешанные чувства. Если брать пример из статьи, то что бы понять, что делает метод, который будет иметь еще 5-10 вложенных методов по 5 строк, то прийдется довольно долго переходить туда-сюда. А особенно с первым правилом про 100 строк на класс (с которым я больше согласен) это может превратиться в некий пазл, а именно, что бы исследовать метод прийдеться вооружиться бумажкой и ручкой и банально выписать все уровни вложенности, ибо держать в голове столько отвлетвлений проблематично.
Так же это приведет к образованию 100500 методов, использующихся ровно 1 раз, ровно в 1 месте и нигде больше.
если название этого метода как нельзя лучше отражает то что он делает, то это просто замечательно
Помимо смыслового названия для метода есть и ряд других требований. Например, если довести ситуацию до абсурда, то крайне неприятны ситуации когда:

* метод А может быть вызван только в определенном состоянии класса (а проверку состояния не проводит ибо 5 строк);
* метод Б может быть вызван только после метода А, и не предназначен для самостоятельной жизни (ибо 5 строк);
* метод В ожидает, что метод Г, вызванный перед ним, был успешен;
* и так далее.

В итоге это создает цепочки и клубки непрозрачных и непонятных взаимосвязей методов, распутать которые становится сложней чем прочитать метод в (о ужас!) 12 строк кода.
Согласен. А еще представьте, у вас вышло 105 строк в классе и, чтобы выйти из положения, вы применили композицию или, скажем, вынесли интерфейс,- не важно, и теперь у вас 2 класса: 100 и 5 строк, причем этот 5-строчный класс, возможно, пролежит всю жизнь никому не нужный, отнимая лишние миллисекунды при загрузке… Настоящее бездумное программирование!
Миллисекунды при загрузке учитывать — вот что точно бездумное программирование.

Но 5 строк на метод — сильно зависит от предметной области. Все-таки строк 20 реальней. Особого смысла уменьшать именно в 5 нет, это только усложнит читаемость кода, а это один из важнейших параметров.

1 объект в контроллере — идея понятна, в некоторых фреймворках применяется, но добавляет уровень абстрации, используемый в одной связке, и особого практического смысла не несет. Фактически получается протокол контроллер-представление, только он явный не особо и нужен. Но, опять же, зависит от проекта.

100 строк на класс и 4 аргумента — примерно нормально. Если аргументов больше, то большая вероятность, что нужно вводить новую модель данных. Исключение — собственно методы вывода, где куча параметров и там нормально.
Миллисекунды при загрузке учитывать — вот что точно бездумное программирование.

Скажем, у вас бюджетное нагруженное веб-приложение, написанное на одном из популярных фреймворков. Средняя загрузка страницы включает 20 обращений к веб-серверу,- допустим часть из них, это динамический контент, все остальное отдает реверс-прокси в виде статики, либо из кэша. При каждом запросе динамического контента загружается автозагрузчик классов, несколько десятков классов, конфиги, плюс, возможно, classmap generator с описанием наймспейсов какого-нибудь легаси,- итого весь бутстрап занимает 50 миллисекунд. Даже если все оптимизировано и закэшировано, запросы к бд только при необходимости, вся графика сжата и сгруппирована в спрайты, все javascript и css файлы оптимально сгруппированы,- все равно каждая бутстрап-инициализация это ~0.05 секунд потерянного времени. Помножьте на число запросов для каждой страницы (к примеру 5), затем на количество запрашиваемых страниц в минуту (допустим 60) 0.05 * 5 * 60 = 15 секунд в минуту только на бутстрап. Прибавьте отдачу статики, медленные запросы и еще с десяток факторов.

Другой пример,- javascript фреймворк, скажем Extjs,- загрузка каждого лишнего класса,- лишнее обращение к веб-серверу,- это уже десятки миллисекунд на каждый класс.

Действительно ли «Миллисекунды при загрузке учитывать — вот что точно бездумное программирование»?
Ну вам же нужно миллисекунды экономить?
Боюсь, что тогда я потеряю десятки часов своего личного процессорного времени)
Звучит безумно, но многое понятно из того, что боты — это команда рубистов, а значит это:
— разработка через тестирование;
— применение различных ООП практик;
— выразительный и компактный синтаксис;
— DSL.

Учитывая эти вещи — 5 строк на метод не такое безумство как кажется. Вот к примеру, методика TDD. Вы пишете сначала тест. Чтобы его написать, вы должны подумать, что будет делать к примеру метод. Пока вы будете думать, вы оцените его потенциальную сложность, и уже на этом этапе попробуете его упростить так, чтобы его можно было очень просто протестировать.

То есть, сами применяемые методологии подталкивают к таким ограничениям.
Весьма спорные правила. Маленькие классы и методы — это конечно же классика хорошего кода, но искусственные ограничения в 100 и 5 строк больше похожи на усложнение своей жизни там, где это не нужно.
Правило «Инстанциировать максимум один объект в контроллере» мне понравилось. Сами себе создали проблему, сами решили. Молодцы :)
Фреймворк предоставляет им готовые хелперы ‘link_to’ и ‘form_for’ с определенным списком аргументов. Опять же, зачем себе создавать искусственные проблемы и бороться с этим?
Надо бороться за легкое сопровождение и понимание кода, а не за количество строк.
Согласен полностью. Главное читаемость и легкость в понимании, а не искусственные ограничения. Пусть автор напишет qsort в 5 строк или любой не тривиальный алгоритм обработки данных. Да, примитивная бизнес логика ляжет в 5 строк, но не более. По мне так решающим фактором, когда что-то надо разбивать на мелкие составляющие — является повторение кода или повторение логики. В первом случае общие части выносятся в методы. Во втором можно попробовать перенести общую логику родительскому классу.
У меня возник вопрос «Кто все эти ребята?». Введение искусственных ограничений действительно способно повысить эффективность работы. Но, копирование подходов у малоизвестной команды, на мой взгляд, сомнительное занятие.
Не понял чем elseif не угодил. Да и вообще hardcoded значения всегда плохо, это касается и кода и головы, хардкодить себе в голову «5 строк кода на метод» однозначная глупость… почему не 4 или 6?
hardcoded значения всегда плохо, это касается и кода и головы
Оу, вы очень удачно сформулировали то, что так давно хотелось сказать и не только тут!
UFO landed and left these words here
def myfunc
  ..
  ..
  ..
  ..
  myfunc2
end

def myfunc2
  ..
  ..
  ..
  ..
  myfunc3
end

def myfunc3
  ..
  ..

Вполне хорошие правила не только для руби. Но опять же, зачем усложнять?
насчет 100/5 строк тоже не очень хорошо — не для всех подходит,
но клепание однострочников в методе вида command --par1 --par2--par3 --myverylongpar | command --par1 --par2--par3 --myverylongpar…
затрудняют читабельность.

В ообще разумные идеи, да.
Я вот стараюсь делать так чтобы методы умещались в один экран текста, но в Powershell/bash некоторые функции у меня занимали больше экрана текста по высоте, хотя в C# у меня достаточно короткие и легко читаемые методы
Не от языка это зависит, а от задач. Захотеть можно и в Lisp писать с правилом 100/5. Но задачи, особенно сильно связанные с математикой, так только сам себе жизнь усложнишь. При желании можно с таким правилом и AES алгоритм реализовать, но выглядеть это будет как спагетти.
Мое правило для Sandi Metz: не навязывай другим правил, если сам не хочешь, чтобы и тебе что-то навязали.
А вот совет пригодится, можно рассмотреть для общего расширения кругозора.
UFO landed and left these words here
Зря Вы так категорично.
Работа в команде приводит к правилам оформления кода, может не таким
У Васи в методе много строк и дома экран в 27", и он метод нормально читает, а у Пети в офисе 19-22" и чтобы осознать метод от Васи надо экран туда сюда скроллить по 10 раз в минуту.
На самом деле вопрос на кого ориентированы эти правила. Если Sandi Metz набирает в разработчики в основном юниоров и индусов и имеет большую текучесть кадров, то жесткое следование таким правилам помогает поддерживать/рефакторить код написанный другими кодерами, которые уже «выучились» и ушли. Так же жесткие правила для юниоров являются более желательными, так как сам юниор не всегда способен решить нужно/можно ли в данном конкретном случае сделать длинный метод или можно ли сделать длинный case switch (который в данном случае вообще никак не влезает в правила). В долгоиграющей небольшой команде, где все друг друга знают могут быть другие правила.
И как уместить case с двумя вариантами в метод?

case a
when 1..5
  puts "It's between 1 and 5"
when 6
  puts "It's 6"
end
«case» получается вне закона. Только ламповые «if» и «else». В «else» вызов другой функции, которая делает дополнительные проверки, и по необходимости вызывает ещё функцию…
Я на это и намекаю. Какое-то бредовое правило, по моему.
Я всецело за короткие методы и классы, но не до такой же степени :)
Используйте карты вариантов, например?

VARIANTS.detect { |v| v.value === value }.do_something_special


или сделайте метод 1.something_special, который для 1..5 вернет одно, а для 6 другое.

И т.д.
Да, но зачем эти проблемы?)
Предлагается использовать полиморфизм, чтобы избавиться от сложных условий.

Conditional code clutters methods, makes extraction and reuse harder, and can lead to leaky concerns. Object-oriented languages like Ruby allow developers to avoid conditionals using polymorphism. Rather than using if/else or case/when to create a conditional path for each possible situation, you can implement a method differently in different classes, adding (or reusing) a class for each situation.
— Ruby Science
чепуха!
код тут не причём.
код надо писать используя собственный разум, а не коллективный.
конечно, методы должны быть минималистичными, классы короткими и как можно меньше инстансов.
держать всё под контролем, под своим контролем!

и нечего пытаться внедрить 10 заповедей в мир программинга!
если это прокатит до охоты на ведьм рукой подать…

Руби сообщество и так серъёзно страдает от рельсовых конвенций.
И если внедрить ещё и религию то точно начнут сжигать Коперников и ему подобных.
Это от каких таких конвенций Rails страдает Ruby?
Очевидно, в любом методе пара-тройка строк является незначащей по-умолчанию (имя+ открытие+ закрытие + возврат значения). Не многовато ли на пять строк, несущих логику?
1. Берём в целом разумные, выработанные поколениями программистов _рекомендации_
2. Называем их правилами, применяем выбранные от фонаря жёсткие ограничения на размер/количество методов.
3. Усугубляем это дело прогрессирующим ООП головного мозга.
4. Навязываем.
Вот такую сигнатуру всегда вспоминаю: - (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers. Тут, конечно, везде своя специфика. Для Objective-C, например, данные правила будут очень затруднительны — особенно про строчки.
ну его задепрекейтили и разделили на два теперь )
>> 100-строковые классы
С этим ограничением я готов согласится, хотя большее строк для класса тоже не криминал, в разумных пределах. Разбивать спеки по фичам, возможно, хорошая идея, нужно попробовать.

>> 5 строк кода на метод
Полный и безоговорочный маразм! Абсолютно идиотское ограничение, заставляющее размазывать логику по десяткам методов (при том, что вызов метода в руби не такая дешевая операция, особенно когда их очень много, из-за особенностей реализации кеширования методов в MRI). Стремление писать лаконичные методы понятно, но не ценой таких, высосанных из пальца, искусственных ограничений. Почему именно 5, а не 6 или 10?

>> Нельзя передавать больше 4 параметров в метод. Значения хэша также считаются параметрами.
Опять спорный момент, особенно вторая часть. Если в хеше лежат паспортные данные пользователя, все, приехали?

>> Инстанциировать максимум один объект в контроллере
Лучший способ размазать логику тонким слоем по всему проекту. Какой смысл плодить пустые классы и тесты к ним, вместо того, что бы написать 3 строчки кода в контроллере?

Роботы как всегда в своем репертуаре. Предлагаю добавить еще пару правил, раз пошла такая пьянка:
— в проекте должно быть не более 97 классов.
— нельзя иметь два файла с одинаковым количеством строк.
— число коммитов в день от одного человека должно входить в ряд Фибоначчи.
— размер всех картинок проекта в байтах должен быть простым числом.
>> 100-строковые классы
Если ваш класс больше — то в 95% случаев он нарушает SRP

>> 5 строк кода на метод
>> >> Полный и безоговорочный маразм!
Частично соглашусь: иногда довольно трудно вместиться в 5 строк, но при правильном дизайне обьектов и зависимостей в 90% методов у вас будет 2-3 строки

>> Если в хеше лежат паспортные данные пользователя, все, приехали?
Это primitive obsession и hash-driven development. Познакомьтесь со Struct или Form objects

>> Какой смысл плодить пустые классы и тесты к ним, вместо того, что бы написать 3 строчки кода в контроллере?
3 строчки кода превращаются в 5, потом в 10 и так до бесконечности. В контроллере не должно быть логики. Дополнительные обьекты более просты для изменений если вы продумали их публичный API.
>В контроллере не должно быть логики. Дополнительные обьекты более просты для изменений если вы продумали их публичный API.

Ошибка. В контроллере не должно быть логики работы с данными. А вот логика форматирования и и обработки событий view очень даже может быть и занимать много места.
Уж простите, но пускать пену изо рта что «эти правила к моему коду не подходят» и «кто такой этот Sandy Metz — да что она вообще знает о программировании» — это позорище.

Для начала: Sandi Metz не мужчина и уж тем более не компания. Не поленитесь, сходите по ссылке, посмотрите её выступления, а потом купите eё книгу — она своих денег стоит (как аргумент: Addison Wesley что попало и кого попало не печатает)

После этого вы, скорее всего поймёте зачем эти правила и как их соблюсти (не всегда строго, конечно, но всё-таки).
Чтобы посмотреть на то как это реализуется на практике: найдите, к примеру, на гитхабе субпроекты Datamapper 2: axiom, virtus, coercible etc.

А потом пойдите и зарефакторьте, наконец, свой говнокод
Сразу как-то вспомнилась сказка про Буратино:

«Не нужно забывать, что Буратино шел всего первый день от рождения.

Мысли у него были маленькие-маленькие, коротенькие-коротенькие...»
Sign up to leave a comment.

Articles