Работа с фигурным супом


11

Я программировал на C # и VB.NET в течение многих лет, но в основном на VB. Я делаю карьеру в сторону C # и, в целом, мне больше нравится C #.

Одна проблема, которую я имею, это кудрявый суп. В VB каждое ключевое слово структуры имеет соответствующее ключевое слово close, например:

Namespace ...
    Class ...
        Function ...
            For ...
                Using ...
                    If ...
                        ...
                    End If
                    If ...
                        ...
                    End If
                End Using
            Next
        End Function
    End Class
End Namespace

Тот же код, написанный на C #, очень трудно читать:

namespace ... {
    class ... {
        function ... {
            for ... {
                using ... {
                    if ... {
                        ...
                    }
                    if ... {
                        ...
                    }
                }
            }
            // wait... what level is this?
        }
    }
}

Будучи настолько привыкшим к VB, мне интересно, есть ли методика, используемая программистами c-style для улучшения читабельности и обеспечения того, чтобы ваш код попал в правильный «блок». Вышеприведенный пример относительно легко читается, но иногда в конце фрагмента кода у меня будет 8 или более уровней фигурных скобок, что потребует от меня прокрутить несколько страниц вверх, чтобы выяснить, какая фигурная скобка заканчивает интересующий меня блок в.


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

7
Одна вещь, которую я видел, сделал, и я взял на себя, это в конце фигурной скобки, я добавлю комментарий об этом. Нечто подобное // End's using X statement.
PiousVenom

14
@FrustratedWithFormsDesigner говорит о том, что ваш поток управления беспорядочный и его необходимо переделать. Тем не менее, я думаю, что вы жалуетесь больше на фигурные скобки, чем обзор, и я бы сказал, что вам просто нужно привыкнуть к этому. Изучение языка со значительно отличающимся синтаксисом, чем вы привыкли, определенно выглядит как суп на некоторое время, но с практикой это уходит. Вам просто нужно пристегнуться и действовать, пока ваш мозг не начнет обрабатывать синтаксис более естественным образом, вы получите это.
Джимми Хоффа

2
@FrustratedWithFormsDesigner - мне нужно очистить много COM-объектов в ситуации взаимодействия COM. Я использую технику, предложенную в этой статье: jake.ginnivan.net/vsto-com-interop . Это легко создает два или три слоя. Когда вы кладете цикл for, функцию, класс и пространство имен поверх этого (вместе с оператором if), вы легко получаете несколько слоев фигурных скобок.
JDB до сих пор помнит Монику

5
@TyrionLannister - И это могут быть одни из самых быстрых комментариев, которые не синхронизируются с тем, к чему они принадлежат ... Я думаю, что если бы у меня было что-то подобное, я бы предпочел, чтобы оно генерировалось автоматически (при отображении только время, не сохраняется) в IDE.
Заводная муза

Ответы:


39

Поместите начальную фигурную скобку в тот же «ранг», что и конечная, например:

namespace ... 
{
    class ... 
    {
        function ... 
        {
            for ... 
            {
                using ... 
                {
                    if ... 
                    {
                        ...
                    }
                    if ... 
                    {
                        ...
                    }
                }
            }
            // It's the `function` level!
        }
    }
}

15
Согласен. Египетские скобки вызывают у меня головную боль.
PiousVenom

8
Кроме того, большинство IDE (вероятно) выделяют партнера скобки при нажатии на нее.
StuperUser

3
@TyrionLannister: Спасибо, что наконец дали мне термин для этого стиля! У меня никогда не было хорошего имени для них, кроме "неправильных скобок".
FrustratedWithFormsDesigner

3
@ Cyborgx37: есть ли в вашей IDE функция «Перейти к соответствующей скобке»? Обычно привязывается к сочетанию клавиш, которое автоматически перемещает курсор на фигурную скобку, которая соответствует выделенной в данный момент.
FrustratedWithFormsDesigner

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

14
  • В зависимости от вашей IDE: наведите курсор на скобку открытия / закрытия, и она выделит как эту, так и соответствующую скобку.
  • Сверните блок, и он покажет вам, где он открывается / закрывается.
  • Напишите меньшие блоки кода. Шутки в сторону. Проверьте Clean Code, и никогда не сталкивайтесь с этой проблемой снова (и иметь более читаемый / поддерживаемый код).

Одно замечание, следующий допустимый синтаксис c #, который может помочь вашей конкретной ситуации:

using (var type = new MyDisposable1())
using (var type2 = new MyDisposable2())
{
    /* do what you will with type2 and type2 */
}

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

