Все из нас видели это:

private String mName;

Это из-за меня.

Я так и сказал — это моя вина.

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

  1. Как появилась m-нотация.
  2. Почему вы, вероятно, не понимаете, что такое венгерская нотация.

M-нотация


Я был одним из первых инженеров, работающих над Android, и мне было поручено разработать руководство по стилю для Android API (для нас, команды Android) и пользовательского кода. В то время у нас было мало Java разработчиков и мало кода на Java, поэтому разработать руководство до того, как кода будет огромное количество — было очень важным.

Когда дело доходит до определения полей, я становлюсь немного предвзят. В то время я уже написал приличное количество Java, Windows и кода на C ++, и я обнаружил, что использование определенного синтаксиса для полей бывает очень полезным. Microsoft использует m_ для этого, в то время как обычно используется лидирующий символ подчеркивания (например, _name) в C ++. С тех пор, как я начал писать Java-код, меня всегда беспокоил тот факт, что Java отошел от этого соглашения.

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

Поэтому я отложил в сторону свои предубеждения и потратил некоторое время на изучение внутренних руководств по стилю Sun и Google, и я придумал собственное руководство для Android, которое состояло на 99% из того, что предлагалось этими двумя руководствами, но с несколькими очень маленькими изменениями.

Одно из отличий, которое я помню, была связана с фигурными скобками. Хотя для обоих руководств по стилю требуется использовать фигурные скобки для всего, я ввел исключение, когда продолжающий оператор может поместиться в одной строке. Идея этого исключения заключалась в том, чтобы учесть распространенную идиому логирования в Android:

if (Log.DEBUG) Log.d(tag, "Logging");

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

Итак, это была первая версия нашего руководства по стилю, и оно не содержало никаких требований к префиксам у полей.

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

Поэтому я вернулся к своей доске для рисования и обдумал несколько вариантов стандартизации.

Я принял во внимание _name и m_name, как упоминалось выше, но отклонил их, потому что подчеркивание было слишком большим отклонением от стандарта Java. Я столкнулся с несколькими другими, более экзотическими нотациями (например, с использованием префикса «iv» для «instance variable»), но в конечном счете я отклонил их всех. Независимо от того, что я рассматривал, префикс «m» крутился у меня в голове как самый разумный и наименее объемный.

Итак, что было очевидным решением? Берете «m», убираете подчеркивание и используете camelcase. Таким образом родилось mName.

Это предложение было принято командой, и тогда мы сделали это официальным обозначением.

Вероятно, вы не понимаете венгерскую нотацию


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

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

  • Информация о типе.
  • Информация о видимости.
  • Семантическая информация.

Давайте рассмотрим их по очереди.

Информация о типе


Это, пожалуй, наиболее распространенное использование метаданных поля: наименование поля таким образом, чтобы его тип можно было узнать по имени. Это используется повсюду в коде Win32 / 64, где вы видите имена, такие как lpsz_name, для обозначения «Long Pointer to String with a Zero terminator». Хотя эта нотация кажется чрезвычайно многословной и сложно читаемой, фактически у Windows программистов она интерпретируется в голове практически мгновенно, и добавленная информация действительно очень полезна для отладки многих непонятных ошибок, которые могут произойти в недрах системы Windows, в основном из-за очень динамичного характера многих его API и большой зависимости от C и C ++.

Информация о видимости


Это то, что используется в Android: использование метаданных для указания с каким типом переменной вы имеете дело: поля, локального или функционального параметра. Мне сразу стало ясно, что поля действительно являются наиболее важным аспектом переменной, поэтому я решил, что нам не нужны дальнейшие соглашения, чтобы отличать локальные переменные от параметров функции. Еще раз: обратите внимание, что эти метаданные не имеют ничего общего с типом переменной.

Семантическая информация


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

Это соглашение можно использовать, когда вам нужно различать переменные подобных типов, но используемые в разных целях. В большинстве случаев разумное имя приведет вас к цели, но иногда метаданные — единственный выход из ситуации. Например, если вы разрабатываете графический интерфейс, который позволяет пользователю вводить имя, то вы можете иметь несколько вариантов view, называемых «name»: edit text («textName»), text view («tvName»), кнопки для подтверждения или отмены («okName», «cancelName», и так далее...).

