brainFuckProgrammImage Все началось лет 8 назад. Я тогда писал одну программу для математических расчетов, и мой преподаватель указал, что я неверно именую переменные. Он был прав: x, xx, xxx сложновато различить в коде. После переименования они превратились в redSegment, greenSegment, blueSegment (в контексте задачи именование было подходящее). Потом были «Рефакторинг» Фаулера, «Совершенный код» Макконнелла, «Паттерны проектирования» банды четырех… каждый день я погружался все глубже в бездну.

В моей текущей компании никто не упоминает о правильном именовании переменных, это несерьезно. Мы обсуждаем с коллегами стили именования тестов, стоит ли использовать TestCase атрибут в nUnit, спорим о целесообразности #region в C#, пишем кастомные анализаторы для своих проектов и пьем смузи вообще всячески наслаждаемся жизнью.

Осознание проблемы началось с тестового задания одного кандидата (весь код в публикации изменен, NDA).

foreach (Dot d in dots)
{
    WriteToOutput(d.X, d.Y);
}

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

Через пару часов я наткнулся на код в sql скрипте

select u.* from Users u

Еще через несколько минут в соседнем скрипте обнаружился кусок

select u.UserName, b.Locked, d.PropertyValueStrings
from Users u
join Bindings b on b.UserId = u.UserId
join Dossiers d on d.UserId = u.UserId
where u.UserName = 'USERNAME'

Последовал диалог с автором:

— Почему ты используешь u,b,d вместо нормальных имен?
— Так короче.

Вы знаете, этот аргумент абсолютно верен. Действительно, так короче.

А как насчет

select bi.BusinessIdentifir, bia.SSAFA, IsNull(bia.Bullshit, ‘Bullshit’), bis1.*, bis2.*, bis.*
from businessItems bi 
    inner join businessItemsArtifacts bia on ...
    inner join businessItemsSegment bis1 on ...
    inner join businessItemsSegment bis2 on ...
    inner join businessItemsSegment bis3 on ...
where 
bia.Date = @creationDate
and bi.Staus = ‘RFW’
AND
(
	(bis1.SignIn = ‘Europe’ and ss2.Limit = 42 and bis3.Connection not in (‘Towel’, ‘Galaxy’))
OR
	(bis1.SignIn = ‘USA’ and ss3.Limit = 146 and bis2.Connection not in (‘Trump’, ‘Klinton’))
	OR
(bis1.PNH = ‘SP’ and ss2.Limit = 21 and bis3.Connection not in (‘Stan’, ‘Kyle’, 'Cartman'))	
)

Запрос и так полон специфических констант и фильтров, неужели нужно усложнить его bis1, bis2, bis3?

Но добил меня

SELECT 
     MFID# as MemberId,
     TRIM(ACX) as FirstName,
     TRIM(ABX) as LastName,
     TRIM(FGS) as Suffix,								
     TRIM(c.DSC) as Country,
     TRIM(mm.CCC) as CountryCode,								
FROM {0}.mailfl
    LEFT OUTER JOIN BDSMTAMDRT.MEMFLT mm ON MFID# = mm.MMID#
    LEFT OUTER JOIN BDSMTAMDRT.CTRCOD c ON mm.CCC = c.CCTRY
WHERE mfid# = ?

Автор дал вменяемые имена выбираемым полям, но не поименовал таблицы.

Знаете, откуда берется эта привычка у шарпистов? Из учебной литературы.

Открываем Шилдта:

var posNums = nums.Where(n => n > 0).Select(r => r);

Открываю msdn:

IEnumerable<int> squares =
    Enumerable.Range(1, 10).Select(x => x * x);

Открываю Троелсена:

List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);

Metanit, professorweb — везде вылезает

numbers.Select(n => ...), teams.Select(t => ...)

А потом в коде возникают артефакты вроде

team.Select( p => p.Age > 18);

Еще одна причина появления «коротышек»: изменения в коде. Был однострочный запрос с таблицей Products, городить именования не особо нужно, оставили p. Потом добавили join на ProductGroups, появилась pg, просто чтобы не изменять текущий стиль. Потом кусок кода скопипастили в другой запрос, там join на Profiles, в итоге имеем p, pg, pr.

Вместо послесловия. На самом деле проблема вовсе не в «плохом» коде. Проблема в том, что подобные куски попадаются мне уже год, а внимания на них я обратил лишь сейчас. Возникает вопрос: сколько еще недочетов лежит на самом видном месте?
Встречаются ли вам плохо именованные объекты?

Проголосовало 384 человека. Воздержалось 100 человек.

Мешают ли вам плохо именованные объекты?

Проголосовало 379 человек. Воздержалось 103 человека.

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

