Pull to refresh

Comments 41

Ну и что такого ужасного в "yyyymmdstr"? Вполне четкое название дающее сразу всю информацию. CurrentDate тут явно не лучше.

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

Как же тяжело бывает объяснить это напарнику, кто везде пихает одно и тоже потому что "а вот 5 лет назад я сделал иначе и мне дали по рукам" (или аналог).

«yyyymmdstr»… Вполне четкое название дающее сразу всю информацию

Какую информацию? что это год-месяц-число? крайне полезно… А год чего? день рождения? дата-то какая вообще?
1. Так вот чем знать как отформатирована дата, глядя на ее переменную, чаще всего куда важнее знать как раз, датой чего именно является эта переменная
2. Попробуйте догадаться, что вводить в поиск, если понадобится найти в проекте подобным образом названное значение
3. Иногда удобнее назвать не просто currentDate, а в соответствии тому, в какой момент присваивается дата (например: entityCreationDate или entityModifiedDate), но это только если переменная далеко идет по коду, а это скорее всего — следствие плохого проектирования архитектуры, поэтому в толковом коде обычно как раз currentDate — достаточно

Тоже соглашусь, когда прочитал, подумал а причем здесь current. Лучше для yyyymmdstr - var (const, let) dateStr = в строго типизированных языках String date. И то, в том случае если я правильно понял концовку str

Это не иия, а тип данных, имя для другого.

А почему вдруг

const isEnabled = (itemsCount > 3);

это "плохо"?

Потому что в оригинале было использование:


/* Bad */
const isEnabled = (itemsCount > 3)
return <Button disabled={!isEnabled} />/* Good */
const isDisabled = (itemsCount <= 3)
return <Button disabled={isDisabled} />

Проблема тут возникает в том, что в этот момент элемент становится привязанным к его использованию, и если это локальная переменная, это еще как-то можно понять, а вот если это свойство — то уже нет.

Действительно, "ожидаемые результат" при редактировании потерялся! Исправил. Спасибо!

Если у меня
<Grid IsEnabled="{Binding isEnabled}">

то выйдет наоборот:
isEnabled — хорошо
isDisabled — плохо
Получается, ViewModel должна быть привязана к View?
Получается, ViewModel должна быть привязана к View?

Это ровно то, про что я в своем комменте пишу:


в этот момент элемент становится привязанным к его использованию

На мой взгляд, это не очень хорошо.

Понятно, автор написал «исправил», а на самом деле в статье противоположная точка зрения.

Я поправил пример в тексте перевода на текст из оригинала

4. Should Reflect expected result

/* Bad */

const isEnabled = (itemsCount > 3)

return <Button disabled={!isEnabled}/>

/* Good */

const isDisabled = (itemsCount <= 3)

return <Button disabled={isDisabled}/>

Точка зрения очень тут понятная: Имя должно отражать ожидаемый результат

В примере кнопка disabled но в первом случае контрольная переменная называется isEnabled и потом ее приходиться применять через отрицание. Лучше было сразу создать isDisabled - в этом случае название соответствует ожидаемому результату.

is — Описывает свойство или состояние текущего контекста (обычно — логическое значение).

isErrorFound точно лучше, чем errorFound? А почему?


Имя должно быть коротким (Short), интуитивно понятным (Intuitive) и описательным (Descriptive).

Ни одно из этих понятий не определено. Берем пример:


shouldDisplayPagination

Это короткое имя? Нет. Так почему его приводят в пример?


Более того, в среднем, "короткое" и "описательное" — это взаимопротиворечащие характеристики (как и видно на этом примере).

В ваших вариантах смысл иной получился.

isErrorFound точно лучше, чем errorFound? А почему?

is - описывает состояние, бинарное, да или нет. errorFound не так однозначно. Это может быть и номер найденной ошибки, и число найденных ошибок. Может быть прямой перевод на русский вроде "ошибкаНайдена" для вас и однозначен, но на английском не так все однозначно.

Потому пишут isFound, countErrorsFound

От этих правил и пляшут кодогенераторы. Для Boolean они сгенерируют чаще всего isErrorFound.

