Как стать автором
Обновить

Комментарии 23

Любые догмы — это булшит, головой надо думать. С одной стороны да, нужно ограничивать вложенность условий по возможности, но «не используйте else» — это уже сектанство какое-то. Ну и остальные пункты тоже из той серии.
Автор предлагает это как упражнения, а не как догмы. Просто попробовать на каком-нибудь небольшом проекте эти правила, чтобы улучшить свои навыки ООП.
И превратить небольшой проект в сферическое ООП в вакууме, с классами у которых не больше 2х аттрибутов?) Это упражнения чего? Как писать код в отрыве от реальности?

Не бывает императивного, хоть сколько то серьезного кода, в котором в ветвлениях нет else, или в котором в классах только по 2 аттрибута (почему 2 вообще?). Это синтетические правила и синтетические упражнения, и я не очень понимаю как они должны помочь писать хороший реальный код.
Бывает. Вот пример enterprise-quality кода, который соответствует всем правилам, изложенным в статье. Проект уже обсуждался на хабре.

При всей абсурдности обсуждения шуточного кода, но даже там эти правила бы пригодились.

Оригинал:
...
public class NoFizzNoBuzzStrategy implements IsEvenlyDivisibleStrategy {

        public boolean isEvenlyDivisible(int theInteger) {
                if (!NumberIsMultipleOfAnotherNumberVerifier.numberIsMultipleOfAnotherNumber(theInteger, NoFizzNoBuzzStrategyConstants.NO_FIZZ_INTEGER_CONSTANT_VALUE)) {
                        if (!NumberIsMultipleOfAnotherNumberVerifier.numberIsMultipleOfAnotherNumber(theInteger, NoFizzNoBuzzStrategyConstants.NO_BUZZ_INTEGER_CONSTANT_VALUE)) {
                                return true;
                        } else {
                                return false;
                        }
                } else if (!NumberIsMultipleOfAnotherNumberVerifier.numberIsMultipleOfAnotherNumber(theInteger, NoFizzNoBuzzStrategyConstants.NO_BUZZ_INTEGER_CONSTANT_VALUE)) {
                        if (!NumberIsMultipleOfAnotherNumberVerifier.numberIsMultipleOfAnotherNumber(theInteger, NoFizzNoBuzzStrategyConstants.NO_FIZZ_INTEGER_CONSTANT_VALUE)) {
                                return true;
                        } else {
                                return false;
                        }
                } else {
                        return false;
                }
        }
        
}


Исправляем на один уровень вложенности в методе:
...
public class NoFizzNoBuzzStrategy implements IsEvenlyDivisibleStrategy {

        public boolean isEvenlyDivisible(int theInteger) {
                if (NumberIsMultipleOfAnotherNumberVerifier.numberIsMultipleOfAnotherNumber(theInteger, NoFizzNoBuzzStrategyConstants.NO_FIZZ_INTEGER_CONSTANT_VALUE)) {
                                return false;
                }

                if  (NumberIsMultipleOfAnotherNumberVerifier.numberIsMultipleOfAnotherNumber(theInteger, NoFizzNoBuzzStrategyConstants.NO_BUZZ_INTEGER_CONSTANT_VALUE)) {
                                return false;
                }

                return true;
}
И даже там я нашёл else
Ох уж эти теоретики от программирования (я не про вас, а про автора оригинальной статьи).

Ага, например, как в первом примере взять и размазать вложенные циклы по однострочным функциям. И где тут ООП? Повышение читаемости? Спорно. Чтобы понять, что происходит, придётся попрыгать по функциям, восстановить контекст, помнить цепочку вызовов и держать размерность блока циклов в голове, вместо того, чтобы просто взять и увидеть всё это в трёх несчастных строчках кода с двумя отступами.

Понимаю, что пример высосан из пальца, но именно его приводит автор. У Фаулера в книжке более адекватные примеры, хотя и не без перегибов, на мой взгляд.

Что это вообще за бредовое правило «не больше одного отступа на метод», ну кто его придумал? Кто сказал и доказал, что два отступа уже не читаются и не поддерживаются? :)
Пора вводить понятие программистский радикализм)
1. Конкретно этот пример гораздо более читаем в одном методе. Если он разрастется, тогда уже разделяем. Думаю, многие со мной согласятся.
8. У меня есть еще отчество. Тоже создавать отдельный класс? Мне кажется это самое бредовое правило. Нужно знать меру все же.
Пункт 3 вообще-то смущает, и при том сильно. Не получится ли в итоге, что в каждом модуле будет по своему типу строк и придется их друг к другу приводить? И вообще, это крайне плохо на производительности сказывается.
НЛО прилетело и опубликовало эту надпись здесь
Многие пункты не актуальны из-за лишнего overhead'a, если оптимизировать код под производительность. Ну например для написания игры.
На C++ можно делать inline. Более того, сам компилятор решает, когда стоит сделать inline. Java умеет так делать? (просто интересно)
НЛО прилетело и опубликовало эту надпись здесь
Дело не только в inline-ах, я про 2 поля в классе. Создание постоянно мелких объектов не очень хорошо для GC и кажется это самый бредовый совет.
Добавьте в список неизменяемость данных и можно на какой-нибудь хаскель переходить.
Боже, это бред какой-то. А early return я вообще считаю злом.
А можно поинтересоваться, почему? Это единственный совет из вышеприведенных, которому я следую в большинстве случаев и он уменьшает количество отступов тела функции и повышает читабельность. Конечно, это если его использовать только в начале функции; искать return'ы в середине никто не любит.
Читабельнее. Код пишется для людей, а не метрик. С else получается более «человеческое» выражение, сразу видно, что хотел сделать автор. ИМХО

А теперь от моего любимого C# со сборкой мусора перейдем к С:
void foo()
{
  int *ptr = malloc(1234);
  ... // Тысячи строк кода
  ...
  if (bar(ptr))
    return; // Утечка
  foobar(ptr);
  ... // Тысячи строк кода
  ...
  free(ptr);
}
Пример сферический, но в целом мысль понятна. Чужой код, все очень сложно, а тебе надо чуток подправить код.
По моему пример неудачный. Здесь early return не пахнет (после первых-то тысяч строк кода).
Ну и в подобных монстрах надо все перепроверять на двадцать рядов, чтобы хоть как-то быть уверенным, что не ошибся.
Даже если поставить else-блок, нельзя гарантировать, что в него случайно не попадет вызов free. А что если вызов free вообще в середине вторых тысяч строк кода, а не в конце? :) Все решает внимательность к деталям.
Пожалуй, можно поспорить, что лучше в плане читабельности обработки ошибок: колбаса из else или goto cleanup. Особенно, если ошибка в каком-то цикле.
Интересно, как быть с правилом «Никаких классов с более чем 2 атрибутами» для сложных сущностей? Например, что-то типа «счет», у которого десяток атрибутов, каждый из которых логически не пересекается ни с каким другим.
Мне кажется, следуя этим правилам, можно написать отличные макароны из кода, чтобы понять которые придется сотни раз прыгать туда-сюда.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории