Я являюсь причиной появления венгерской нотации в Android

http://beust.com/weblog/2017/07/17/i-am-the-reason-for-hungarian-notation-in-android/
  • Перевод
Все из нас видели это:

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
  • +12
    где вы видите имена, такие как lpsz_name

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


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

    • +1
      Есть еще s_ для статических переменных in C++.
      • 0
        Еще несколько раз видел a(rgument) для аргументов.
      • 0

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

      • +28
        Ооо, теперь я знаю имя того, кто притащил эту хрень в Java на Андроид!
        Лично я HN в Java не переношу. Чтобы найти переменную с такой нотацией, надо сначала вспомнить ее тип, угадать какие еще дикие бредни пришли в голову разработчику, когда он решил поставить lpsz или еще что-то, и только потом можно поискать по имени. Вместо того чтобы набрать "." и начать вводить очевидное имя, приходится угадать m, g, lpsz, wtf и пр., и только потом искать по имени.
        Конечно, всегда можно заглянуть в начало класса и посмотреть там, но тогда вообще нет разницы, есть мета или нет.
        А при правильно составленном Coding Conventions, можно избежать вообще необходимости угадывать какие есть поля в классе, обращаясь к нему снаружи, т.к. можно просто прописать работать только через геттеры и сеттеры.
        • 0
          А вы не читали статью Борескова про эту нотацию? :) Он тоже не любит её.
          • +2
            Спасибо, прочитал. :) Я не пишу на С и С++, поэтому стал сталкиваться с такой нотацией уже в более высокоуровневых языках. Не знаю как было в 70-х и 80-х, но тащить это в Java и C# сейчас… мягко говоря, странное решение.
          • +6
            Не в защиту префиксов (сам их не люблю), но справедливости ради.
            В современных средах после точки можно вводить любой кусок имени идентификатора, сопоставление ищется по подстроке (VisualAssist, например, такое умеет).
            P.S. пардон, ниже уже об этом написали.
            • +1
              Вместо того чтобы набрать "." и начать вводить очевидное имя, приходится угадать m, g, lpsz, wtf и пр., и только потом искать по имени.
              Что интересно, если использовать нижнее подчёркивание в именовании, то этого можно почти избежать:

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

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


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

                • 0

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

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

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

                    И?

                  • +2

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

                    • +1

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

                      • +2
                        Я Netbeans пользуюсь, он не такой умный. Но искать по коду приходится не только в IDE. Так вот искать/грепать по .name проще и понятнее, чем вспоминать префикс.
                        • 0
                          del
                          • –1
                            Грепать лучше по чему-то уникальному. Просто «name» явно таким не является.
                          • –1
                            Но что же делать всем остальным?
                            Что может помешать использовать наилучшую Java (да ещё и официальную для Андроида) IDE? Плюс, ещё и бесплатную (Community Version отлично работает с Андроидом).
                            • 0
                              del
                              • 0
                                Те, кто не пользуется IDEA, пользуются Eclipse и немного NetBeans, там тоже есть подсветка полей и переменных.
                              • +7

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


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

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

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


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

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


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

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

                                  • +1

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

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

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


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

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


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

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

                                    • +1

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

                                      • 0

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

                                  • +1

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

                                    • +4

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

                                      • +1

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

                                        • +1
                                          Исправление нпе в легаси по логу от клиента. Открыл, нашел строку, исправил и забыл.
                                          • 0
                                            Где тонко — там и рвётся

                                            Всегда стараюсь тушить на корню такие фиксы: обязательно нужно разбираться во всей системе, познать предпосылки и причину аварийного состояния.
                                            Добавить проверку на нул, это не исправить, это отодвинуть ошибку в другое место. Авось, в другом месте и не упадёт, не космолёт же пишем?
                                            • +2
                                              Вам не заплатят за анализ миллиона строк легаси кода из-за ошибки допущенной 5 лет назад, но впервые проявишейся.
                                              И в 99% случаев нпе это просто нпе.
                                              • +7

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

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

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

                                              • 0

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

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

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

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

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

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

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

                                                C++ — он, как бы, в отличие от C не умеет «из коробки» преобразовывать друг в друга никак не связанные между собой типы. Его этому нужно учить. И желательно — так, чтобы работало.
                                                • 0
                                                  Есть разница. Например, передать const (w)char * вместо BSTR это UB, пусть даже и скомпилируется. Кто придумал такой api? Майкрософт, который использовал венгерку
                                              • +1
                                                Но возможность отличать mLength от length — не кажется мне бесполезным.

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

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

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

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


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

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

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

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

                                                    del

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

                                                      Чтобы автокомплит отфильтровал поля класса среди методов, статических полей и прочего.
                                                      • 0
                                                        название метода/класса и сотни других вещей тоже может начинаться с m. Зато названия публичных методов/классов не могут начинаться с _
                                                        • 0
                                                          Тем и странен выбор «m» вместо «m_».
                                                        • 0

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

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

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

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

                                                              • +2

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

                                                                • 0

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

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

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

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

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

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

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

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


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

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


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

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

                                                                            Но вообще решения по тому что лучше стоит принимать не исходя из того, что «на JIT закладываться не стоит», а исходя из результатов профилирования.
                                                                            Это смотря чего вы хотите добиться. Подход, описанный в статье, не только ускоряет код, но и уменьшает его. А по моему опыту тут — профилирование не работает. В типичной программе есть, как правило, участки, на выполнение которых уходит 90% времени, но нет участков, которые занимают 90% объёма.
                                                                            • 0
                                                                              Чтобы достичь скорости, которую даёт описанный в статье 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);
                                                                      • 0
                                                                        я не особо разбираюсь в дебрях JIT и прочих возможностей оптимизации java-кода, но даже если это все вдруг не сработает, потери на сопровождение такого кода по всей кодовой базе приложения имхо дороже, чем потеря производительности нескольких мили-(микро?)секунд на вызове функции.
                                                                      • +1

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

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

                                                                          На C++ код, написанный человеком с 10 годами работы на Java тоже без слёз не взглянешь. Тормоза получаются знатные.
                                                                          • +2
                                                                            тормоза — полбеды. Сотни new без единого delete там, где объект мог бы вообще лежать на стеке — вот по чему рефакторинг плачет
                                                                            • 0
                                                                              Да, при переходе с си на язык вроде java и обратно, нужно мозг менять практически целиком. У них слишком много противоположных подходов в ключевых местах.
                                                                          • 0
                                                                            Так и не понял зачем было вообще изобретать свой code style, когда есть готовый общепринятый java code style?
                                                                            • 0

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

                                                                              • 0

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

                                                                            • +2

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


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


                                                                              uint16_t mu16_InstanceId;

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


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

                                                                              • +3

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

                                                                                • +1

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


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

                                                                                  • 0
                                                                                    Это опыт. Большинство с опытом пишут более простой и лаконичный код на «автомате».
                                                                                  • 0
                                                                                    Все эти lpsz рождались когда не было никакой подсветки синтаксиса и такая нотация была вполне оправдана. Позже контекстная подсветка появилась в Visual Assist для Visual Studio. Позже был Resharper с опцией «highlight usage». А еще позже появился Android. Насколько помню даже тогда Eclipse имел подсветку синтаксиса и наверняка умел отличить локальную переменную от поля класса. Ну если не имел, то NetBeans и Intellij Idea уж точно имели, так что не было никакой необходимости тащить этот костыть в Android.
                                                                                    • +1
                                                                                      Всё проще: если чего-то не умеет Gerrit, то неважно чего там умеет NetBeans, IntelliJ Idea или Eclipse. Gerrit подсветку синтаксиса умеет, но отличать локальные переменные от полей класса — нет. Всё. Вопрос закрыт. Для разработчиков Android, разумеется.

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

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