Мой обычный диалог при код ревью:
— что означает переменная errorFound?
— Это — код ошибки.
— Отлично. Давай то, что ты сказал, и запишем в само имя переменной — errorCode.
— Что означает shouldShowPaginationIfTooManyRecords?
— Что нужна пагинация.
— Отлично. Давай так и запишем — pagination.
— Что означает shouldShowPaginationIfRowHeightIsVeryVeryBig?
— Что нужна пагинация.
— Отлично. У нас уже есть такая — давай эту удалим.
Это короткое имя? Нет. Так почему его приводят в пример?
Да, короткое)
Минимально возможная длина именования, при которой будет интуитивно понятен смысл содержания и не нарушена логика интуитивного поиска по этому именованию для подавляющего большинства разработчиков. Так лучше?)

ИМХО: тема хорошая, советы небесспорные.

А тема такая, что тут спорить и спорить, бесспорных вариантов не бывает. Мне статья понравилась, вполне всё по делу.

Начинающий программист.

Никак руки не доходили рассмотреть эту тему. Везде слышу о том, что надо правильно давать имена переменным, функциям, а как?? Всегда называл "как приходилось", а сейчас буду ответственнее к этому подходить, советы на самом деле очень дельные. Спасибо автору.

Как по мне, совет в том виде, в котором он дан для функций — начинать имя с глагола — это прямо вот ужасно. Такой подход еще нормально работает в «общих библиотеках», но при попытке применить к коду, который описывает бизнес-сущности конкретного домена и где их количество (сущностей) растет как снежный ком — это просто издевательство. У меня ни разу не возникало необходимости получить или удалить что-нибудь, чтобы начать свой поиск метода с fetch или delete. Наоборот, всегда пытаешься понять, что доступно (уже написано) для каких-то конкретных сущностей и сообразить, можно ли из этого соорудить, что требуется.

Я прямо вот очень хорошо понимаю теперь, почему товарные позиции в магазинах называются в таком «дурацком» виде, типа «Томат, голландский, весовой» или «Болт, M12, оцинкованный» — поиск в списках, составленных по такому принцип — «сущность — уточнение, уточнение,…, уточнение» просто в разы удобней.
То есть, вместо listOrders, getOrder, updateOrder, вы пишете
ordersList, orderGet, orderUpdate?
Но это режет слух всем, что более-менее говорит на английском, и заставляет переключаться после использования API библиотек, котороые спроектированы в противоположном стиле.

Хотя, таким способом легко видеть, где «моё» (названое как сущность + действие), а где «библиотечное» (действие + сущность). Но в командной работе, я думаю, такой стиль брать плохо.
То есть, вместо listOrders, getOrder, updateOrder, вы пишете
ordersList, orderGet, orderUpdate?

Почти, с небольшим «тюнингом». В CRUD операциях 3 из 4 букв — это запись (input). Потому я использую глагол только для пишущих операций, а для чтения — get опускается. В сочетании с самими сигнатурами метод — пишущие в общем случае void — это более чем достаточно. Ваш пример в моем коде будет выглядеть как Orders, Order, OrderUpdate.

Но это режет слух всем

Я вот только что перепроверил, как переведет гугл транслейт фразу «алгоритм обновления заказа», коим и является OrderUpdate method — получилось «order update algorithm». Код описывает алгоритмы и структуры, логично и называть его исходя из этого, нет? Я полагаю, мода на глагольные префиксы торчит из-за путаницы с уровнем UI через CLI. На UI пользователь шлет команды, которые запускают алгоритмы. И для именования команд вроде как в самом деле интуитивней через глаголы.
только что перепроверил, как переведет гугл транслейт
Видимо, вы не из тех, кто «более-менее говорит на английском». В этой фразе ключевое слово «алгоритм», остальное — уточнения. А вы его опускаете в результате, выбрасывая суть. По той же логике чтение заказа надо именовать как «алгоритм чтения заказа», т.е., опуская «алгоритм», OrderReading(), а «алгоритм получения списка заказов» — «obtaining a list of orders», т.е. ordersObtaining(). Это вообще дико выглядит.
… с небольшим «тюнингом». В CRUD операциях 3 из 4 букв — это запись (input). Потому я использую глагол только для пишущих операций, а для чтения — get опускается. В сочетании с самими сигнатурами метод — пишущие в общем случае void — это более чем достаточно

