Безнравственно ли я использую имя переменной, которое отличается от своего типа только регистром?

95

Например, возьмите этот фрагмент кода:

var person = new Person();

или для вас Pythonistas:

person = Person()

Мне постоянно говорят, насколько это плохо, но я еще не видел примера безнравственности этих двух строк кода. Для меня человек - это Личность, и попытки дать ему другое имя - пустая трата времени. Я полагаю, что до выделения синтаксиса это было бы большим делом. Но в наши дни довольно легко отличить имя типа от имени переменной. Черт возьми, здесь, на SO, даже легко увидеть разницу.

Или что-то мне не хватает? Если да, было бы полезно, если бы вы могли предоставить пример кода, вызывающего проблемы.

Джейсон Бейкер
источник
Меня всегда это интересовало. Хороший вопрос!
Уильям Брендель,
18
Называть человека человеком просто жестоко. Что не так с «боб»?
Сэм Мелдрам,
17
Не будем забывать, что до var была дзен-красота: Person person = new Person ();
Джейми Иде,
1
@Jamie, ты называешь статическую типизацию дзен-подобной?
orokusaki
Я хотел бы пойти еще на один уровень глубже в этот вопрос: Является ли это неоспоримо неправильно делать Person Person=new Person();для этого дела? Как сказано в Вопросе, мы живем во времена такой невероятной подсветки синтаксиса и распознавания контекста, что мой компилятор никогда не жаловался на то, что я делаю именно это. Мне просто нравятся мои переменные CamelCased - почему бы и нет (в ситуациях, когда Person Personэто общий и единственный экземпляр класса, а конфликт отсутствует и не возможен)?
Роберт Сынорадский,

Ответы:

94

Каковы аргументы тех, кто говорит вам, что это плохо? Я все время это делаю. Это самый простой и выразительный способ дать имя отдельной переменной типа. Если вам нужны два Personобъекта, вы можете добавить к префиксу personмногозначительные прилагательные, например

fastPerson
slowPerson

иначе просто

person

меня устраивает.

Эндрю Хэйр
источник
8
"Каковы аргументы тех, кто говорит вам, что это плохо?" - Не знаю. Вот почему я завел эту тему. :-)
Джейсон Бейкер
Ясно, что вам никогда не приходилось использовать чужой код. Я знаю, что когда меня просят исследовать какую-то недавно обнаруженную ошибку в коде давности несколько лет программистом, который давно ушел из компании, - все, что мешает мне разозлить, - это время не устранять проблему. Если одно из этих препятствий пытается выяснить, что такое экземпляр, а что класс, только потому, что программист не удосужился сказать «var currentPerson = New Person ();» тогда это бесполезная трата времени. ... и когда ваши клиенты ждут решения проблемы, время имеет значение.
Дэвид,
3
@ Дэвид - Ты меня поймал! Я знал, что кодирование в вакууме рано или поздно поднимет свою уродливую голову :) Хотя если серьезно - мне трудно поверить, что вы запутаетесь из-за невозможности различать типы и их экземпляры на основе этого соглашения об именах.
Эндрю Хэйр,
2
@David - это должно быть проблемой для инструмента анализа кода. Кроме того, именно поэтому существует соглашение, согласно которому в Python типы начинаются с заглавной буквы.
илья н.
69

Я часто использую этот шаблон в сигнатурах методов. Если я не могу предоставить альтернативное описательное имя, то ИМХО, в этом нет ничего плохого.

Что неправильно, если у вас есть два типа Person и person, тогда это очень-очень неправильно.

Джош Берке
источник
1
«Что неправильно, если бы у вас было два типа Person и person, тогда это было бы очень неправильно». - Для меня это имеет смысл.
Джейсон Бейкер,
1
Если вы создаете API, VB не сможет обрабатывать код, поскольку он нечувствителен к регистру.
JoshBerke
1
Эй, в случае с API вас беспокоят имена или свойства общедоступных методов, а не имена переменных, потому что последние не будут открыты для клиентского кода. Что касается вопроса Джейсона, я тоже все время использую это именование. Абсолютно ничего плохого в этом нет.
Фредерик Дурак,
1
Точно моя точка зрения, Фредерик, почему иметь два типа, которые отличаются только базовым случаем, - плохая идея ;-)
Джош Берке
1
Даже если это не так, это затрудняет чтение кода. Читаемость тоже имеет значение.
J3r3myK
45

