Маленькое удобство, способное прекратить вселенские споры

    Все те, кто пишет на Си-подобных языках, знакомы с двумя немного отличающимися стилями кода. Выглядят они вот так:

    for (int i=0;i<10;i++) {
        printf("Hello world!");
        printf("Hello world again!");
    }

    for (int i=0;i<10;i++)
    {
        printf("Hello world!");
        printf("Hello world again!");
    }

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

    Компромиссное решение могло бы выглядеть вот так:

    image

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

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

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

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

    И с другой стороны — красота остаётся нетронутой! Визуально блок кода выделяется самой симметричной из всех симметричных конструкцией. Глаза всё так же легко найдут начало и конец. Ну и возражать против такого стиля будет просто некому, ведь оппоненты наверняка все перейдут в лагерь сторонников подхода.

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

    Алгоритм замены скобок


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

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

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

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

    Но остаётся небольшая сложность в виде бесшовного совмещения процесса редактирования с отображением замен в виде подчёркиваний.

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

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

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

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

    Пока мы в блоке текста, включая крайние строки, делать ничего не нужно. Когда мы нажимаем enter в любом месте последней строки кроме конца — нужно перенести подчёркивание. Если enter нажимается в конце строки — ждём ввода символа. Когда мы нажимаем backspace в последней строке в позиции подчёркивания — нужно переместить текущее подчёркивание на одну линию выше. И разумеется, при всех операциях нужно не забывать вставлять и удалять скобки в тот текст, который будет сохраняться на диск.

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

    И напоследок о символе overscore, который я здесь условно назвал «верхним подчёркиванием». Его, к сожалению, нет на стандартной клавиатуре, а потому нет возможности вводить его напрямую без помощи редактора. Именно поэтому важна помощь IDE. Хотя теоретически можно вводить последовательность юникода (\u00af = ¯), которую некоторые редакторы автоматически преобразуют в символ overscore, но всё же делать так каждый раз, когда нам нужна скобка, было бы просто издевательством над разработчиками. Поэтому и нужны плагины, ну и изменения в спецификациях языков.

    Всё, ждём срочных обновлений спецификаций языков и массу удобных плагинов для всех возможных IDE.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 70

      +31

      "Теперь у нас три немного отличающихся стиля кода"

        +4
        Mandatory xkcd

        image

          +3
          Стилей по прежнему два, ведь не предлагается обязательно сохранять текст именно в таком виде. А если никто кроме конкретного разработчика не видит альтернативный стиль, значит для других его нет. Логично?

          Смысл в удовлетворении разных желаний. Кто не хочет, тот не будет включать плагин, а кто хочет — сможет экономить много строк и не отказаться от привычного стиля в текстах, которые сохраняются на диск. Прозрачно, бесшовно, легко и непринуждённо. Как-то так.
            +3

            Предлагаю 4ый вариант. Сделать плагин который при открытии файла будет форматировать код под индивидуальные хотелки. А сохранять файл с общепринятыми в команде формате.

            +1
            Четыре… И одна змея.
            –27
            Первый стиль, где фигурная скобка после ) пришел скорее из JavaScript.
              +41
              K&R известные джаваскриписты.
                +7
                Этот стиль появился когда JavaScript ещё даже в проектах не было.
                  +26
                  Более того, Java получили из JavaScript отбросив «Script».
                    –3
                    Скорее наоборот, когда Java хайпанула, livescript смотрелся как-то не очень:)
                    +3

                    Были найдены на острове Java в санScriptских рунах

                    +2

                    Мне чет не нравится как это выглядит (я сторонник "лишних" строк).

                      –14
                      Мне нравится так:
                      for (int i=0;i<10;i++) {   
                          printf("Hello world!");
                          printf("Hello world again!");
                          }  
                      И где голосовалка?
                        +6

                        В go, кстати, второй вариант невозможен, только:


                        for i := 0; i < 10; i++ {
                            fmt.Print("Hello world!")
                            fmt.Print("Hello world again!")
                        }
                          +31
                          Это. Паааадаждите. До скобок ещё надо решить — почему кто-то использует табы вместо пробелов. И только псоле этого можно притрагиваться к положению скобок.
                            0
                            Так принцип тот же — IDE на лету конвертирует в то, что вы хотите. Так что этот вопрос тоже решён.
                              0
                              Ага, а при коммите в git что будет?
                                +2

                                Pre-commit hook, который будет проверять исходники на соответствие выбранному в проекте стилю оформления кода и бить по рукам.

                                  +4
                                  Может тогда сразу IDE настроить на форматирование кода в стиле, который принят в этом проекте? А кому нравится по другому — пусть в pet-проектах занимается извращениями.
                                  +1
                                  Это. Паааадаждите. Ещё надо решить — почему кто-то использует Mercurial вместо Git
                                0
                                Вспомнил сериал Кремниевая долина, где один из гг бросил девушку, потому что он использовал пробелы (или табы, уже не помню точно), а она наоборот.
                                  0
                                  Это. Паааадаждите. До скобок ещё надо решить — почему кто-то использует табы вместо пробелов. И только псоле этого можно притрагиваться к положению скобок.

                                  Правильный стиль — tab indent space alignment (статьи есть в Инете и на Хабре). Т. е. писать только табами, только пробелами или их рандомной смесью — всё неверно, и лично для меня это лютый быдлокод. Правильно именно tab indent space alignment.

                                    –1

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

                                      +1

                                      Вы прочитали что такое tab indent space alignment? Данный стиль не имеет ни одной проблемы. В том числе в приведённом Вами случае только этот стиль сможет отработать нормально, т. к.:


                                      • Если всё написать пробелами, юзер не сможет настроить величину отступов в браузере.
                                      • Если всё написать табами, поедет выравнивание.
                                      • А tab indent space alignment единственный стиль, который отработает корректно в приведённых Вами примерах.
                                        0

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

                                          0

                                          Проблем из-за правильных табов (в tab indent space alignment) ровно ноль. Зато проблем от пробелов 100500.


                                          Если кто-то использовал табы неверно — это не вина этого стиля. Ненавидьте всех, кто использует только табы или только пробелы, т. к. они все быдлокодеры (по моему мнению). Стиль не имеет отношения к этим людям.

                                  +28

                                  А я ничего не буду говорить, просто сяду с попкорном и буду ждать когда кто-нибудь скажет слово "Python" и холивар разожжется еще сильнее.

                                    +2
                                    Блин, а я терпел и молчал
                                      0

                                      Будет скучно — докиньте дровишек людям насчет отступов (TAB vs 4xSpace vs 2xSpace).
                                      PEPов-то в С[++] нет.
                                      PS. хотя есть рекомендации и прочие RFC, но кто ж их читает (судя по статье)?

                                      +1
                                      А без скобок прикинуться питоном не получится?
                                        +1
                                        Всё, ждём срочных обновлений спецификаций языков

                                        Так вы сами языки меняете или только отображение скобочек в IDE?
                                          –1
                                          Стандарт стоит поменять для того, что бы в нём было упоминание об альтернативном отображении текста. Не обязательно текст в таком виде сохранять, ведь IDE снова всё исправит при следующей загрузке. Но вот показать в стандарте удобный вариант отображения — это важно. Без стандартизации будет ситуация «кто в лес, кто по дрова».
                                            +3
                                            Стандарт стоит поменять для того, что бы в нём было упоминание об альтернативном отображении текста.

                                            Зачем?


                                            Без стандартизации будет ситуация «кто в лес, кто по дрова».

                                            Так и будет. Было два варианта, станет, с вашей помощью, три.

                                          +1

                                          Хорошая идея. Остается убедить остальных членов команды )

                                            0

                                            Ожила увидеть что-то типа:


                                            for int i = 0 ; i < 10 ; i++
                                                printf "Hello world!"
                                                printf "Hello world again!"

                                            Нет скобок — нет проблемы с их расположением.

                                              +1
                                              В обоих вариантах, вторая скобка дает дополнительный отступ, чтобы избежать каши на следующей строке
                                              +7

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


                                              Поэтому нам нужен компромисс.

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


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

                                              После чего у нас сломается парсер в IDE, отлично придумано.
                                              Украшательства не должны вмешиваться в исходный код, для этого есть code folding.
                                              Вот вам живой пример: Advanced Java Folding


                                              Всё, ждём срочных обновлений спецификаций языков и массу удобных плагинов для всех возможных IDE

                                              И переезда столицы в Нью-Васюки!

                                                +2
                                                Да хоть смайлики используй если с ними ты эффективней, но при слиянии используйте оговоренный code cleanup
                                                  +1
                                                  с двумя

                                                  Всего с двумя? Точно-точно?

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

                                                  Какой ужас.

                                                  printf("Hello world!");

                                                  Тут уж или puts(), или что-то в конце строки забыто.

                                                    0

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

                                                      +3
                                                      Не знаю о чём вы тут все спорите. У меня в Scratch-е такой фигни нет :)
                                                        +1
                                                        Для VS давно решил данную проблему: Line Press
                                                        1) Увеличиваем расстояние между строк
                                                        2) Для пустых строк и строкам содержащим одиночные символы "{","}",")}" и т.п. делаем «компрессию»
                                                        И никакие фигурные скобки не отвлекают от структуры кода.

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

                                                          for ( int i = 0; i < 10; i++ ) {
                                                              printf ( "Hello world!" );
                                                              printf ( "Hello world again!" );
                                                          }
                                                            0
                                                            После открывающей и перед закрывающей скобками пробелы не нужны по правилам любого языка.
                                                              0
                                                              Тем не менее есть такой стиль, повышающий читабельность. В простых примерах это не особенно заметно, а в большом потоке кода глазу зацепиться за аргументы. То-же относится к пробелу между именем функции и открывающей скобкой.
                                                                0
                                                                Не согласен. Иначе бы книги тоже писали так ( вот с такими пробелами внутри скобок ). Выглядит это плохо и читабельность совсем не повышает.
                                                                  +2

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


                                                                  Скажем, в английском (да и в русском) языке в большей части случаев вокруг скобок требуется пробел: Parentheses should have spaces on either side, just like words., однако запись f(x), насколько я знаю, в математике считается правильной, в отличие от f (x).

                                                            +1
                                                            Фигурные скобки надо ставить веде, иначе магии будет еще больше!
                                                              +1
                                                              Один вопрос, вы это серьёзно? Вот прям до изменения стандарта языка?
                                                                0
                                                                скорее кодстайлов с встроением в иде макросов замены черт на скобки
                                                                0
                                                                То есть не особо-то что и изменилось, теперь действительно у нас три варианта расставления скобок, Вы вместо упомянтых двух стилей предложили делать так:
                                                                for ( int i = 0; i < 10; ++i)
                                                                {    printf( "hello world" );
                                                                     printf( "hello world again" );
                                                                }
                                                                

                                                                причем еще и нижняя скобка абсолютно никак не говорит, что следующая за ней строка стоит в этом же блоке кода, отдельно интересно зачем заменять скобки на подчеркивания? читаемости это никак не добавило, ко всем сомнительным плюсам добавим, что и символ верхнего подчеривания просто так не напишешь, что было Вами и подмечено…
                                                                может просто договориться в какой стиль привести код перед коммитом, а дальше форматировать как удобно, благо функция автоформатирования под заданный стиль в IDE уже есть?
                                                                  0
                                                                  Вы вместо упомянтых двух стилей предложили делать так:

                                                                  Нет, не так. А вот так:
                                                                  for ( int i = 0; i < 10; ++i)
                                                                  {    printf( "hello world" );
                                                                  }    printf( "hello world again" );

                                                                  То есть нижняя скобка сдвигается на строчку вверх. Иначе она так и будет занимать пустую строку. Но поскольку вместо скобки используется подчёркивание, всё выглядит как будто новые «скобки» выше и ниже блока кода.
                                                                    0
                                                                    а, то есть следующий printf все таки во внешнем цикле, это же нечитаемо, изначальные стили читаемы хотя бы…
                                                                      +1
                                                                      Нет, следующий printf в том же самом цикле, что и первый.

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

                                                                      Должно быть вот так:
                                                                      for ( int i = 0; i < 10; ++i)
                                                                      ¯    printf( "hello world" );
                                                                      _    printf( "hello world again" );

                                                                      Здесь расцветка и длина верхнего символа изменены стилями страницы, но суть именно такая. Нижняя и верхняя черта визуально ограничивают всё тот же двухстрочный блок.
                                                                        0
                                                                        Так там он был во внешнем цикле, с такой постановкой скобок в моей аналогии, ну и вроде как не особо-то визуально стало легче((
                                                                      +2
                                                                      for (int i = 0; i < 10; ++i)             { 
                                                                          printf( "hello world" );
                                                                          printf( "hello world again" );       }

                                                                      Вот так ещё можно
                                                                        +2
                                                                        А еще можно
                                                                        #define begin {
                                                                        #define end   }
                                                                        И писать на си на паскале.
                                                                          +1
                                                                          Милое дело, да.
                                                                          Но там тоже свои заморочки

                                                                          for (int i = 0; i < 10; ++i)             
                                                                          begin 
                                                                              printf( "hello world" );
                                                                              printf( "hello world again" );       
                                                                          end
                                                                          
                                                                          или
                                                                          
                                                                          for (int i = 0; i < 10; ++i)             
                                                                              begin 
                                                                              printf( "hello world" );
                                                                              printf( "hello world again" );       
                                                                              end
                                                                          или
                                                                          
                                                                          for (int i = 0; i < 10; ++i) begin 
                                                                              printf( "hello world" );
                                                                              printf( "hello world again" );       
                                                                          end
                                                                          


                                                                          И тут опять, первый красивее :)
                                                                            0

                                                                            <шутка про Lisp>

                                                                              0
                                                                              Скобки должны были быть круглыми
                                                                              0
                                                                              Если честно, за свои годы я так и не понял, каким образом открывание блока с новой строки повышает читаемость. При чем, со скобками еще норм, а этот вот begin ассоциируется с какой-то отдельной конструкцией. Возможно, все из-за того, что я начинал с бэйсика.
                                                                    • UFO just landed and posted this here
                                                                        0

                                                                        Хорошему танцору программеру скобки мешают.

                                                                          +6
                                                                          Надо действовать кардинальнее — заменим скобочки на begin end.
                                                                            +1
                                                                            привет, паскаль?)
                                                                              +2
                                                                              а после end будем писать, к чему он относился!
                                                                              +1

                                                                              В языке Zimbu от создателя Vim, кстати, эта проблема решена радикально. Там нет открывающей скобки.


                                                                              FUNC Main() int
                                                                                IO.write("Hello, World!\n")
                                                                                RETURN 0
                                                                              }
                                                                                +2

                                                                                Ох, жесть какая… Надо еще убрать открывающую круглую скобку и первую кавычку.

                                                                                  +1
                                                                                  Закрывающая скобка занимает целую пустую строку. Это непорядок.

                                                                                Only users with full accounts can post comments. Log in, please.