Пишет "это". перед переменной экземпляра и методами хорошего или плохого стиля?

Одна из моих неприятных (?) Привычек программирования на C++ и Java - всегда предшествовать вызовам или доступу к членам с this. Например: this.process(this.event).

Некоторые из моих учеников прокомментировали это, и мне интересно, учу ли я вредным привычкам.

Мое объяснение:

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

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

Примечание: я превратил его в CW, поскольку на самом деле нет правильного ответа.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
35
0
4 427
20

Ответы 20

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

this.fieldName = fieldName

При присвоении поля.

Тем не менее, если вам по какой-то причине нужен способ различать поля, я предпочитаю "this.fieldName" другим соглашениям, таким как "m_fieldName" или "_fieldName"

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

Allain Lalonde 29.09.2008 15:02

Из любопытства: подчеркивание следует использовать только в Java в константах, где camelCase не применяется. Или я не прав?

Georgi 29.09.2008 23:00

Подчеркивание @Georgi можно использовать в Java для любого идентификатора. «следует» - это только вопрос соглашения о кодировании. подчеркивание допустимо где угодно в любом идентификаторе Java.

Aaron 01.10.2008 21:00

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

Peter Lawrey 28.03.2009 10:11

@Georgi Java может использовать практически любой символ Юникода, для которого Character.isJavaIdentifierStart или isJavaIdentifierPart истинно. Без использования случайных значений Unicode оба _ и $ являются допустимыми идентификаторами Java. Их использование считается дурным тоном!

KitsuneYMG 13.05.2010 01:16

Думаю, более читабельно. Я делаю это по-твоему по точно таким же причинам.

С точки зрения .Net, некоторые из инструментов анализа кода, которые я использовал, видели «это» и сразу же пришли к выводу, что метод не может быть статическим. Это может быть что-то для тестирования с Java, но если он делает то же самое, вам может не хватать некоторых улучшений производительности.

Статические методы и методы экземпляра не имеют существенной разницы в производительности в реальном мире. Разница составляет 0 или 1 такт в зависимости от метода. Если вам это небезразлично, то в любом случае .NET - неправильная платформа.

Greg Beech 29.09.2008 04:40

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

Это очень субъективная вещь. В Microsoft StyleCop есть правило, требующее квалификатора это. (хотя оно связано с C#). Некоторые люди используют подчеркивание, некоторые - странные венгерские обозначения. Я лично квалифицирую участников с это., даже если это явно не требуется, чтобы избежать путаницы, потому что бывают случаи, когда это может сделать код более читаемым.

Вы также можете проверить этот вопрос:
Какой префикс вы используете для переменных-членов?

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

user22044 29.09.2008 08:20

@saratav: Я понимаю вашу точку зрения, а как насчет параметров? По сути, они локальны для метода и не нуждаются в уточнении ... Наличие 'this' позволяет вам ЗНАТЬ, что это не параметр.

Neil N 17.06.2009 01:10

Я бы сказал, что самое главное - это последовательность. Есть разумные аргументы «за» и «против», поэтому выбор подхода в основном вопрос вкуса.

Иногда мне нравится писать такие уроки:

class SomeClass{
    int x;
    int y;

    SomeClass(int x, int y){
        this.x = x
        this.y = y
    }
}

Это упрощает определение того, какой аргумент устанавливает какой член.

Я думаю, что это единственный раз, когда рекомендуется использовать "this" в качестве префикса.

Bill the Lizard 29.09.2008 04:32

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

Jason Baker 29.09.2008 05:10

Я стараюсь сделать это единственный раз, когда использую префикс «это».

Heath Borders 29.09.2008 18:06

@Bill: this также может понадобиться при использовании внутренних классов. Если вам нужно устранить неоднозначность между внутренним классом и содержащим его классом, вам понадобится SomeClass.this.

idbrii 20.01.2011 03:52

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

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

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

Я всегда использовал это ... Затем коллега указал мне, что в целом мы стремимся сократить ненужный код, поэтому разве это правило не должно применяться и здесь?

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

Uri 29.09.2008 07:08

Но более длинные имена переменных служат определенной цели. Возникает вопрос, так ли это. больше похоже на преобразование i в rowIndex или преобразование retVal в returnValueThatHasBeenCreatedButNotVerifiedAndIsThereforeBei‌ ngHeldHere.

Guvante 29.09.2008 15:12

Если вы собираетесь избавиться от необходимости добавлять это. перед переменными-членами, инструменты статического анализа, такие как Checkstyle, могут оказаться неоценимыми при обнаружении случаев, когда переменные-члены скрывают поля. Удалив такие футляры, вы, в первую очередь, избавитесь от необходимости использовать это. При этом я предпочитаю игнорировать эти предупреждения в случае конструкторов и установщиков, чем придумывать новые имена для параметров метода :).

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

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

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

@Uri: Я не уверен, что вижу, как привычки smalltalk просачиваются в Python, но, возможно, есть какая-то завуалированная связь.

S.Lott 29.09.2008 05:40

Я имел в виду, что в smalltalk вы должны послать сообщение чему-то, даже «self msg», «super msg» и т. д.

Uri 01.10.2008 08:32

@Uri: Попался - self.whatever в smalltalk очень похож на self.whatever () в Python. Совершенно ясно, где найти определение чего угодно.

S.Lott 01.10.2008 16:29

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

«Читаемость»

Я нашел полезным использование "this", особенно когда не используется IDE (небольшие быстрые программы).

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