Поделиться с друзьями
-->

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


  1. Anger22
    10.05.2017 10:39

    Это еще ладно, самое противное когда называют члены класса и локальные переменные(а еще хуже аргументы) в методе этого-же класса одинаковыми идентификаторами.


    1. Oxoron
      10.05.2017 10:45

      Это характерно для конструкторов, лечится через style-guide. Переменные\параметры именуются как var, закрытые поля — _filed, открытые поля Field.
      Кстати, вы в чем разрабатываете? VS + R# вроде подсвечивают конфликты такого рода.


      1. Anger22
        10.05.2017 10:47
        +1

        До недавнего времени C++, сейчас C# скрипты для игр на Unity


        1. Oxoron
          10.05.2017 10:53

          Тогда только style-guide. Или Rider посмотреть, авторы вроде хотели его для Unity программистов предлагать.


          1. Anger22
            10.05.2017 11:01
            +1

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


            1. SbWereWolf
              10.05.2017 14:48

              дать имя переменной одна из двух самых сложных проблем программирования :)

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


  1. aquamakc
    10.05.2017 10:39
    +10

    Справедливости ради многие такие «сокращения» — условно принятые сообществом соглашения. Например:

    for(int i = 0; i < 10;i++){}
    

    Сокращение? Да.
    Осмысленное? Нет.
    Условно принятое, как норма и применяемое повсеместно? Да.
    Также и с лямбдами x.

    Лично для себя выработал правило — если переменная «локальная» для одной функции (или даже для части функции — можно и сократить Dot до d. Но если уж сократил так в одном месте — давай точно такое-же сокращённое имя в других местах кода. Если переменная относительно глобальная (например, публичное свойство объекта класса) тут уж будь добр — дай осмысленное имя.


    1. Oxoron
      10.05.2017 10:48

      Циклы — да, это уже норма. Хотя во вложенных циклах «коротышки» уже могут напрягать.

      По второй части: однострочники имеют обыкновение дополняться со временем. И переменная-«коротышка» может жить и в разросшемся скрипте.


      1. aquamakc
        10.05.2017 11:00
        +1

        однострочники имеют обыкновение дополняться со временем. И переменная-«коротышка» может жить и в разросшемся скрипте

        А вот это уже проблема кодинга. «Спагетти-код», «Божественный объект» и другие антипаттерны.
        Если работа с «коротышкой» усложняется — изменить имя не сложно. Главное этот момент определить, вот только в состоянии «потока» это сделать сложно. Как-раз для этого и надо периодически выделять время на рефакторинг.


      1. Bonart
        15.05.2017 00:16

        Это проблема того кто дополняет.
        Пока область видимости переменной — одна строка, ей ни к чему быть длиннее одного символа.
        Если программист расширил область видимости переменной, то подбор более подходящего имени — его и только его ответственность.


        1. Oxoron
          15.05.2017 10:43

          Это вы знаете. Это я знаю. Но не факт, что это знает программист расширяющий область видимости. Не факт, что у него над душой не стоит менеджер и не твердит: «дедлайн, премия, дедлайн, премия». Не факт, что этот расширяющий программист не подумает «сохраню исходный стиль». Не факт, что он вообще использует имена длиннее одной буквы в LINQ\SQL. Не факт…

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

          В комментариях уже указали ситуации, когда хватит «коротышек». Но если противопоказаний нет — лучше использовать нормальные имена.


          1. Bonart
            15.05.2017 11:46

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

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


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

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


            Но если противопоказаний нет — лучше использовать нормальные имена.

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


    1. EndUser
      10.05.2017 11:00

      Осмысленное — исторически из математики, как и программирование из математики.
      И всегда означало integer значение и/или index.
      image


      1. aquamakc
        10.05.2017 11:05

        Сдаётся мне, что и в математике это не более, чем соглашение. Как, кстати, и фигурирующая тут-же N.


      1. Anger22
        10.05.2017 11:06
        +1

        А также i-тератор, хотя с прогрессом текущих ЯП итераторы переросли в нечто большее.


      1. Oxoron
        10.05.2017 11:08

        Программисты далеко не всегда используют i для суммирования. На матане мы иногда интегралы через I обозначали. Так скорее i-index просто традиция с корнями из математики.

        Я как-то пробовал код

        for(int index = 0; index < 10; index++){}
        

        довольно непривычно было первое время.


  1. Houston
    10.05.2017 10:44
    +6

    Всё зависит от области видимости переменной. Если это однострочник из 10 символов, то почему бы и нет? И это вполне читаемо:


    IEnumerable<int> squares = Enumerable.Range(1, 10).Select(x => x * x);


    1. Oxoron
      10.05.2017 10:50
      -2

      Однострочники иногда разрастаются. См. выше.


      1. flancer
        10.05.2017 11:07
        +9

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


        1. Oxoron
          10.05.2017 11:14
          -3

          Довольно спорно.
          Зачем оставлять потенциальную проблему? Фикс занимает секунды.
          Честно говоря, я не понимаю почему локальные переменные нужно именовать нормально, а параметры в запросах-однострочниках — необязательно.


          1. aquamakc
            10.05.2017 11:26
            +5

            почему локальные переменные нужно именовать нормально, а параметры в запросах-однострочниках — необязательно

            ))) как известно в программировании есть 3 основных проблемы — наименование переменных и ошибка на единицу.

            Иногда проще написать условную x, d или i, которая используется в 1-2 строчках, чем тратить время на придумывание и набор осмысленного имени.


          1. poxvuibr
            10.05.2017 11:29
            +6

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

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


            1. Oxoron
              10.05.2017 16:24

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


              1. Bonart
                15.05.2017 00:18

                чем больше переменных задействовано в скоупе
                У однострочника (и его локальных переменных) скоуп — одна строка.
                Чем больше переменных в скоупе — тем больше резона разбить его на несколько.


          1. Deosis
            10.05.2017 11:33

            .


          1. Eltaron
            10.05.2017 20:24
            +4

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

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


  1. fogone
    10.05.2017 10:44

    А мне короткое имя в лямбдах в одно выражение вполне ок. В котлине вон есть it и тоже неплохо для простых выражений.


  1. poxvuibr
    10.05.2017 11:24
    +5

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


    P. S. Поля у запросов поименованы потому, что они попадут в названия колонок результирующей таблицы. Псевдонимы таблиц туда не попадают.


    1. Eldhenn
      10.05.2017 11:38
      +8

      Потому что это удобно. Потому что в среднем запросе каждую таблицу надо упомянуть десяток-другой раз, и если каждый раз писать BusinessItemsArtifact — запрос превратится в нечитаемую кашу. Обычно в пределах запроса таблиц не очень много, и контекст User u, Person p или BusinessItemsArtifact bi1 не вызывает сложностей.


      1. Evergray
        11.05.2017 10:13
        +1

        Добавлю к каше масла :-). Достаточно попробовать написать schema bound view или функцию в MSSQL, где обязательно указывать имя схемы. И будет не User.Name, а MySchema.User.Name для каждого поля. А ещё табличка с пробелом в названии. Вроде dbo.[Order Details].ProductID. Короткие алиасы весь этот визуальный шум убирают.

        И при изменении структуры БД удобнее рефакторить — меньше изменений делать нужно.


  1. KitScribe
    10.05.2017 11:44

    There are only two hard things in Computer Science: cache invalidation and naming things.

    Phil Karlton

    Ну, в приницпе, всё зависит и от типа переменной и от длины кода.


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


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


  1. terrier
    10.05.2017 12:26
    +4

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


    1. martin_wanderer
      10.05.2017 15:50

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


    1. Tishka17
      10.05.2017 18:42
      +1

      дело в том, что например в Oracle есть жесткие ограничения на длину идентификатора. Если использовать нормальные имена — на раз вылетаешь за ограничения.


  1. michael_vostrikov
    10.05.2017 13:26
    +7

    Где-то читал (может у Макконнелла), что короткие имена дают техническим переменным, которые нужны для организации работы программы, а не для моделирования предметной области. И на мой взгляд это правильно. Чем меньше у них семантики, тем меньше они обращают на себя внимание. Алиасы таблиц в SQL относятся сюда же, они используются для указания движку, какое поле имеется в виду.


    Сравните:


    for (int i = 0; i < users.Count; i++)
    {
        var user = users[i];
        ...
    }
    
    foreach (var user in users)
    {
        ...
    }

    Поменяли тип цикла, техническая переменная ушла в движок языка.


    1. martin_wanderer
      10.05.2017 15:46

      Поддерживаю. Зашел сказать, что алиасы-коротышки в SQL — это хорошо и правильно: объявлены рядом, область действия — только сам запрос. Иначе они вообще не нужны — кроме случая нескольких джойнов к одной таблице можно просто использовать само имя таблицы.


  1. SbWereWolf
    10.05.2017 14:41
    +1

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

    Если не сокращать, то будет у меня имя альяса 20 символов и имя поля ещё 20 символов, итого 40 символов на ровно одно поле, это пол строки, для экрана широкоформатника — треть, на мой вкус жирно, для одного поля столько от строки отъедать.
    Запросы не всегда в две строки пишутся, для меня это как правило джоины от двух до пяти таблиц, иногда с формулами во фразе SELECT, и подзапросом или двумя во фразе WHERE, раздуть всё это полными именами таблиц? ещё и так что бы альяс был говорящим в рамках запроса?
    Нет я конечно очень не доволен ORACLE SQL где имя объекта ограничено в 30 символов и очень рад PostgreSQL где можно использовать аж 64 символа, но не настолько что бы в запросе повторять все 64 символа для каждого поля таблицы.

    Другое дело в коде программы, там другое дело, там счётчик это counter / index / element и другие более осмысленные именования, потому что тоже вложенность бывает на пару уровней и если использовать «i», «j», «k» очень легко сбиться.


  1. Sirikid
    10.05.2017 14:45
    +1

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


    -- var posNums = nums.Where(n => n > 0).Select(r => r);
    posNums = filter (>0) nums
    
    -- IEnumerable<int> squares = Enumerable.Range(1, 10).Select(x => x * x);
    squares = fmap (^2) [1..10]
    
    -- List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);
    evenNumbers = filter even list
    
    -- team.Select( p => p.Age > 18);
    _ = filter ((>18) . age) team


    1. sshikov
      10.05.2017 20:16

      Это вас в общем случае не спасет. Да и в частном — не сильно лучше ваши варианты. Вы думаете, назначение even всегда будет таким уж очевидным? Ну т.е. идея-то правильная, а вот примеры не очень удачные.


  1. ElectroGuard
    10.05.2017 15:56

    Пишу на Delphi. Придерживаюсь простого правила. Все значимые переменные обязательно именую. Незначимые — временные, циклические и т.п. пишу короткими (как правило — одно-буквенными). Мне кажется оптимальный вариант.


  1. KVL01
    10.05.2017 16:22

    Если у точки координаты X, Y, Z, то никто в здравом уме не будет их называть как координатаПоОси<имя оси>. В этом плане мне мешают плохо именованные объекты – много писанины, за которой смысла не видно.

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


  1. piranuy
    10.05.2017 20:30

    Какие то некорректные примеры «вредных» книжных примеров приведены. Если в лямбдах переменные называть длинно, то их еще и на несколько строк придется разбивать, а ведь переменная даже за их пределы не выйдет. Другое дело — какие-нибудь большие вложенные циклы, сравнимые с вашими 15ти строчными sql запросыми, где привычные i и y тоже могут боком выйти. Это тоже самое, что и с паттернами и уметь определять где с таким именованием будет лучше, а где вредно.


  1. kxl
    10.05.2017 22:11
    +1

    На C# привык в простых лямбдах ставить знак _ вместо буквы (особенно, когда без разницы — какую букву использовать). Потому, что так лучше видно, какие методы/свойства задействованы в лямбде. Из Лиспа что-ли это тянется…


  1. Lerg
    11.05.2017 01:11

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


    1. aquamakc
      11.05.2017 09:16

      зачем? это была бы лишняя работа. все эти имена нужны только человеку. Для машины — это адреса памяти. Тратить ресурсы на преобразование текста кода туда-обратно бессмысленно.


      1. Eldhenn
        11.05.2017 16:50

        Скоро мощность среднего десктопа приведёт к тому, что IDE перестанут тормозить. Это недопустимо.


      1. YemSalat
        12.05.2017 05:24

        зачем?

        Ответ и так дан выше:
        … чтобы он занимал меньше места на экране и лучшим образом показывался алгоритм/структура метода…


        Тратить ресурсы на преобразование текста кода туда-обратно бессмысленно

        Тратить ресурсы на раскрашивание текста кода бессмысленно — из той же оперы?


        1. aquamakc
          12.05.2017 08:42
          +1

          … чтобы он занимал меньше места на экране и лучшим образом показывался алгоритм/структура метода…

          И каким же образом автоматическая замена осмысленных имён на всякие x, y, z улучшит читаемость кода и понимание алгоритма?


          1. Deosis
            12.05.2017 09:17

            И каким же образом автоматическая замена осмысленных имён на всякие x, y, z улучшит читаемость кода и понимание алгоритма?

            Просите у авторов языка APL: P<{0~??a?????0,??a?!?a


            1. aquamakc
              12.05.2017 09:18
              +1

              давайте ещё к авторам Brainfuck`а за простотой и наглядностью синтаксиса сходим


          1. YemSalat
            16.05.2017 14:03
            -1

            И каким же образом автоматическая замена осмысленных имён на всякие x, y, z улучшит читаемость кода и понимание алгоритма?

            По аналогии с тем как работает «мини-карта» кода в современных текстовых редакторах:


            Она дает вам возможность взглянуть на свой код «с высоты птичьего» полета и помогает быстрее понимать структуру текущего файла.

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


  1. Shablonarium
    11.05.2017 02:15

    Когда в выражении более одного сокращения — это уже плохо.