2
@ Cyborgx37: Отсюда пункт 3. Если весь ваш кодовый блок помещается на экране, вам никогда не придется охотиться. В большинстве / всех написанных мною классов единственными парами фигурных скобок, которые не помещаются на экране, являются пространство имен / класс.
Стивен Эверс

То, что вы предлагаете в пунктах 1 и 2, - это то, что я делаю сейчас ... но это требует, чтобы я покинул то место, где я кодирую, и начал манипулировать своим представлением о коде, чтобы выяснить, куда поместить следующую строку. Точка 3 хорошо принята, но не всегда возможна, особенно если ваш код требует нескольких слоев usingблоков (см. Jake.ginnivan.net/vsto-com-interop )
JDB все еще помнит Монику

@ Cyborgx37: см. Мое редактирование.
Стивен Эверс

1
@ Cyborgx37 Если вы выберете цвет, который будет отличаться от всего остального (я некоторое время использовал фиолетовый фон и белый текст, IIRC), то вам не нужно охотиться за соответствующей фигурной скобкой - она ​​практически кричит на вас "Я ЗДЕСЬ ! ».
CVN

5

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

if {
   ...
} // end if

while (condition) {
   ...
} // end while

и т. д. Я сам никогда не подходил к этой конвенции, но некоторые люди находят ее полезной.


16
Я видел, как люди делают это, и когда они меняют / меняют начало блока (меняют a whileна a for, меняют ifоператоры), они почти НИКОГДА не забывают обновить закрывающие комментарии, делая их хуже, чем бесполезными. Это соглашение, вероятно, будет полезно только в том случае, если вы сможете заставить себя поддерживать комментарии каждый раз, когда {меняется характер соответствия .
FrustratedWithFormsDesigner

Да, я сделал кое-что из этого, но это много дополнительной работы (и шума). Я надеялся, что будет что-то более простое.
JDB до сих пор помнит Монику

5
Комментарии должны только объяснять, почему никогда что или как, поскольку код выполняет оба из них и полагается на комментарии для объяснения любого из них, означает, что код трудно читать, что является признаком того, что код должен быть исправлен, а не прокомментирован.
Джимми Хоффа

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

2
@JimmyHoffa: я думаю, что лучшим правилом для комментариев является то, что они должны обеспечивать ясность . Обычно это означает ответ «почему», но это может означать и другие вещи. Не зацикливайтесь на догмах, так как это мешает вам делать то, что действительно помогает, например, иногда добавлять комментарий к закрывающей скобке, которая находится далеко от ее открывающей скобки.
Брайан Оукли

5

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


5

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

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


Год спустя, и этот совет звучит правдоподобно. :)
JDB до сих пор помнит Монику

4

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

После этого вы редко будете иметь вложение более 4-х уровней.

namespace FooNameSpace {
class Foo {

public void bar()
{
    while(true)
    {
        while(true)
        {
            break;
        }
    }
}

public void fooBar()
{
    foreach(var item in FooList)
    {
        foreach(var b in item.Bars)
        {
            if(b.IsReady)
            {
                bar();
            }
            bar();
        }
        bar();
    }
}

}}//end class, namespace

Мне нравится эта идея, но Visual Studio, похоже, не поддерживает ее (по крайней мере, 2008 год. Мы обновляемся до 2012 года к концу года, так что надеемся)
JDB все еще помнит Монику

@ Cyborgx37. Я редактирую текст извне в VIM, так что это не проблема. Но в Visual Studio выполните: Control + A, затем нажмите кнопку «Отступ меньше». Делайте это только для новых файлов. Не беспокойтесь о существующих файлах, так как это испортит сравнения сравнения в управлении исходным кодом.
mike30

Ввод закрывающих скобок / скобок запускает автоматическое форматирование VS, но вы всегда можете нажать CTRL + z, чтобы отказаться от его предложения.
Алекс В Париже

1

Недавно я решил попытаться формализовать два правила для конструкций управления потоком, которые в основном идут следующим образом:

  • У вас не должно быть ничего, кроме необходимых конструкций потока кода
  • Вы должны сделать конструкции потока кода как можно меньше

Именно по тем причинам, которые вы упомянули и четко знаете, я думаю, что это отличные правила для подражания. Есть несколько простых методов, которые вы можете использовать для их выполнения:

  • Выйдите из области видимости, как только сможете (это включает область видимости циклов и функций)
  • Следите за остальными, которые можно смягчить, выйдя из функции из предыдущего if и примените технику выхода из области действия, как я уже упоминал
  • Отмените условные проверки, когда код внутри if больше, чем снаружи
  • Код фактора внутри цикла выходит в другой метод, когда размер цикла увеличивается, чтобы скрыть остальную часть метода
  • Следите за любыми областями, которые содержат только другую область видимости, например, функцию, вся область которой заполняется оператором if, не имеющим ничего, кроме if

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