Я все время использую его для временных ссылок на объекты. Я бы избегал этого, как чумы для примитивных типов данных.

Person person = new Person(); // okay

int Int = 42; // pure evil
Билл Ящерица
источник
Если бы действительно не было семантического значения, я мог бы дать примитиву, я бы использовал i или s, кроме индексов цикла, я не могу придумать другого такого сценария.
AnthonyWJones,
1
Я бы не рекомендовал использовать i, особенно если вы пишете код с циклом. i почти повсеместно рассматривается как имя переменной цикла.
Джейсон Бейкер,
3
Согласовано. Однобуквенное имя переменной кричит: «Я временный». Индексы цикла должны быть i, j, k, любые другие должны быть a, b, c, x, y, z или любой другой буквой, которую нельзя принять за что-то еще, например l и o.
Bill the Lizard
Браво! 42 - это слишком много. :)
Vishal Seth
18

Если кто-то говорит, что это зло, спросите его, лучше ли это:

var abc = new Person();
Крис
источник
2
@ Крис: именно так! Или еще лучше: var temp = new Person();(Отказ от ответственности: я знаю, что действительно есть места для одноразового использования временных переменных, но часто, когда я вижу это в чьем-то коде, автор просто никогда не возвращался к тому, чтобы дать переменной подходящее имя, и это может также будет "abc".)
Дина
15

Если Личность в контексте является общей Личностью, то «человек» - действительно хорошее имя. Конечно, если у человека есть определенная роль в коде, то лучше назвать ее, используя роль.

PEZ
источник
9

Полагаю, за это меня проголосуют против, но ...

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

Майк Данлэйви
источник
6
Или же, если моральные решения, которые мы можем принять, столь незначительны, мы прокляты. Я не уверен, что хочу, чтобы моя похоронная речь была сосредоточена на моем стиле кодирования. Я хотел бы хотя бы вскользь упомянуть, что являюсь частью семьи.
Дэвид Торнли,
1
@ Дэвид: И снова верно. С моим первым внуком в пути, я полагаю, это банально, но меня волнует, какой мир мы передаем.
Майк Данлэви
8

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

Тим Алмонд
источник
6

Джейсон - Я не уверен, кто сказал тебе, что это плохо. Ряд авторов используют это как стандартный способ выражения экземпляра (в нижнем регистре) класса ( в верхнем регистре ).

Я использую это довольно часто, так как обнаружил, что переменная в нижнем регистре фактически сообщает мне не только то, что это экземпляр, но и имя класса.

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

Марк Бриттингем
источник
6

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

Человек person = новый Человек ();

Человек person2 = новый Человек ();

Тогда это было бы на грани «Плохого». Однако в этом случае вам следует провести рефакторинг вашего исходного персонажа, чтобы различать их.

Что касается вашего примера, имя переменной «человек» - это совершенно описательное имя для объекта «Человек». Поэтому в этом нет ничего плохого.

День Робина
источник
3

Я говорю имя для того, что это такое: если переменная представляет человека с двумя собаками, назовите его personWith2Dogs. Если переменная имеет короткую область видимости (например, цикл var), тогда с человеком все в порядке.

Митч Уит
источник
3

Я часто использую это в своем коде и не думаю, что с этим что-то не так. Тем не менее, я (вероятно) не стал бы использовать его в методе дольше, чем, скажем, один экран, и если существует несколько экземпляров класса Person. Определенно не называйте их person1, person2, person3 ... вместо этого используйте что-нибудь более описательное, например person_to_del, person_to_ban, person_to_update и т. Д.

Kmelvn
источник
3

Не аморально, но глобальный поиск найдет и то, Personи другое, и personесли вы не активируете чувствительность к регистру. Я предпочитаю префикс, чтобы упростить глобальный поиск / замену, но абсолютно НЕ венгерский или что-то длинное / сложное. Итак, я использую ...