В таких примерах важно четко указать, что все эти идентификаторы относятся к одной и той же операции (редактирование имени) при дифференциации их функции (метаданных).

Надеюсь, теперь у вас должно быть более точное представление о венгерской нотации, и я настоятельно рекомендую прочитать статью Джоэла Спольси «Making wrong code look wrong» на эту тему, которая должна помочь понять все эти пункты.

Итак, что вы думаете о венгерской нотации?


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

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

Я также не согласен с аргументом: «Сегодня наши IDE могут различать все эти идентификаторы цветами, чтобы нам больше не нужно было делать этого самим». Этот аргумент ошибочен по двум причинам:

  • Код часто читается вне IDE (начиная, по иронии судьбы, со скриншота, снятого с обсуждения на reddit, у которого нет подсветки). Я читаю код в браузерах, терминалах, diff utils, git tools и т. д. Большинство из них не имеют подсветки, которая бы упростила анализ кода, поэтому использование метаданных идентификатора может помочь в таких случаях.

  • Подсветка в IDE по-прежнему не поможет вам разобраться в неоднозначных случаях, таких как, например, графический интерфейс, описанный выше. Есть еще случаи, когда вы, разработчик, знаете больше о своем коде, чем может знать IDE, и добавление метаданных идентификатора — это единственный разумный выбор, который вы можете сделать.

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

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