Спасибо, возможно, есть блок или два, которые я мог бы переработать. Это поможет, но трудно реорганизовать несколько вложенных usingблоков.
JDB до сих пор помнит Монику

@ Cyborgx37, фактически использующие блоки, могут быть встроены, если они вложенные, выполняя области, смотрите здесь stackoverflow.com/questions/1329739/… он в основном работает как однострочные конструкции управления потоком, как вы можете if (true) doSomething (); Вы также можете if (true) if (somethingElse) if (otherThings) {doThis (); сделай это(); делай что угодно(); } и ifs гнездятся так, как вы ожидаете (НЕ ПИШИТЕ КОД, КАК ТОЛЬКО ДЛЯ ЛЮБВИ БОГА, ПРОСТО ДЕЛАЙТЕ ЭТО С ИСПОЛЬЗОВАНИЕМ И НИЧЕГО, ХЕ ХЕ)
Джимми Хоффа

Да, я знаю о вложенности с использованием блоков, но это работает, только если у вас есть одна строка внизу. В большинстве моего кода это не так. Все еще очень полезный пост в целом ... узнал несколько вещей (+1)
JDB все еще помнит Монику

@ Cyborgx37 да, я понимаю, что вложение области действия работает только если у вас нет лишних битов, что говорит о том, есть ли образец в вашем поведении? Возможно, было бы целесообразно перенести часть этого дополнительного в конструктор, если он вверху или в распоряжение, если он внизу? Это если это по шаблону; предположить, что это может быть, так как вы подняли это как проблему, так что вы, вероятно, столкнетесь с этим, используя гнезда в своем коде
Джимми Хоффа

Я фактически начал работу над реализацией шаблона фабрики, которая оборачивает COM-объекты в класс AutoCleanup. Затем я использую один usingоператор для класса фабрики и, когда он удаляется, он автоматически удаляет все упакованные классы. Пока это работает хорошо и значительно сократило количество usingоператоров в моем коде.
JDB все еще помнит Монику

1

К сожалению, это одна из старейших причин компьютерных войн. Обоснованные аргументы могут быть выдвинуты с обеих сторон (лучшая вертикальная экономика недвижимости по сравнению с более простой способностью визуально сопоставлять открывающую скобку с закрывающей скобкой), но на самом деле простой форматировщик исходного кода решит все за вас. MS Visual C # имеет один встроенный, который работает хорошо.

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

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


1
Я не уверен, что это средство форматирования по умолчанию или что-то в ReSharper, но когда я использовал C #, у нас был набор опций, который переформатировал код как часть регистрации. Таким образом, вы можете отформатировать код так, как вам хочется, пока вы работаете с ним, но при регистрации он будет переформатирован в «стандарт проекта». Я думаю, что единственным реальным стандартом форматирования, который у нас был, было использование пробелов вместо табуляции.
TMN

1

Используйте Resharper, который поможет порекомендовать способы уменьшения вложенности. Кроме того, прочитайте книгу Боба Мартина « Чистый код» , в которой подчеркивается, что функция должна выполнять только одну вещь, и поэтому каждая функция должна быть длиной всего в полдюжины, так что вам не придется беспокоиться о таком количестве уровней вложенности.


1

Существует редактор для редактора, который может помочь вам по адресу: C # Outline .

Дополнение расширяет редактор VS20xx для C #, добавляя функции для свертывания, расширения и выделения вложенных блоков кода. Эти функции упрощают редактирование и чтение вложенного содержимого блоков кода, таких как if, while и т. Д.


0

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

Но в целом, я думаю, что потребуется некоторое время, пока вы не привыкнете к "Curly-Braces-Soup". (Кстати, мне действительно нравится это выражение. Звучит как Эпизод для Теории Большого Взрыва)


0

Отступы говорят вам, где вы находитесь, в обоих стилях синтаксиса. Если вы напишите в одной строке VB-программу или C # -программу, вы вскоре не сможете определить, где находится вложенный синтаксис. Машина анализирует конечные фразы блока или фигурные скобки, но людям нужен отступ.

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

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

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

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

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

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


-1

Если вы используете IDE, просто нажмите Crtl+ k+, Dи IDE сделает всю остальную работу.


какое затмение IDE использует ctrl-shift-i для отступа и ctrl-shift-f для форматирования
трещотка урод

проверить в визуальной студии
Jagz W
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.