Personдля класса / типа aPersonдля локальной переменной thePersonдля параметра метода myPersonдля переменной экземпляра ourPersonдля переменной класса

В редких случаях я могу использовать pв локальном контексте, где у меня есть МНОГО ссылок, но обычно это относится только к индексам циклов и т.п.

Роб Уильямс
источник
3

Это зависит.

Если у вас строгий стиль использования заглавных букв, поэтому переменные начинаются с нижнего регистра (и используют либо under_scores, либо camelCase для разрывов слов), а классы начинаются с заглавных букв, тогда очевидно, что person - это переменная, а Person - это класс, и когда кто-то это понимает , они не будут находиться в перекрывающихся пространствах имен. (Точно так же люди почти никогда не путают глагол или существительное «полировать» и прилагательное «польский».)

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

Дэвид Торнли
источник
Еще раз привет, Дэвид. Я не могу вспомнить, отредактировал ли вы одно из моих постов, потому что я написал «опрос», или это было «полировка», когда я хотел потереть что-то, пока оно не засияет? Ну что
ж
Не думаю, что я делал такое редактирование, так что, вероятно, это был кто-то другой. Кстати, это «полировка».
Дэвид Торнли,
2

Какие точные аргументы используют эти люди?

Если они не позволяют вам использовать человека в качестве имени переменной, вы можете подумать о добавлении префикса «a».

aPerson = Person()
Герри Шенк
источник
2
На мой взгляд, это было бы хуже. Его сложнее читать, и он не дает никакой дополнительной информации.
Joachim Sauer
Да, но, по крайней мере, имя отличается от имени класса, чего они явно хотят.
Gerrie Schenck,
Это было бы соблюдением буквы закона, но определенно не духа.
Иоахим Зауэр,
1
+1, я использую thePerson для параметров и myPerson для местных жителей, которыми я управляю.
Amy B,
2

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

Например, я использую lowerCamelCase для экземпляров, переменных и UpperCamelCase для классов и т. Д.

Стандарты кодирования должны устранить эту проблему.

Когда я смотрю на успешные программы с открытым исходным кодом, у них часто есть стандарты кодирования.

http://drupal.org/coding-standards

http://help.joomla.org/content/view/826/125/

http://wiki.rubyonrails.org/rails/pages/CodingStandards

http://lxr.linux.no/linux/Documentation/CodingStyle

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