Комментарии (88)


  1. Shtucer
    18.07.2017 14:35
    +12

    где вы видите имена, такие как lpsz_name

    Я пойму, что это «Long Pointer to String with a Zero terminator», но еще это и отхождение от гайдлайна. По гайдлайну должно быть lpszName. Знак подчеркивания есть только у "m(ember)" и "g(lobal)".
    Пруф


    Это всё что нам надо знать о проблеме написания и чтении гайдлайнов. :)


    1. BalinTomsk
      18.07.2017 19:51
      +1

      Есть еще s_ для статических переменных in C++.


      1. playermet
        19.07.2017 14:58

        Еще несколько раз видел a(rgument) для аргументов.


    1. Steed
      19.07.2017 14:13

      lpsz_name — корректный вариант при использовнии гайдлайна по префиксам при именовании переменных с_разделением_слов_подчеркиванием. Общий гайдлайн Microsoft включает в себя рекомендации не только по префиксам, но и по именованию (camelCase). Но нет никакой проблемы, что в проекте гайдлайн используется не целиком, а частично.
      А в данном случае это, скорее всего, просто мелкая невнимательность автора, который привел не совсем удачный пример.


  1. habradante
    18.07.2017 16:28
    +28

    Ооо, теперь я знаю имя того, кто притащил эту хрень в Java на Андроид!
    Лично я HN в Java не переношу. Чтобы найти переменную с такой нотацией, надо сначала вспомнить ее тип, угадать какие еще дикие бредни пришли в голову разработчику, когда он решил поставить lpsz или еще что-то, и только потом можно поискать по имени. Вместо того чтобы набрать "." и начать вводить очевидное имя, приходится угадать m, g, lpsz, wtf и пр., и только потом искать по имени.
    Конечно, всегда можно заглянуть в начало класса и посмотреть там, но тогда вообще нет разницы, есть мета или нет.
    А при правильно составленном Coding Conventions, можно избежать вообще необходимости угадывать какие есть поля в классе, обращаясь к нему снаружи, т.к. можно просто прописать работать только через геттеры и сеттеры.


    1. da-nie
      18.07.2017 19:41

      А вы не читали статью Борескова про эту нотацию? :) Он тоже не любит её.


      1. habradante
        18.07.2017 20:41
        +2

        Спасибо, прочитал. :) Я не пишу на С и С++, поэтому стал сталкиваться с такой нотацией уже в более высокоуровневых языках. Не знаю как было в 70-х и 80-х, но тащить это в Java и C# сейчас… мягко говоря, странное решение.


    1. to_climb
      18.07.2017 20:07
      +6

      Не в защиту префиксов (сам их не люблю), но справедливости ради.
      В современных средах после точки можно вводить любой кусок имени идентификатора, сопоставление ищется по подстроке (VisualAssist, например, такое умеет).
      P.S. пардон, ниже уже об этом написали.


    1. Donutellko
      18.07.2017 23:19
      +1

      Вместо того чтобы набрать "." и начать вводить очевидное имя, приходится угадать m, g, lpsz, wtf и пр., и только потом искать по имени.
      Что интересно, если использовать нижнее подчёркивание в именовании, то этого можно почти избежать:

      image


      1. Firsto
        19.07.2017 14:46
        +2

        Автодополнение и без этих префиксов будет точно так же работать.


    1. Steed
      19.07.2017 14:20

      Вы смешали в кучу префиксы по типу и по видимости, от чего автор как раз предостерегает. Если у вас только 'm', то прекрасно понятно, писать его или нет, ведь вы точно знаете, какую переменную ищете — локальную или член класса.


      Coding Conventions не помогут вам в коде метода класса понять, например, использует/изменяет ли данный кусок кода состояние класса (т.е. переменные-члены) и можно ли его отрефакторить,


      1. vintage
        23.07.2017 16:50

        Если я ищу член класса, то я так и пишу: this.


    1. Jamdaze
      19.07.2017 15:15

      Использование средств разработки с не тривиальным поиском после «набрать .» решило бы эту проблему.


  1. Revertis
    18.07.2017 17:35
    +6

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

    И его это «объяснение»:
    Код часто читается вне IDE (начиная, по иронии судьбы, со скриншота, снятого с обсуждения на reddit, у которого нет подсветки). Я читаю код в браузерах, терминалах, diff utils, git tools и т. д. Большинство из них не имеют подсветки, которая бы упростила анализ кода, поэтому использование метаданных идентификатора может помочь в таких случаях.
    Совершенно не причина поганить весь свой код. Дифы, мерджи и другие гитовые операции отлично работают и отображаются с подсветкой в IDEA.


    1. Shtucer
      18.07.2017 17:48

      И?


      1. forceLain
        19.07.2017 12:37
        +8

        DEA


    1. aliksend
      18.07.2017 17:50
      +2

      Вы конечно всё хорошо и правильно написали. Но это справедливо только для тех, кто пользуется IDEA. Но что же делать всем остальным?
      И немного отвечая на комментарий habradante: в IDEA, если я не ошибаюсь, если писать a.Name, он будет подсказывать и .lpszName в том числе (если не в первую очередь)


      1. grossws
        18.07.2017 17:56
        +1

        Будет, но не в первую очередь, если есть более удачные совпадения. Можно также писать a.name и получить подсказку для a.mName или a.CNa и получить a.mComplexName. Нормальный человеческий fuzzy search.


      1. habradante
        18.07.2017 18:08
        +2

        Я Netbeans пользуюсь, он не такой умный. Но искать по коду приходится не только в IDE. Так вот искать/грепать по .name проще и понятнее, чем вспоминать префикс.


        1. Free_ze
          18.07.2017 18:39

          del


        1. netch80
          19.07.2017 07:28
          -1

          Грепать лучше по чему-то уникальному. Просто «name» явно таким не является.


      1. Revertis
        18.07.2017 18:37
        -1

        Но что же делать всем остальным?
        Что может помешать использовать наилучшую Java (да ещё и официальную для Андроида) IDE? Плюс, ещё и бесплатную (Community Version отлично работает с Андроидом).


      1. Free_ze
        18.07.2017 18:37

        del


      1. Flammar
        18.07.2017 19:07

        Те, кто не пользуется IDEA, пользуются Eclipse и немного NetBeans, там тоже есть подсветка полей и переменных.


    1. borv
      18.07.2017 21:22
      +7

      Автор оригинальной статьи, вероятно, как и положено сеньору в Гугеле, проводит больше времени в Gerrit, чем в IDE. А там как раз будет дифф без подсветки и прочего. А тащить ветку локально чтобы посмотреть на нее через IDE это слишком много телодвижений для уважаемого человека.


      Слуга ваш покорный пострадал на прошлой работе в попытках аргументированно объяснить, что код пишет 50 человек и каждый день, а ревью делают 4 и только перед финалом. И исходя из этого раскладывать компонент по 6 местам и фигачить полукилометровые имена с префиксами несколько иррационально. Тем более что за 12 месяцев ни каких замечаний от оных уважаемых людей, кроме соответствия гайдлайнам, я не видел. На что получил вполне ожидаемый ответ — мы есмь четыре всадника апокалипсиса, покайсо холоп и убойся гнева нашего. На том и разошлись. ;-)


      1. apro
        19.07.2017 00:51
        +1

        код пишет 50 человек и каждый день, а ревью делают 4

        А почему всего 4? Всего четыре подсистемы с 4 владельцами?
        Просто у нас перекрестное ревью, и т.к. в команде все "сеньоры",
        то аппроксимируя на ваши цифры 50 пишут и 50 проводят ревью


        и только перед финалом

        перед каким финалом, типа неделю разрабатываешь в отдельной ветке, а
        потом на review отправляешь?


        фигачить полукилометровые имена с префиксами

        полукилометровые из-за одной буквы m вначале?


        1. zagayevskiy
          19.07.2017 19:21
          +1

          У нас тоже перекрёстные ревью, в основном народ смотрит дифф без подсветки. И большинство проголосовало за избавление от префикса m. Что мы делаем не так?


        1. borv
          19.07.2017 22:58

          а почему всего четыре

          потому что так у них повелось. См про качество этого процесса в том же параграфе.


          перед каким финалом

          pull request / git workflow. Ревью делаются на PR.


          полукилометровые из-за одной буквы m

          нет, из-за naming conventions у компонентов и методов. Типа PublicCampaignAnalyticsEventTransitiveViewFactory::analyticsEventCreationTimestamp. Это в общем из той же оперы.


      1. Steed
        19.07.2017 15:09
        +1

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


        1. borv
          19.07.2017 23:04

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


  1. avost
    18.07.2017 17:49
    +1

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


    1. soniq
      18.07.2017 22:23
      +4

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


      1. avost
        19.07.2017 00:52
        +1

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


        1. zuwr2t
          19.07.2017 06:53
          +1

          Исправление нпе в легаси по логу от клиента. Открыл, нашел строку, исправил и забыл.


          1. kolipass
            19.07.2017 07:49

            Где тонко — там и рвётся

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


            1. zuwr2t
              19.07.2017 07:56
              +2

              Вам не заплатят за анализ миллиона строк легаси кода из-за ошибки допущенной 5 лет назад, но впервые проявишейся.
              И в 99% случаев нпе это просто нпе.


              1. kolipass
                19.07.2017 08:09
                +7

                Профессионал всегда делает работу хорошо и до конца, не зависимо от бюджета. Или в другой формулировке: если ты не можешь сделать работу хорошо за небольшие деньги, ты и за большие не сможешь.
                Как код становится 5-ти летним легаси? Да вот так, когда его затыкают проверками на npe, хотя потратив больше времени, можно слегка отрефакторить задев более высокий слой. И, быть может, проверка не понадобится, такая ситуация уйдёт сама собой.
                NPE это симптом, а не болезнь.


                1. zuwr2t
                  19.07.2017 10:56
                  +1

                  НПЕ это просто ошибка.
                  Код становится 5-ти летним легаси через 5 лет. Ставить костыли или вообще как-то шевелиться для этого не нужно.
                  Про сияющие доспехи профессионалов проигнорирую.


                  1. khim
                    19.07.2017 13:09

                    Код становится 5-ти летним легаси через 5 лет.
                    Код становится 5-ти летним легаси после 5 лет втыкания костылей. Глядя на код в нашем проекте 3х летней давности (иногда нужно править ошибки в старых ветках) мне плакать иногда хочется, а с современным его состоянием — нет. Это, собственно, и отличает профессионала от непрофессионала. «Сиять» для этого не нужно, нужно работать.


                  1. zagayevskiy
                    20.07.2017 12:05

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


          1. avost
            19.07.2017 09:24

            А зачем вам для этого знать был null присвоен полю или локальной переменной?


  1. Flammar
    18.07.2017 19:11

    «Как попытаться убить платформу Android»…

    Зачем венгерская нотация в статически типизированных языках???


    1. khim
      18.07.2017 20:27
      +3

      Зачем венгерская нотация в статически типизированных языках???
      Для того, чтобы указать в ней то, что не указано в типе?

      Никогда не понимал использование lpsz (а особенно wParam для 64-битного значения). Но возможность отличать mLength от length — не кажется мне бесполезным. Типы-то у них совпадают… а подсветка, всё-таки, не является частью языка.

      Другое дело, что подчёркивание в конце мне нравится больше — хотя это уже совсем по HN…


      1. soniq
        18.07.2017 22:34

        Учитывая, что те же строки бывают и C-string, и BStr, и ANSI, и Unicode, и const, и out. И ещё черта лысого, а C++ легко кастит все эти типы туда-сюда, от такой нотации много пользы.


        1. khim
          19.07.2017 01:11

          Если «C++ легко кастит все эти типы туда-сюда» и при этом программа работает — то какая вам разница что конкртно там используется? А если не работает — то кто придумал такой API?

          C++ — он, как бы, в отличие от C не умеет «из коробки» преобразовывать друг в друга никак не связанные между собой типы. Его этому нужно учить. И желательно — так, чтобы работало.


          1. Antervis
            19.07.2017 05:53

            Есть разница. Например, передать const (w)char * вместо BSTR это UB, пусть даже и скомпилируется. Кто придумал такой api? Майкрософт, который использовал венгерку


      1. neit_kas
        19.07.2017 01:51
        +1

        Но возможность отличать mLength от length — не кажется мне бесполезным.

        Мне для этих целей больше this использовать понравилось. Правда C++ использую. Использование полей с this может и длиннее, но без него я знатно путался.


        1. khim
          19.07.2017 02:17
          +1

          В Python, где другого способа нет — это работает, в C++/Java — нет. Потому что пропущенный this-> не приводит к ошибке компиляции и в рантайме тоже «стреляет» не сразу. Хотя выглядит красиво, бесспорно.


          1. zagayevskiy
            20.07.2017 12:06

            пропущенный m, как не странно, тоже не приводит к ошибке компиляции


            1. khim
              20.07.2017 17:07

              Только в тех случаях, когда у вас есть аналогичная переменная без «m». Такого лучше в функциях длиннее трёх строк (читай: конструкторы) просто не допускать. А this-> пропущенный компилируется всегда — и потому отсутствию this-> доверять нельзя никогда, что и делает его бессмысленным.


        1. knotri
          19.07.2017 13:47

          В javascript также — все поля и методы только через this
          Когда только начинал учить после других языков — страшно бесило


          Но сейчас (я стал фронтенд-ом) мне это очень нравится.


    1. MrErsh
      19.07.2017 07:46

      Похоже вы не понимаете что такое венгерская нотация. Почитайте статью подробнее и вопрос отпадёт.


  1. Antervis
    18.07.2017 21:06
    +4

    Венгерская нотация явно имела повод для существования во времена программирования в блокнотах. Зачем префикс m или m_ к имени сейчас, если IDE выделяет поля класса цветом? Пользуюсь лидирующим _ для полей в с++ только лишь для того, чтобы писать нормальные имена для геттеров: скажем, поле _initialized, геттер initialized()

    Префиксы типа, аля lpwzPath, конечно, нагляднее, чем переходить к месту определения переменной в IDE, но существенно увеличивают объем кода. В итоге его становится сложнее читать попросту потому, что его много.

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


    1. DrLivesey
      19.07.2017 11:10

      del


    1. Free_ze
      19.07.2017 12:40
      +1

      Зачем префикс m или m_ к имени сейчас, если IDE выделяет поля класса цветом?

      Чтобы автокомплит отфильтровал поля класса среди методов, статических полей и прочего.


      1. Antervis
        19.07.2017 14:28

        название метода/класса и сотни других вещей тоже может начинаться с m. Зато названия публичных методов/классов не могут начинаться с _


        1. Free_ze
          19.07.2017 14:35

          Тем и странен выбор «m» вместо «m_».


      1. zagayevskiy
        20.07.2017 12:08

        То есть вы жмёте m и дальше в списке ищете нужное имя? Или всё же пишите 2-4 первые буквы?


        1. Free_ze
          21.07.2017 13:44

          Если человек, придерживающийся этой нотации, хочет увидеть в автокомплите список членов типа, то он жмет «m_».


  1. asmrnv777
    18.07.2017 21:18
    +3

    Префиксы типа mObject в андроиде — зло. Нет, если пишешь код в блокноте, может и полезно, но абсолютное большинство разработчиков пользуется нормальными IDE, в которых эти префиксы только мешают, кроме того, приходится рефакторить скопипащенный код для «обычной» джавы, чтобы не перемешивать стили.
    Префиксы/постфиксы типа tvName — штука полезная из-за того, что может быть, грубо говоря, TextView для имени, и может быть CheckBox для имени: они удобны, чтобы не выдумывать новые имена для объектов.

    Итого: я пользуюсь постфиксами для объектов типа View (nameTv, nameEt, nameBtn и т.д.), а префиксами для полей перестал пользоваться где-то через полтора года после начала разработки под Android, когда понял, что они бесполезны.


  1. DSolodukhin
    18.07.2017 21:48
    +3

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


  1. Ritorno
    18.07.2017 21:48
    +1

    Один из многих холиваров на тему стиля, только и всего.


  1. nixel
    18.07.2017 21:48
    +2

    Я понимаю, что статья про другое, но… Неужели человек, разрабатывающий гайдлайн для разработчиков не догадался увести if (Log.Debug) внутрь функции Log.d? И никаких однострочников и холиваров про скобки…


    1. Nakosika
      18.07.2017 22:24
      +2

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


      1. izzholtik
        18.07.2017 23:11

        В андроиде всё сделано так, как было проще разработчику андроида.


        1. Nakosika
          18.07.2017 23:50
          +2

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


    1. dion
      18.07.2017 22:27
      +2

      Разница в том что в случае с if внутри аргументы Log.d будут вычисляться даже если логи выключены.


    1. Iqorek
      18.07.2017 22:48

      if намного быстрей, чем вызов функции.


      1. grossws
        19.07.2017 00:30

        В случае openjdk/oracle jdk зачастую if вне функции и внутри одинаковы по времени после JITа. Существенное отличие — сбор строки для логгирования (вычисление аргументов). В том же slf4j пошли путём использования интерполяции уже внутри вызова логгера.


        1. khim
          19.07.2017 01:21

          С первой же миллисекунды быстрее? Извините, но… Не верю. JITу нужно долго «прогреваться», «разгоняться» — и в новых версиях Java этот процесс не становится более быстрым.

          А процессы в Андроиде должны умирать и рождаться незаметно для пользователя и «свежезапущенный» процесс должен работать так же, как «прогретый». Зачем такую систему вообще сотворить на Java — отдельный вопрос, но раз уж сотворили, то закладываться на JIT не стоит…


          1. grossws
            19.07.2017 02:24
            +1

            С первой же миллисекунды быстрее? Извините, но… Не верю. JITу нужно долго «прогреваться», «разгоняться» — и в новых версиях Java этот процесс не становится более быстрым.

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


            А процессы в Андроиде должны умирать и рождаться незаметно для пользователя и «свежезапущенный» процесс должен работать так же, как «прогретый». Зачем такую систему вообще сотворить на Java — отдельный вопрос, но раз уж сотворили, то закладываться на JIT не стоит…

            Они с ART сейчас вообще пошли в сторону AOT-компиляции. Но вообще решения по тому что лучше стоит принимать не исходя из того, что "на JIT закладываться не стоит", а исходя из результатов профилирования.


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


            1. khim
              19.07.2017 02:40

              Но логгер дёргают достаточно часто, и его методы должны прогреться довольно быстро.
              Чтобы достичь скорости, которую даёт описанный в статье if «прогреть» нужно не логгер, а, фактически, всю программу — чтобы метод за'inline'ился и потом исчез…

              Но вообще решения по тому что лучше стоит принимать не исходя из того, что «на JIT закладываться не стоит», а исходя из результатов профилирования.
              Это смотря чего вы хотите добиться. Подход, описанный в статье, не только ускоряет код, но и уменьшает его. А по моему опыту тут — профилирование не работает. В типичной программе есть, как правило, участки, на выполнение которых уходит 90% времени, но нет участков, которые занимают 90% объёма.


              1. grossws
                19.07.2017 02:52

                Чтобы достичь скорости, которую даёт описанный в статье if «прогреть» нужно не логгер, а, фактически, всю программу — чтобы метод за'inline'ился и потом исчез…

                Даже компиляция всего метода с выделенным hot path, который делает просто ret для trace/debug уже даёт очень неплохой результат. Останется нелокальный переход, но это не столь страшно. Кроме того, настройка логгирования (включение, например, debug для определенного package'а) может меняться во время жизни приложения, что вызовет deopt и компиляцию когда-нибудь в будущем. Мне сейчас, честно говоря, несколько лень брать в руки JMH чтобы сравнить эти два варианта.


                Это смотря чего вы хотите добиться. Подход, описанный в статье, не только ускоряет код, но и уменьшает его. А по моему опыту тут — профилирование не работает. В типичной программе есть, как правило, участки, на выполнение которых уходит 90% времени, но нет участков, которые занимают 90% объёма.

                Не сказал бы, что уменьшает:


                if (Log.DEBUG) Log.d(tag, "someVar=" + someVar + ", anotherVar=" + anotherVar);
                // versus
                log.debug(tag, "someVar={}, anotherVar={}", someVar, anotherVar);


      1. nixel
        19.07.2017 15:56

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


    1. zagayevskiy
      20.07.2017 12:10
      +1

      Кажется, это про оптимизацию. Не уверен, что компилятор выкинет вызов метода, даже если он пустой. А if(false) выкинет.


  1. Iqorek
    18.07.2017 22:53

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


    1. khim
      19.07.2017 01:24
      +1

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

      На C++ код, написанный человеком с 10 годами работы на Java тоже без слёз не взглянешь. Тормоза получаются знатные.


      1. Antervis
        19.07.2017 06:00
        +2

        тормоза — полбеды. Сотни new без единого delete там, где объект мог бы вообще лежать на стеке — вот по чему рефакторинг плачет


      1. Iqorek
        19.07.2017 12:23

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


  1. september669
    19.07.2017 07:22

    Так и не понял зачем было вообще изобретать свой code style, когда есть готовый общепринятый java code style?


    1. grossws
      19.07.2017 12:22

      Это который из?


      1. Regis
        21.07.2017 16:06

        По большому счету, почти любой существующий был бы лучше, чем новый.


  1. DrLivesey
    19.07.2017 11:12
    +2

    Как пример lpwzPath прекрасен, но это все прекрасно работает, если есть готовый LLD и нет никаких отклонений.


    Приведу пример:


    uint16_t mu16_InstanceId;

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


    После такого diff будет выглядеть довольно раздуто.


  1. apro
    19.07.2017 14:08
    +3

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


  1. elmal
    19.07.2017 14:55
    +1

    Странно. Я вообще начинал с венгерки. Думал что она прекрасна, позволяет избежать ошибок и т.д. Потом пересел на Java, поработал в нормальных IDE, и для меня необходимость в венгерке отпала. А после того, как пописал на языках, где есть функционал val (или auto), то есть тип слева от переменной можно не указывать, почему то пришло понимание, что это тоже очень хорошо. Пришло понимание, что нужно думать об имени переменной, а не о типе, о типе должен компилятор, а не я, постоянно помнить. В результате гораздо стало проще рефакторить а также гораздо проще читать код. Ошибаться стал меньше, чем когда венгерку использовал.


    Учитывая, что сейчас я в имени никакую информацию о типах стараюсь не давать, а то и вообще типы явно не указываю, то следует ли считать, что лет 15 назад я был лучшим разработчиком, чем сейчас :)? Я ведь тогда многое что делал дополнительно, еще и когда скобочку закрывал, я в комментах писал к чему эта скобочка относится и тому подобное. А сейчас забил на это, и просто делаю методы короткими, а имена максимально понятными.


    1. zodchiy
      19.07.2017 15:08

      Это опыт. Большинство с опытом пишут более простой и лаконичный код на «автомате».


  1. r_ii
    19.07.2017 19:36

    Все эти lpsz рождались когда не было никакой подсветки синтаксиса и такая нотация была вполне оправдана. Позже контекстная подсветка появилась в Visual Assist для Visual Studio. Позже был Resharper с опцией «highlight usage». А еще позже появился Android. Насколько помню даже тогда Eclipse имел подсветку синтаксиса и наверняка умел отличить локальную переменную от поля класса. Ну если не имел, то NetBeans и Intellij Idea уж точно имели, так что не было никакой необходимости тащить этот костыть в Android.


    1. khim
      19.07.2017 19:47
      +1

      Всё проще: если чего-то не умеет Gerrit, то неважно чего там умеет NetBeans, IntelliJ Idea или Eclipse. Gerrit подсветку синтаксиса умеет, но отличать локальные переменные от полей класса — нет. Всё. Вопрос закрыт. Для разработчиков Android, разумеется.

      Ваш workflow может отличаться и вам, возможно, этот префис-суффикс и не нужен…