Comments 49
Используй TODO и FIXME.
Крайне сомнительная рекомендация. Либо делай сразу, либо заводи задачу там, где она не потеряется. А вот уже ссылку на задачу можно добавить в TODO.
Можно ли сразу поддержать ARM? Можно, но не нужно: полноценная поддержка усложнит разработку в 1.5-2 раза, а если вы оставите «мёртвый код» без тестов и/или пользователей, то обнаружите, что к моменту, когда он понадобится — код «протухнет». TODO «протухают» тоже, конечно, но худшее, что с ними может произойти — они станут непонятными и вы их выкините, а странный код, появившийся ради задачи, от которой, в итоге, отказались будет вам мешать долгие годы — так как без комментариев все будут его видеть, но никто не будет понимать — зачем он там.
Используй TODO и FIXME.
вредна. Сегодня с утра один наш разработчик скинул в общий чат скриншот этой статьи с этой фразой. Тогда как у нас в компании всего месяц назад с моей подачи запретили оставлять в коде TODO без указания номера задачи.
Предполагает вынос блока try в отдельную функцию. Имеет ли смысл выносить в отдельную функцию если внутри блока одна строчка
Автор утверждает, что имеет, насколько помню. Я с этим согласен. Есть метод, который работу работает. Есть тот, который ошибки ловит. И второй не разобран на части первым. И вообще это разные задачи, зачем их перемешивать?
Привыкнуть только никак не могу. Среда разработки и язык не располагают к хоть сколько нибудь быстрому и / или удобному рефакторингу. В Джаву хочу, на Идею… И выделять методы, выделять методы...
Идеальное количество входных аргументов для функции = 0. Если входных аргументов больше трех, то стоит задуматься каким образом лучше от них избавиться, например, создать класс для этих аргументов.
По мне так наоборот. Не стоит плодить классы с методами без аргументов, в случае нужды будет сложнее понять какие конкретно данные метод берет, на какие другие методы эти данные повлияют, и сложно будет метод переиспользовать.
Нужно стремиться к чистым функциям. Вот вход, вот выход, все сразу понятно из заголовка. Если забирает сразу много данных — сделай интерфейс.
Идеальное — это 1. Что-то вошло — что-то вышло. Прямолинейный поток выполнения, композиция, лёгкость переиспользования. Когда у функции нет аргументов, это значит, что она берёт входную информацию из окружения, а значит имеет побочный эффект. Такую архитектуру нельзя называть «чистой».
this для методов — это не окружение, а один из аргументов.
Да, конечно.
int doSomething() {
this.data = 42;
return this.data;
}
То что this
является неявным аргументом для методов только ухудшает возможности для композиции: состояние класса является мутабельным окружением для всех методов, и ошибок с доступом к такому мутабельному состоянию не счесть. Даже без многопоточности.
А почему методы не могут быть чистыми?
Могут, это приветствуется, и вполне заметно улучшает поддерживаемость кода.
Но представим, что все методы чистые. Это значит, что их работа не зависит от состояния инстанса класса, и тогда возникает вопрос: "Зачем эти все методы содержатся в этом классе?"
И есть только один разумный ответ: класс просто группирует эти методы (которые уже просто функции), но если язык позволяет организовывать модули просто с внешними функциями (например, Kotlin, Scala, Rust), то вполне естественно организовать их так.
Продолжая в том же духе, мы можем все классы "раскрыть" таким образом, и получим программу состоящую из функций, организованных в модули и работающих с неизменяемыми данными.
Почти как в Хаскеле.
Вместо return null лучше использовать пустой объект — Collection.empty() или null-объект — EmptyObject().
Объясните, почему так? До настоящего момента приходилось встречать только вариант с null, чем он хуже?
1) Нет друзей — возвращаем null;
2) Есть один друг — возвращаем собственно объект;
3) Друзей больше одного — возвращаем коллекцию объектов.
Мало того что на null например можно попросту забыть проверить, или ожидать только null или коллекцию не учтя случай с одним объектом, так еще и разное поведение лепить в зависимости от типа возвращаемого значения.
Тогда как при пустой коллекции или коллекции с одним элементом нам бы не пришлось в клиентском коде городить отдельную логику.
То есть каждое правило применимо, ну, скажем, в 99% случаев, но поскольку у нас тут чуть больше, чем полсотни правил, то в половине мест хотя бы одно из правил стоит нарушить…
Про это недавно отдельная статья была…
Очень спорное утверждение.
Приблизительный максимум 20 строк и 150 символов в одной строке
150 символов — это явный перебор. Большенство редакторов ставят отсечку почти на половине от этой величины. И даже это многовато.
Идеальное количество входных аргументов для функции = 0
Если это foo/bar/baz для hello world — да, а так нет.
Названия методов должны содержать глагол, который описывает, что этот метод делает и ключевое слово с которым работает данный метод. Если в названии метода нет глагола, то эта сущность не должна быть методом или ему нужно дать правильное название.
Не обязательно. Это зависит от ЯП.
Не комментируй плохой код — перепиши его. Не стоит объяснять, что происходит в плохом коде, лучше сделать его явным и понятным.
Это не всегда зависит от пожеланий одного разработчика. Время на рефакторинг далеко не всегда удаётся выбить.
If, else, while и т.д. должны содержать вызов одной функции. Так будет читабельнее, понятнее и проще.
Вообще не обязательно. Очень сомнительное правило.
Не обязательно. Это зависит от ЯП.
Пример можно?
Я всего на нескольких ЯП пишу. Ни в одном из них нет ограничений на имя метода.
Если это foo/bar/baz для hello world — да, а так нет.
- start() — идеальный метод;
- start(speed) — отличный метод;
- start(speed, direction, path) — похуже. Сходу и не вспомнишь, в какой последовательности параметры передавать;
- start(speed, direction, path, maxBias, onError) — комментарии, думаю, излишни.
Пример можно?
Я всего на нескольких ЯП пишу. Ни в одном из них нет ограничений на имя метода.
Ruby. Вполне характерно писать вообще без глаголов или глагольных префиксов.
И если чистые глаголы это ещё куда не шло (#call, #perform или что-то в этом роде), то глагол + ключевое слово — это скорее code smell, чем норма.
И это не ограничение, а соглашение.
start() — идеальный метод;
start(speed) — отличный метод;
start(speed, direction, path) — похуже. Сходу и не вспомнишь, в какой последовательности параметры передавать;
start(speed, direction, path, maxBias, onError) — комментарии, думаю, излишни.
Если аргументов больше ~3 (это эмпирически) — это уже code smell.
Разумно применять keyword-аргументы, если возникает путаница.
Если следовать правилам чистого кода, то надо было их назвать calc_sqrt, calc_sin, find_exp и т.д. Делает ли это код чище? Ничуть.
- применяются в т.ч. в математике
- приживались годами
и поэтому не вызывают дополнительных вопросов.
А вот на заре моей программистской деятельности SQR и SQRT было сложно запомнить.
Полная запись GetSqareRoot (вполне вероятно) вызывала бы меньше вопросов поскольку не является «набором несвязанных букв» (как я тогда воспринимал) а вполне осмысленным словосочетанием.
Ruby. Вполне характерно писать вообще без глаголов или глагольных префиксов.
Я не сталкивался с Ruby.
Например, как геттеры от сеттеров отличаются?
И если чистые глаголы это ещё куда не шло (#call, #perform или что-то в этом роде), то глагол + ключевое слово — это скорее code smell, чем норма.
Из текущего:
Есть запрос (Request), который содержит список параметров (Parameter).
У Request есть метод для добавления параметра в список.
Назови я его add никто не поймет что именно добавляется.
Назови я его addParameter — даже не знакомому с архитектурой человеку будет понятно что именно добавляется в Request.
Будет ли имя addParameter «запахом»?
parameters.add
выглядит немного лучше нежели addParameter
Я не сталкивался с Ruby.
Например, как геттеры от сеттеров отличаются?
Немного вклинюсь к вам просто разнообразия ради)
Objective-C
getter: `param`;
setter: `setParam:(value)` (синтаксис неточный)
Т.е. функция-геттер не имеет глагола.
Например, как геттеры от сеттеров отличаются?
# это геттер
def first_name
@first_name
end
# это сеттер
def first_name=(val)
@first_name = val
end
Вот и всё различие.
На самом деле таким макаром геттеры/сеттеры не пишут, только если надо переопределить их стандартное поведение.
Дефолтную пару можно сгенерировать с помощью одной строчки
attr_accessor :first_name
Будет ли имя addParameter «запахом»?
Скорее да, чем нет.
Из Вашего примера, скорее всего данный функционал будет имплементирован немного по-другому.
request.params[key]=value
params — это просто словарь, к которому можно обратиться напрямую.
"[]=(key,value)" — это тоже метод.
P.S. Проверил — так примерно в рельсах и сделано. Только там params — это экземпляр класса Parameters, который в свою очередь ведёт себя как словарь.
Манифест Чистого Программиста или краткий конспект книги «Чистый Код» Роберта Мартина