может со второй попытки заметите
В этой фразе ключевое слово «алгоритм», остальное — уточнения. А вы его опускаете в результате, выбрасывая суть.

Мы же по прежнему говорим про код? Можете привести пример, когда в методе или процедуре содержится НЕ алгоритм? Чтобы у меня появился резон добавлять это уточнение — что это именно алгоритм, а не что-то другое.

Вы в одном комментарии смешиваете кислое с горячим.

В начале пишете про функции, а потом "понимаете" про товарные позиции.

Товарные позиции так назывались ранее по простой причине - не было баз данных. Были листочки на которых писали. В лучшем случае разлиновывали таблички. В современном мире ваш «Болт, M12, оцинкованный» ляжет в БД с полями item size material а на ценнике будет напечатано так же как и ранее «Болт, M12, оцинкованный». Вот только ни какой связи с неймингом в программировании эти товарные позиции не имеют.

Вернусь к функциям.

Во-первых не "прям ужасно" и по-английски читается часто как обычный текст на языке. Встречаются варианты когда объект указывается в начале, а действие после него. Имеет право на жизнь оба варианта. Вопрос договорённостей внутри команды.

И это не зависит от "общих библиотек" или "конкретного домена". Функция или метод это всегда действие - поэтому глагол.

Я так понимаю, в новом магазине (c базой данных) без этих старых пережитков, — и отделы стоит назвать «Наливают», «Нарезают», «Насыпают»? А внутри отдела по алфавиту расположить «Бензин», «Бельгийское пиво»… «Зимний бензин», «Темное Бельгийское пиво».

Вы в одном комментарии смешиваете кислое с горячим. В начале пишете про функции, а потом «понимаете» про товарные позиции.
Так смешиваю, или сперва пишу про одно, а потом про другое? Я это называю «аналогия».

Во-первых не «прям ужасно» и по-английски читается часто как обычный текст на языке.

В моем комментарии говорится что "совет, в том виде, котором он дан, ужасен". Это не то же самое, что «читается ужасно».

Имеет право на жизнь оба варианта.

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

Если Вам действительно хочется понять мою позицию — можете ради интереса глянуть формулу количества информации в сигнале. Сигналы, у которых начало менее вариативно, всегда будут чуток отставать в скорости передачи информации и «догонять» только в самом конце при прочих равных. Если у вас все функции начинаются с get, set, handle, то после получения (прочтения) 'g', 's' и 'h' следующие 2-5 символов несут вам просто ноль информации.

Люди не дурные и чувствуют это интуитивно. Точно так, как нелеп магазин с отделами «Наливают», «Нарезают», точно также будет нелеп завод где вместо Токарного, Фрезерочного, Штамповочного, Кузнечного и что там у них еще, будут цеха «Сталь» и «Алюминий».

В программировании это не так очевидно, потому что как раз очень сильно зависит от домена.
Заметил, что часто в коде над которым работают несколько разработчиков, возникает разница в порядке слов, например, mainDocument и documentMain в разных местах. В обоих случаях можно найти свои за и против, и единого стиля в итоге на проекте нет.
За статью спасибо, полезно бывает задуматься о таких базовых вещах.

В английском языке — сначала прилагательное, потом существительное. В русском возможна перемена мест, но обычный порядок такой же.

Вопрос вкуса и договорённости в команде. Но важно чтоб в одном проекте было единообразно.

В современных языках они превратились в свойства, так что понятно желание хоть немного уменьшить boilerplate.

Сейчас довольно модно опускать префикс «get» у геттеров: не getName()/setName(), а просто name()/setName() - ибо имеет смысл: пишется короче, а смысл не меняется (если метод - существительное, то это геттер или свойство). Учитывая, что геттеров обычно во много раз больше, чем сеттеров (ибо immutability pattern - сеттеры это вообще антипаттерн в большинстве случаев), получается хорошо так.

Пока существительное не окажется глаголом. showName() — это название телепередачи или "покажи имя"?