На самом деле посмотрите запись в википедии (из http://en.wikipedia.org/wiki/CamelCase )

Стиль программирования и кодирования

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

В этих рекомендациях часто проводится различие между UpperCamelCase и lowerCamelCase, обычно указывается, какое разнообразие следует использовать для конкретных типов сущностей: переменных, полей записи, методов, процедур, типов и т. Д.

Один широко используемый стиль кодирования Java требует, чтобы UpperCamelCase использовался для классов, а lowerCamelCase - для экземпляров и методов [19]. Признавая это использование, некоторые IDE, такие как Eclipse, реализуют ярлыки на основе CamelCase. Например, в функции поддержки содержимого Eclipse ввод только заглавных букв слова CamelCase будет предлагать любое подходящее имя класса или метода (например, ввод «NPE» и активация помощника по содержимому может предложить «NullPointerException»).

Исходная венгерская нотация программирования указывает, что сокращение нижнего регистра для «типа использования» (не типа данных) должно предшествовать всем именам переменных, а оставшаяся часть имени должна быть в UpperCamelCase; как таковой это форма lowerCamelCase. CamelCase - это официальное соглашение для имен файлов в Java и для персонального компьютера Amiga.

Microsoft .NET рекомендует использовать lowerCamelCase для параметров и закрытых полей и UpperCamelCase (также известный как «Pascal Style») для других типов идентификаторов. [20]

Python рекомендует использовать UpperCamelCase для имен классов. [21]

Реестр NIEM требует, чтобы элементы данных XML использовали UpperCamelCase, а атрибуты XML использовали lowerCamelCase.

Не существует единого соглашения для включения аббревиатур в верхнем регистре (в основном акронимов и инициализмов) в имена CamelCase. Подходы включают в себя оставление всей аббревиатуры в верхнем регистре (например, в «useHTTPConnection») и оставление только первой буквы в верхнем регистре (например, в «useHttpConnection»).

Корпус Camel отнюдь не универсален в вычислительной технике. Пользователи нескольких современных языков программирования, особенно из семейств Lisp и Forth, почти всегда используют дефисы. Среди причин, которые иногда приводят, является то, что для этого не требуется сдвиг на большинстве клавиатур, что слова более читабельны, когда они разделены, и что верблюжий регистр может просто не сохраняться надежно в нечувствительных к регистру языках или языках со складыванием регистра (например, Common Lisp, который, хотя технически и является языком с учетом регистра, по умолчанию преобразует (сворачивает) идентификаторы в верхний регистр).

Стюарт Робинсон
источник
2

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

  • Индикатор хорошей детализации кода: если ваши методы короткие, одноцелевые и имеют описательные названия, вам не нужно много информации в именах переменных. Если у вас есть длинные методы, которые выполняют множество функций и вам необходимо отслеживать большой объем контекста и состояния, тогда имена переменных должны быть более наглядными.

  • Индикатор универсальных вычислений, переданных в универсальные методы: если вы выполняете промежуточные манипуляции со структурами данных в бизнес-методе, например, массив пользователей должен быть дедуплицирован, вам необходимо иметь переменные в области видимости с такими именами, как users[]и deduplicatedUsers[]. Если вы переместите дедупликацию в служебный метод, вы можете вызвать метод Utils.dedup(array), и вы можете вызвать дедуплицированный массив deduplicatedArrayили просто result.

  • Декомпиляторы Java часто используют подобную схему для именования локальных переменных (переменные экземпляра и класса обычно доступны в байт-коде, но локальные переменные нет), и результаты более читабельны, чем вы могли ожидать, на самом деле часто более читаемы, чем первоисточник.

  • См. Принцип Ларри Уолла «Локальная неоднозначность - это нормально» - http://www.wall.org/~larry/natural.html .

user8599
источник
2

Я бы сказал, что вы, вероятно, имеете в виду какое-то конкретное использование, когда создаете объект. Один только тип очень редко отражает это использование.

Поэтому, если вы хотите создать новый контакт в приложении адресной книги, вы можете вызвать переменную newContact.

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

Вызов этого просто personупускает большой шанс сделать ваш код самодокументированным.

Иоахима Зауэра
источник
Назовите это анонимным! :)) var anonymous = new Person (); Или даже лучше: var you_know_who = new Person (); :))
Вадим Фердерер
@Vadim Ferderer: var he_who_must_not_be_named = new Person();? :-)
Platinum Azure
2

Только если вы программируете на VB6. В таком случае то , что вы делаете, незаконно, но не аморально.

Brianegge
источник
1

Я тоже так делаю и не понимаю, почему это должно быть «аморальным». Хотя я могу понять, что это иногда может сбивать с толку, но сегодня у нас есть IDE с intellisense и подсветкой синтаксиса, которая гарантирует, что (если вы сделаете ошибку и укажете свою переменную вместо своего класса, и наоборот) увидеть свою ошибку довольно быстро. А еще у нас есть компилятор. :)

Фредерик Гейзель
источник
1

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

мафу
источник
1

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

Например, если вы рассчитываете стоимость определенного товара в интернет-магазине, следующий код будет не лучшим вариантом:

Decimal _decimal = item.BaseCost + item.Tax;

Вместо этого было бы рекомендовано более описательное имя, такое как «_total» или «_cost».

Джей С.
источник
1

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

Если они различаются только регистром, это будет нормально работать на языках с учетом регистра, таких как C #, но не на VB.NET.

Так, например, в VB я бы написал

Private _name As String

но

Public Property Name() As String
    Get
        Return _name
    End Get
    Set(ByVal Value As String)
        _name = Value
    End Set
End Property

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

