Почему использование союзов в именах методов является плохим соглашением об именах? [закрыто]

12

В моей команде мы тесно сотрудничаем с несколькими архитекторами программного обеспечения. Они одобряют все проектные решения наших проектов, делают некоторые обзоры кода и т. Д.

Наши проекты состоят в основном из серверной функциональности, реализованной на PHP с использованием фреймворка Symfony 2. Таким образом, синтаксически код, соглашения об именах и структура проекта выглядят практически идентично тому, как будет выглядеть Java (Symfony 2 поддерживает такую ​​структуру). Я упоминаю об этом, потому что специфические для Java соглашения также применимы в нашем случае (если это возможно).

Недавно они предложили кое-что, что я нахожу очень странным: все методы должны иметь соединения в названии, например getEntityOrNull, setValueOrExceptionи т. Д.

Такое соглашение об именах кажется мне очень неправильным, но я не могу придумать какие-либо конкретные аргументы или онлайн-статьи / страницы, которые специально оспаривают это.

Единственное, что я придумал, это:

  • такая информация должна присутствовать в аннотациях метода, например @returnили@throws
  • использование союзов («и», «или» и т. д.) в именах методов обычно предполагает, что принцип единой ответственности должным образом не соблюдается

Какие еще конкретные аргументы против этого соглашения об именах?

Раду Мурзеа
источник
как правило, вы не можете
комнат
5
the use of conjunctions ("and", "or" etc.) in method names usually suggest that the Single Responsibility Principle is not properly respectedЭто не относится к приведенным вами примерам, где соединение используется для пояснения механизма, используемого для обработки сбоев, а не для указания того, что он может делать то или иное. Даже у самой узко определенной функции могут быть допустимые условия сбоя, например выталкивание пустого стека.
Доваль
4
Подумайте: (1) используя «опционально», а не «или ноль». «GetOptionalEntity» звучит лучше для моего уха, чем «GetEntityOrNull». (2) библиотека базовых классов .NET использует соглашение, согласно которому, если у вас есть два метода, которые отличаются только тем, что они выдают, назовите тот, который не может выдать «TryBlah». Например, Int32.TryParseи Int32.Parse- оба анализируют строку в целое число, но первое возвращает логическое значение, указывающее на успех, а второе выбрасывает при неудаче.
Эрик Липперт
Я бы не использовал суффикс для бросающего варианта, но я бы использовал один для нулевого возвращаемого варианта. Может быть Try..., ...OrNull, ...OrDefault. @EricLippert Это не единственное соглашение в .net. Рассмотрим Singleпротив SingleOrDefault, что очень близко к OrNullпредложенному ОП.
CodesInChaos

Ответы:

11

Вероятно, они делают это из-за конфликтов имен. Я предполагаю, что у вас не может быть двух названных методов getEntity, один из которых, возможно, вызывает исключение, а другой возвращает null. Поэтому вы должны назвать их соответственно.

Мне, например, не нравится практика использования множества разных способов вызова одного и того же метода, если только он не выполняет некоторые изменения, которые может выполнять только этот конкретный класс.

Другими словами, если getValueOrNullэто просто вызов getValueOrException, захват исключения и, в этом случае, возврат null, это может выполнить вызывающая сторона. Он загромождает класс методами, которые не приносят ничего полезного. Скорее я бы предпочел getValue, и знаю, что это исключение. Более того, я бы предпочел знать, что все методы get потенциально генерируют исключения, и ни один из них не возвращает nullвзамен так, чтобы поведение было одинаковым во всем моем проекте, или наоборот, все потенциально возвращались null, и знал, что вызывающая сторона должна была бы генерировать исключение, если это было желательно.

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

Нил
источник
Если вам нужно было выбрать только один, лучше вернуть null(или еще лучше, тип Optional / Maybe), так как бросание является относительно дорогим. Написание помощника, который проверяет, является ли значение недопустимым, и бросает, не добавляет много накладных расходов. Однако, когда вам нужна версия без бросков, проглатывание исключения не вернет вам удар по производительности, который вы получили, бросив его.
Доваль
1
@Doval Хороший вопрос, и, возможно, что еще более важно, исключения должны быть исключительными . Если вы часто бросаете исключения, вы не правильно их используете. Только проблема с возвращением в nullтом , что на nullсамом деле может быть допустимым возвращение в некоторых случаях , и поэтому вы должны отклоняться от нормы и бросить исключение в таких случаях.
Нил
3

Хотя использование союзов часто указывает на нарушение SRP, в этом случае оно просто указывает возвращаемое значение алгебраического типа данных бедного человека, которое может быть одним из двух значений, либо nullзначением «успеха».

Они используют своего рода венгерскую нотацию, чтобы компенсировать слабые места в системе типов, а именно отсутствие необнуляемых типов. Другими словами, в вашей @returnаннотации нет способа указать, что функция никогда не вернется null, и, наоборот, в вашей @returnаннотации нет способа указать, что функция может возвращать null.

Кроме того, я считаю, что @throwsаннотации не являются обязательными в php, поэтому отсутствие аннотации не указывает на отсутствие исключения, хотя это лучше решить, если сделать аннотацию обязательной в руководстве по стилю.

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

Карл Билефельдт
источник
2

В моем коде я иногда создаю пары методов с именами, такими как getEntity () и getEntityOrNull (). Название ясно показывает ожидаемое поведение. Если getEntity () не находит сущности, тогда генерируется исключение. getEntityOrNull () вернет ноль.

Благодаря этому вызывающий код становится немного понятнее. Если вызывающий код должен иметь сущность, тогда getEntity сделает свое дело. Если entity - это какая-то необязательная вещь, тогда getEntityOrNull является методом выбора.

То же самое может быть достигнуто с помощью одного метода, но это затем переносит часть нагрузки на вызывающую программу. Вам всегда нужно проверять на ноль, или вам нужен блок try / catch. В любом случае это дополнительный код, который необходимо дублировать при каждом вызове метода.

Если ваши архитекторы не используют такие пары методов, то да, я бы поставил под сомнение необходимость суффикса.

Никогда не видел метод setValueOrException. Не могу придумать хорошего варианта использования для этого.

Вы можете спросить архитекторов, почему. Те, кого я знаю, всегда рады объяснить свои решения. Часто в мельчайших (а иногда и мучительных) деталях.

Cerad
источник
То, что getEntity будет генерировать исключение при сбое, мне совершенно не понятно, я бы ожидал простого NULL.
Элиз ван Лоидж
1

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

Пока вы это делаете, вы должны убедить их не использовать части "get" и "set", если только эти методы не устанавливают непосредственно или не получают переменную-член.

Эбен
источник