т.е.

//Before
this.calculateMass();
this.perfornmDengerAction();
this.var = ...
this.other = ...

После «рефакторинга»

// after
this.calculateMass();
riskDouble.calculateMass();
riskDouble.setVar(...);
this.other = ... 

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

class Employee {

        void someMethod(){
             // "this" shows somethings odd here.
             this.openConnectino() ; // uh? Why an employee has a connection???
             // After refactor, time to delegate.
             this.database.connect(); // mmhh an employee might have a DB.. well.. 
         }
     ... etc....
}

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

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

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

public void setFoo(String foo) {
    this.foo = foo; //member assignment
}

public doSomething() {
    doThat(); //member method
}

У меня есть коллеги, которые предпочитают:

public void setFoo(String foo) {
    _foo = foo;
}

3 причины (костюм Nomex НА)

1) Стандартизация

2) Читаемость

3) IDE

1) ГлавныйНе является частью стиля кода Sun Java.

(Нет необходимости иметь какие-либо другие стили для Java.)

Так что не делайте этого (на Java).

Это часть «синего воротничка» в Java: всегда везде одно и то же.

2) Читаемость

Если вы хотите this.to иметь this.this перед каждым this.other this.word; вы действительно думаете, что это улучшает читаемость?

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

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

Если вы хотите узнать, находится ли метод в родительском классе ваших классов или нет ... не забудьте указать @Override в своих объявлениях и позволить компилятору сообщить вам, если вы неправильно переопределите. super.xxxx () является стандартным стилем в Java, если вы хочу вызываете родительский метод, в противном случае оставьте его.

3) IDE Любой, кто пишет код без IDE, который понимает язык и дает схему на боковой панели, может сделать это самостоятельно. Понимая, что если это не чувствительно к языку, вы попали в ловушку 1950-х годов. Без графического интерфейса: в ловушке 50-х.

Любая достойная IDE или редактор сообщит вам, откуда взялась функция / переменная. Даже исходный ВП (<64 КБ) сделает это с помощью CTags. Есть просто нет оправдания для использования дрянных инструментов. Хорошие раздаются бесплатно !.

Есть веская техническая причина предпочесть или отказаться от использования this - эти два понятия не всегда эквивалентны.

Рассмотрим следующий код:

int f();

template <typename T>
struct A
{
  int f();
};

template <typename T>
struct B : A<T>
{
  int g()
  {
    return f();
    return this->f();
  }
};

Теперь в f() есть два вызова B<T>::g(). Можно было бы ожидать, что он будет называться A<T>::f(), но только второй. Первый назовет ::f(). Причина этого в том, что, поскольку A<T> зависит от T, поиск обычно не находит его. this, будучи указателем на B<T>, также зависит от T, поэтому, если вы его используете, поиск будет отложен до тех пор, пока не будет создан экземпляр B<T>.

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

Я думаю об этом как об еще одном способе поломки C++ ... также обратите внимание, что второй вызов f никогда не будет вызван, потому что 1-й - это оператор возврата B-)

Brian Postow 13.05.2010 00:56

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

if (0 == someValue)
{
    ....
}

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

if (someValue = 0)

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

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

Причины, которые я слышал, в основном сводятся к «наилучшей практике», как правило, со ссылкой на Эффективная Java Джоша Блоха, которая имеет здесь огромное влияние. На самом деле, однако, Блох даже не использует его там, где даже я думаю, что ему, вероятно, следует улучшить читаемость! Опять же, похоже, что это больше похоже на то, что делают люди, которым приказывают делать это и не знают почему!

Лично я склонен больше согласиться с тем, что говорит Брюс Экель в книге «Мышление на Java» (3-е и 4-е издания):


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


сноска, стр. 169, «Мышление на Java», 4-е издание

Довольно. Меньше значит больше, люди.

Я использую this как минимум по двум причинам:

Причины заблуждений

Мне нравится иметь согласованные стили кода при кодировании на C++, C, Java, C# или JavaScript. Я продолжаю использовать тот же стиль кодирования, в основном вдохновленный java, но вдохновленный другими языками.

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

Мой код довольно многословен. Имена моих методов могут быть длинными (или нет). Но они всегда используют полные имена и никогда не используют сжатые имена (например, getNumber(), а не getNbr()).

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

Когда они научатся писать «исключение» или «класс», я снова подумаю обо всем этом ...

Реальные причины

Хотя я ценю работу компилятора, есть некоторые двусмысленности, которые я хотел бы внести в UN-неоднозначности.

Например, я (почти) никогда не использую using namespace MyNamespace. Я использую либо полное пространство имен, либо трехбуквенный псевдоним. Мне не нравятся двусмысленности, и мне не нравится, когда компилятор внезапно сообщает мне, что слишком много функций "print" сталкиваются друг с другом.

По этой причине я добавляю к функциям Win32 префикс глобального пространства имен, т.е. всегда пишу ::GetLastError() вместо GetLastError().

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

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

Мое заключение?

В общем, проблема в основном стиля, и по чисто техническим причинам. Я не хочу смерти того, кто не пишет this.

Что касается цитаты Брюса Экеля из его "Thinking Java" ... Меня не особо впечатлили предвзятые сравнения Java / C++, которые он продолжает делать в своей книге (и, как ни странно, отсутствие сравнения с C#), поэтому его личная точка зрения на this , сделано в сноске ... Ну ...

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

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

Другие вопросы по теме