ChrisA
источник
Единственное, что мне не нравится в этом подходе, это то, что переменные с префиксом с одним подчеркиванием, как правило, связаны с закрытыми членами класса. Но я считаю, что общий подход неплохой.
Джейсон Бейкер,
Да, это то, что я здесь иллюстрирую. Было бы хорошо определить локальную переменную, например «Тусклый человек как новый человек». Очень (очень) иногда с компилятором VB возникает двусмысленность, и нормального обнадеживающего автоматического ввода заглавных букв не происходит. Это хороший визуальный сигнал, что не все в порядке.
ChrisA
1

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

Жоао Синтра
источник
1

Person person = new Person()Сам часто пользуюсь . Обычно используется в Java / C #.

Хотя вчера я задался вопросом, почему

private enum DataType {NEW, OLD}

не работает на C # ...

Особенно видя , как вы можете использовать String, string, Double, double, ... по желанию в C #.

Carra
источник
enum поддерживает только byte, sbyte, short, ushort, int, uint, long, ulong. т.е. типы не дробных числовых значений
Кев,
1
Person person = new Person()

хорошо в моей книге.

Ужас становится, когда у вас есть:

string Person;
string person;

Очень легко смешать 2.

Джонно Нолан
источник
1

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

Что касается типов CLR (int, string и т. Д.), Вы можете использовать String или string (и т. Д.) Для объявления типа, поэтому я бы избегал использования чего-то вроде

int Int = 0;
string String = "hi there";
Муад'Диб
источник
1

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

fastPerson / slowPerson, как указано выше, хороши ... они описательны и отличаются от имени типа переменной ... но давай, человек, вызывать int "Int" было бы просто лениво.

Алексвуд
источник
1

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

void SaveToDatabase(Person person) {...}

Единственное, что вы могли бы с полным основанием назвать человеком, это person_to_saveто, что кажется лишним.

Однако во многих случаях вы можете улучшить читаемость кода, заменив person на более информативное имя. Например, это менее наглядно

void AddToAccount(Account account, Person person)  {...}

чем это

void AddToAccount(Account account, Person dependent)  {...}

Однако, пожалуйста, пожалуйста - хорошенько, пожалуйста, не ставьте «a» или «t» перед названием типа. IE aPerson для «человека» или tPerson для «человека». Это слишком сложно и ничего не добавляет. Кроме того, вы начинаете засорять область видимости кучей переменных, которые начинаются с a или t, что может минимизировать значение intelli-sense.

Джошуа
источник
Я согласен с последним абзацем. Я не вижу причин добавлять посторонние символы, чтобы избежать незначительных проблем со стилем.
Джейсон Бейкер,
0

Я бы не сказал, что это ужасно. Я обычно добавляю к имени переменной префикс 'a' в таких вещах, чтобы показать, что это единственный экземпляр типа, поэтому я бы сделал

Person aPerson = new Person();

Думаю, это делает код более естественным.

Роб К
источник
0

Абсолютно ничего плохого в этом нет с учетом оговорок, указанных другими (резюмируя здесь для удобства): не делать этого с примитивными типами, рефакторинг исходного экземпляра, если другой экземпляр добавляется позже, не использовать регистр символов для различения имен классов и т. Д.

Мое практическое правило? Заявления в коде должны читаться как простые английские предложения.

Человек person = новый Человек ();

Сотрудник employee = person.getRole (СОТРУДНИК);

Родитель parent = person.getRole (PARENT);

person.getFullName ();

employee.getSalary ();

parent.getChildren ();

parent.getFullName (); // предполагаем, что шаблон декоратора в игре

if (person.hasRole (СОТРУДНИК)) {

  ...

}

И так далее.

Если область действия переменной ограничена (например, метод инкапсуляции составляет 10-15 строк), я могу даже использовать «p» вместо «person». Более короткие имена переменных меньше отвлекают при попытке удержать контекст в голове. Избегайте бесплатных префиксов, таких как «а» или (вздрогнуть) венгерских обозначений и их ответвлений. (Имейте в виду, я ничего не имею против таких префиксов, когда они используются в соответствующем контексте - код C ++ / COM / ATL / Win32 API и т. Д., Где это помогает сохранять прямое присвоение / приведение типов).

Мои две (!) Биты :-)

алан-п
источник