Справа з фігурним брекет-супом


11

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

Одна з проблем, які у мене є, - це кучерявий суп з брекетів. У VB кожне ключове слово структури має відповідне ключове слово, наприклад:

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 для поліпшення читабельності та забезпечення того, щоб ваш код опинився у правильному "блоці". Наведений вище приклад порівняно легко читати, але іноді в кінці фрагмента коду у мене буде 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
Я бачив, як люди роблять це, і коли вони поміняють / змінюють початок блоку (змінюють а 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

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


Дякую, може виникнути блок чи два, які я міг би рефакторити. Це допоможе, але важко перефактурувати кілька вкладених usingблоків.
JDB досі пам’ятає Моніку

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

Так, я знаю про вкладку за допомогою блоків, але це працює лише в тому випадку, якщо під вами є одна лінія. У більшості мого коду це не так. І все-таки дуже корисна публікація загалом ... дізналася кілька речей (+1)
JDB все ще пам’ятає Моніку

@ Cyborgx37 так, я розумію, що сфера гніздування працює лише у вас, якщо у вас немає зайвих шматочків, що сказало, чи є модель у вашому способі використання? Чи можливо, можливо, перенести частину додаткової частини в конструктор, якщо вона знаходиться вгорі або утилізація, якщо вона знаходиться внизу? Тобто, якщо це з малюнком; здогадуючись, це може бути з моменту, коли ви поставили це як проблему, тож ви, ймовірно, натрапляєте на них, використовуючи гнізда часто у своєму коді.
Джиммі Хоффа

Я фактично розпочав роботу над реалізацією Factory-pattern, яка обгортає об'єкти COM у класі "AutoCleanup". Потім я використовую одне usingтвердження про заводський клас і, коли воно розміщене, воно автоматично розпоряджається усіма завершеними класами. Наразі він працює добре і значно скоротив кількість usingвисловлювань у моєму коді.
JDB досі пам’ятає Моніку

1

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

Однак будьте попереджені, що якщо ви працюєте в складі команди, від вас очікується відповідати умовам, які використовує ця команда, тож варто платити за знайомство з обома стилями та утримуватися від релігійності над стилями брекетів.

Тож, коли ви навчаєтесь, у будь-якому випадку зосередьтеся на стилі, який полегшує вам навчання, але при цьому тримайте половину уваги за іншим, поки ви на це навчаєтесь, і ви будете робити добре.


1
Я не впевнений, чи це формат за замовчуванням або щось у ReSharper, але коли я використовував C #, у нас був набір параметрів, який переформатував код як частину реєстрації. Таким чином ви можете відформатувати код, який хочете, під час роботи з ним, але він буде переформатований на "стандарт проекту" при реєстрації. Я думаю, що єдиним реальним стандартом форматування було використання пробілів замість вкладок.
TMN

1

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


1

Є редактор, який може допомогти вам за адресою: C # Контур .

Додаток розширює редактор VS20xx для C #, додаючи функції для згортання, розширення та виділення вкладених блоків коду. Ці функції дозволяють легше редагувати та читати вкладені вмісти блоків коду, наприклад, якщо, поки тощо.


0

Якщо ви пишете свій код у Visual Studio, також є плагін, який показує вам вертикальні точки між початком і кінцем кожної структури, яку ви створюєте.

Але в цілому я думаю, що це просто пройде деякий час, поки ти не звикнеш до "Кучерявих брекетів-супів". (Btw, мені дуже подобається цей вираз. Звучить трохи як назва епізоду для теорії великого вибуху)


0

Відступ показує, де ви знаходитесь, в обох стилях синтаксису. Якщо ви пишете або програму VB, або програму C # в одному рядку, незабаром ви не зможете сказати, де ви вкладений синтаксис. Машина розбирає блок, що закінчується фразами або фігурними дужками, але людині потрібні відступи.

Фрази, що закінчуються блоком, походять з епохи перфокарт та паперової стрічки, коли програмування було набагато менш інтерактивним та наочним. Або, справді, зовсім не інтерактивним. Вводити програми було важко, тому програмістам потрібні компілятори, щоб вони були дуже розумні щодо аналізу синтаксису та відновлення помилок.

У ту епоху, що минула, цикл редагування-збирання міг включати підготовку перфокарт із картографічним перфоратором, а потім вишикуватися до вікна подання на роботу, де діловод взяв пробиті картки та подав їх до машини. Пізніше програміст збирає вихід (надрукований на папері) з іншого вікна. Якщо в програмі були помилки, вихід складається з просто діагностики компілятора. Коли час повороту тривалий, додаткова вартість набору тексту end ifзамість просто )виправдана, якщо це сприяє поліпшенню якості діагностики, оскільки програмісту потрібно виправити якомога більше помилок за одну ітерацію, щоб зменшити кількість витрат часу ітерації через вікно подання завдання.

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

Коли ви працюєте в текстовому редакторі, який знає код, який автоматично відступає та розфарбовує ваш код, на екрані з високою роздільною здатністю, де ви можете бачити шістдесят і більше рядків, аргументи для таких видів незграбних мов більше не застосовуються. Ви можете поступово редагувати та відновлювати програми настільки швидко, що ви можете просто впоратися з однією помилкою. Більше того, переглядаючи великі розділи програми одночасно на екрані та підтримуючи належний відступ, ви можете в першу чергу зменшити кількість таких помилок введення. І хороший редактор тексту програмування навіть позначатиме деякі типи синтаксичних помилок під час введення. Більше того, є складні редактори, які згортають блоки програми на основі її синтаксису, надаючи "структурну форму" уявлення про її структуру.

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

Насправді, символи закінчення вам зовсім не потрібні, як це демонструє мова Python. Ідентифікація може бути просто структурою. Люди вже використовують відступи, щоб упорядкувати структуру коду навіть у мовах, де машина покладається на кінцеві символи чи фрази.


-1

Якщо ви використовуєте IDE, просто натисніть Crtl+ k+, Dі IDE виконає решту робіт.


який IDE eclipse використовує ctrl-shift-i для відступу та ctrl-shift-f для форматування
храповик-фрік

заїзд у візуальну студію
Jagz W
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.