при нормальной архитектуре это будет очевидно из контекста. showName «как название» будет фигурировать на уровне описания структур сущностей, самом низком. showName «покажи» возможен только на уровне UI.

Так вводится дополнительная сущность "нормальная архитектура". Поди, для всех ещё нормальность разная. А если архитектура вообще так себе? А если это не show, а print, call,  map или ещё какое-то слово, которые в аналитических языках типа английского  легко переходят из одной части  речи в  другую?  Лучше проще, да  лучше.

А если архитектура вообще так себе?

ну тогда остается лишь префиксовать все подряд и надеяться, что не понадобится метод загрузки из базы только имени шоу — getShowName и не понадобится подключать api внешнего сервиса с AI для подбора «продающих» имен шоу — getShowName.

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

Вы имеете ввиду инкапсуляцию? Инкапсуляция в ООП нужна для того, чтобы строить абстракции в терминах поведения, а не прямой манипуляции состоянием объекта. Интерфейсы в терминах поведения более стабильны и приводят к меньшему coupling.

Представьте, что какое-то значение изначально хранилось в поле, а потом вы решили, его вычислять или откуда-то запрашивать. Если это поле не "засветилось" в интерфейсе класса, то такое изменение никак не затронет клиентов класса. И это очень хорошо.

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

Заменив прямой доступ к полю на геттер с сеттером можно формально соблюсти требование этого правила, но получившийся дизайн будет обладать практически всеми теми же самыми недостатками, что и дизайн с прямым доступом к полям. Вернёмся к примеру выше, с заменой хранения значения в поле на вычисление. Что случится, если вместо поля в интерфейсе у нас будет геттер и сеттер? С геттером все хорошо, он просто вернёт вычисленное значение. А сеттер? А вот тут все плохо, сеттер придется убрать и вы будете вынуждены рефакторить весь код клиентов класса, который к нему обращался.

Получается, что обилие геттеров и особенно сеттеров в коде как правило свидетельствует точно о таком же нарушении инкапсуляции, как и прямой доступ к полям. Но зато "буква" ООП вроде как соблюдена :)

К сожалению, вы смешали теплое с мягким. Наличие геттеров не обязывает использовать сеттеры. А вот метод, возвращающий значение переменной называть именем этой же переменной бред — читаемость кода ухудшается. А уж про обилие геттеров и сеттеров рассуждать — это вообще странно. Если нам нужно у конкретной переменной считывать значение, то пишем геттер. Если нужно дать возможность вручную менять значение переменной — пишем сеттер. К этому все привыкли и это считается хорошим тоном.

Я аппелировал к вашему утверждению о том, что доступ к полям нарушает принципы ООП, а геттеры/сеттеры нет. ИМХО, они точно так же нарушают инкапсуляцию, на уровне абстракций. Геттер area()/getArea(), возвращающий значение переменной - плохой с точки зрения инкапсуляции, а вот метод area()/getArea(), возвращающий площадь - хороший.

Но иногда гетеры и сеттеры действительно полезны, они позволяют, например, решать проблемы двоичной совместимости или использовать паттерны наподобие прокси. Только к концепциям ООП это перпендикулярно.

А для любителей предоставлять доступ к полям, многие объектно-ориентированные языки (C#, Java, Pascal, Python, JavaScript и т.д.) имеют такую штуку, как свойства. Для вызывающего кода выглядят они точно так же, как и поля, но на уровне реализации сводятся к тем же геттерам/сеттерам. И приписывание или опускание префиксов get/set при этом регулируют либо на уровне синтаксиса, либо официально принятыми конвенциями. Java, например, требует префикс get для свойств классов (java beans), но не допускает его для свойств структур. Так что использовать префикс get или не использовать зачастую уже решили за вас.

Лично я нахожу конвенцию, в которой допускается называть существительными методы, не имеющие сайд эффектов, вполне удобной и читабельной. И без префикса get понятно, что кроме возврата значения такой метод больше никаких видимых изменений не делает, а визуального мусора меньше. Плюс, похоже на те же самые свойства, разве что с пустыми скобочками на конце (в некоторых языках и скобочки можно опустить).

Sign up to leave a comment.

Articles