중괄호 수프 다루기


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 interop 상황에서 많은 COM 개체를 정리해야합니다. 이 기사에서 제안한 기술을 사용하고 있습니다 : jake.ginnivan.net/vsto-com-interop . 이것은 2 ~ 3 개의 레이어를 쉽게 만듭니다. for 루프, 함수, 클래스 및 네임 스페이스를 if 문과 함께 스택하면 여러 계층의 괄호에 쉽게 도달 할 수 있습니다.
JDB는 여전히 Monica

5
@TyrionLannister-그리고 그것들은 그들이 속한 것들과 동기화되지 않는 가장 빠른 주석 일 수 있습니다 ... 내가 그런 것을 가질 것이라고 생각한다면, 자동 생성되는 것을 선호합니다 (디스플레이에서) IDE에 의해 지속되지 않음).
Clockwork-Muse

답변:


39

다음과 같이 시작 중괄호를 끝과 같은 "순위"에 넣으십시오.

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

15
나는 동의한다. 이집트 괄호는 나에게 두통을 준다.
PiousVenom

8
또한 대부분의 IDE는 아마도 클릭했을 때 버팀대의 파트너를 강조합니다.
StuperUser

3
@TyrionLannister : 마침내 그 스타일에 대한 용어를 줘서 감사합니다! 나는 "mis-aligned braces"가 아닌 다른 이름을 가진 적이 없었다.
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는 여전히 Monica

2
@ Cyborgx37 : 따라서 포인트 3. 전체 코드 블록이 화면에 맞으면 사냥 할 필요가 없습니다. 필자가 작성한 대부분의 / 모든 클래스에서 화면에 맞지 않는 유일한 괄호 쌍은 네임 스페이스 / 클래스입니다.
Steven Evers

포인트 1 & 2에서 제안하는 것은 지금하는 일입니다 ... 그러나 이것은 코딩 할 곳을 떠나서 다음 줄을 어디에 배치 해야하는지 파악하기 위해 코드에 대한 내 견해를 조작하기 시작해야합니다. 포인트 3은 잘 활용되지만 항상 가능하지는 않습니다. 특히 코드에 여러 계층의 using블록이 필요한 경우 ( jake.ginnivan.net/vsto-com-interop 참조 )
JDB는 여전히 Monica를

@ Cyborgx37 : 내 편집을 참조하십시오.
Steven Evers

1
당신이 다른 모든 것들에서 눈에 띄는 색상을 선택하면 Cyborgx37 @ 다음 일치하는 중괄호에 대한 사냥 필요가 없다 (I 잠시, IIRC에 대한 보라색 배경과 흰색 텍스트를 사용) - 당신은 "난 그것을 실질적으로 비명 여기 ! ".
CVn

5

일반적인 규칙은 닫는 중괄호 뒤에 주석을 추가하여 닫는 구조를 나타냅니다.

if {
   ...
} // end if

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

등. 나는이 컨벤션에 온난 한 적이 없지만 어떤 사람들은 그것이 도움이된다고 생각합니다.


16
나는 사람들이 이렇게 볼, 그들은 교환 할 때 /를의 (a 변경 블록의 태초 변경 한 whileA를 for에, 스왑 if그들은 문) 거의 결코 그들을 렌더링, 닫는 주석을 업데이트 할 기억하지 쓸모보다. 이 규칙은 일치하는 특성이 {변경 될 때마다 주석을 유지하도록 강제 할 수있는 경우에만 유용합니다 .
FrustratedWithFormsDesigner

예,이 중 일부를 수행했지만 많은 추가 작업 (및 소음)이 있습니다. 더 직접적인 것이 있기를 바랐습니다.
JDB는 여전히 Monica

5
댓글은 설명해야 하는 이유 결코 무엇인지 또는 어떻게 코드가 하나 그들의 의견에 사람들과 의지 모두 설명을 수행하는 코드는 코드가없는 주석 수정해야 징조 인 읽기 어렵다 의미한다.
지미 호파

1
이것은 왜 아무도이 주석을 표시하지만 실제로는 코드에 주석을 포함하지 않는 편집기를 작성했는지 궁금하게 만듭니다.
Brendan Long

2
@ JimimHoffa : 의견에 대한 더 나은 규칙은 명확성 을 제공해야한다는 것 입니다. 일반적으로 "왜"라는 대답을 의미하지만 다른 것도 의미 할 수 있습니다. 도그마에 얽매이지 말고 때로는 여는 중괄호에서 멀리 떨어진 닫는 중괄호에 주석을 추가하는 것과 같이 실제로 도움이되는 일을 방해합니다.
Bryan Oakley

5

일반적으로 스타일에 상관없이 중괄호를 맞추기가 어려워지면 메소드가 너무 길어서 리팩터링되어야 함을 의미합니다.


5

나는 당신이 중괄호로 힘들어해야한다고 생각합니다. 결국 그들은 당신에게 두 번째 본성이 될 것이며 당신은 그들없이 어떻게 살았는지 궁금 할 것입니다.

그래도 들여 쓰기가 잘되고 간격 규칙이 준수되는지 확인하십시오 (어떤 문제는 중요하지 않습니다).


1 년 후,이 조언은 사실입니다. :)
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는 여전히 Monica

@ 사이보그 37 VIM에서 텍스트를 외부에서 편집하므로 문제가되지 않습니다. 그러나 Visual Studio에서 : Control + A를 누른 다음 "들여 쓰기"버튼을 누르십시오. 새 파일에 대해서만 수행하십시오. 소스 제어에서 비교 비교를 망칠 수 있으므로 기존 파일을 신경 쓰지 마십시오.
mike30

닫는 괄호 / 괄호를 입력하면 VS에 의해 자동 서식이 시작되지만 CTRL + z를 눌러 제안을 거부 할 수 있습니다.
Alex In Paris

1

최근에 기본적으로 다음과 같은 흐름 제어 구성에 대한 두 가지 규칙을 공식화하려고 시도했습니다.

  • 필요한 코드 흐름 구조 만 있으면됩니다.
  • 코드 흐름 구조를 가능한 작게 만들어야합니다

당신이 언급하고 분명히 알고있는 이유 때문에, 나는 이것이 따라야 할 훌륭한 규칙이라고 생각합니다. 이를 달성하기 위해 사용할 수있는 몇 가지 간단한 기술이 있습니다.

  • 최대한 빨리 범위를 종료하십시오 (루프 범위 및 함수 포함).
  • 앞의 if에서 함수를 종료하여 완화 할 수있는 다른 사항을 살펴보고 언급 한대로 범위 종료 기술을 적용하십시오.
  • if 내부의 코드가 외부 코드보다 큰 경우 조건부 검사를 취소하십시오.
  • 루프의 크기가 커져 나머지 방법을 모호하게 할 때 루프 내부의 요인 코드를 다른 방법으로 추출
  • 다른 범위 만 포함하는 모든 범위를 살펴보십시오 (예 : if 이외의 항목이없는 경우 if로 전체 범위를 채우는 함수).

여기 에 설명을 따르지 않는 방법에 대한 예를 자세히 설명 했지만 코드를 잘못된 코드 블록에 넣는 것은 좋지 않으며 유지 관리 중에 버그가 발생하기 쉽습니다.


감사합니다. 리팩토링 할 수있는 블록이있을 수 있습니다. 도움이되지만 여러 개의 중첩 된 using블록 을 리팩터링하는 것은 어렵습니다 .
JDB는 여전히

실제로 블록을 사용하는 @ Cyborgx37은 범위를 충족하는 중첩 된 경우 인라인 될 수 있습니다. 여기를보십시오. stackoverflow.com/questions/1329739/… 기본적으로 단일 라인 흐름 제어가 어떻게 작동하는지 (true) doSomething (); if (true) if (somethingElse) if (otherThings) {doThis (); 그렇게(); 무엇이든해라(); } 그리고 예상대로 ifs가 중첩됩니다 (하나님의 사랑을 좋아하는 코드를 쓰지 말고 다른 방법으로 사용하지 마십시오)
Jimmy Hoffa

예, 블록을 사용한 중첩에 대해 알고 있지만 아래에 한 줄이있는 경우에만 작동합니다. 내 코드의 대부분에서는 그렇지 않습니다. 아직도 매우 도움이 게시물 전체 ... 몇 가지를 배웠다 (+1)
JDB은 여전히 모니카 기억

@ Cyborgx37 네, 스코프 중첩은 추가 비트가없는 경우에만 작동한다는 것을 알고 있습니다. 즉, 사용 방식에 패턴이 있다고 말했습니까? 상단에있는 경우 생성자 또는 하단에있는 처리기를 추가로 생성하는 것이 가능할까요? 그것이 패턴 화 된 경우입니다. 이 문제를 문제로 제기했기 때문에 추측 할 수 있으므로 코드에서 종종 중첩을 사용하여 이러한 문제가 발생할 수 있습니다.
지미 호파

실제로 "AutoCleanup"클래스에서 COM 개체를 래핑하는 팩토리 패턴 구현 작업을 시작했습니다. 그런 다음 using팩토리 클래스 에서 단일 명령문 을 사용하고 배치되면 자동으로 래핑 된 클래스를 모두 처리합니다. 그것은 지금까지 잘 작동하고 있으며 using내 코드 의 문 수를 크게 줄였습니다 .
JDB는 여전히 Monica

1

불행히도 이것은 컴퓨팅에서 가장 오래된 전쟁 원인 중 하나입니다. 양측에서 합리적인 논거를 할 수 있지만 (수직 부동산 경제가 개선되고 개방 브레이스와 시각적으로 괄호를 맞추는 것이 더 쉬워 짐) 간단한 소스 코드 포맷터가 모든 것을 해결해 줄 것입니다. MS Visual C #에는 잘 작동하는 것이 내장되어 있습니다.

그러나 팀의 일원으로 일하는 경우 해당 팀에서 사용하는 규칙을 준수해야하므로 두 스타일 모두에 친숙해지고 브레이스 스타일보다 종교적인 태도를 취하지 않아야합니다.

따라서 배우는 동안 배우기 쉽도록 스타일에 중점을 두어야합니다. 그러나 배우는 동안 다른 쪽을 절반 만 주시하면 괜찮을 것입니다.


1
그것이 ReSharper의 기본 포매터인지 또는 무언가인지 확실하지 않지만 C #을 사용할 때 체크인의 일부로 코드를 다시 포맷하는 옵션 세트가있었습니다. 이렇게하면 작업하는 동안 원하는대로 코드를 포맷 할 수 있지만 체크인시 "프로젝트 표준"으로 다시 포맷됩니다. 우리가 가진 유일한 형식 지정 표준은 탭 대신 공백을 사용하는 것이라고 생각합니다.
TMN

1

Resharper를 사용하면 중첩을 줄이는 방법을 권장합니다. 또한 Bob Martin의 책 Clean Code를 읽으십시오 . 여기서 함수는 한 가지 작업 만 수행해야하므로 각 함수의 길이는 6 줄이어야하므로 많은 중첩 수준을 염려 할 필요가 없습니다.


1

C # Outline 에서 편집기에 도움이되는 애드온이 있습니다 .

이 부가 기능은 중첩 된 코드 블록을 축소, 확장 및 강조 표시하는 기능을 추가하여 C # 용 VS20xx 편집기를 확장합니다. 이 기능을 사용하면 if, while 등과 같은 코드 블록의 중첩 컨텐츠를 쉽게 편집하고 읽을 수 있습니다.


0

Visual Studio에서 코드를 작성하는 경우 구성하는 모든 구조의 시작과 끝 사이에 수직 점을 표시하는 플러그인도 있습니다.

그러나 전반적으로 "Curly-Braces-Soup"에 익숙해 질 때까지 시간이 좀 걸릴 것이라고 생각합니다. (Btw, 나는 그 표현이 정말 마음에 듭니다. 빅뱅 이론의 에피소드 이름과 비슷합니다.)


0

들여 쓰기는 두 구문 스타일 모두에서 현재 위치를 알려줍니다. VB 프로그램이나 C # 프로그램을 한 줄에 작성하면 중첩 구문의 현재 위치를 곧 알 수 없습니다. 기계는 블록 끝 구문 또는 중괄호를 구문 분석하지만 들여 쓰기가 필요합니다.

블록 엔딩 프레이즈는 프로그래밍이 인터랙티브하고 시각적이지 않은 펀치 카드 및 종이 테이프 시대에서 비롯되었습니다. 또는 실제로 대화 형이 아닙니다. 프로그램을 입력하기가 어려웠으므로 프로그래머는 구문 분석 및 오류 복구에 대해 매우 영리한 컴파일러가 필요했습니다.

그 시대에 편집 컴파일 실행주기에는 카드 펀 처로 펀칭 된 카드를 준비한 다음, 점원이 펀칭 된 카드를 가져 와서 기계에 제출 한 작업 제출 창에 줄을 섰을 수 있습니다. 나중에 프로그래머는 다른 창에서 출력물 (종이에 인쇄)을 수집합니다. 프로그램에 오류가있는 경우 출력은 컴파일러 진단만으로 구성됩니다. 처리 시간이 길면 프로그래머가 단일 반복에서 가능한 한 많은 오류를 수정하여 시간 낭비 횟수를 줄여야하므로 진단 품질을 향상시키는 데 도움이되는 경우 입력하는 end if대신 추가 입력 비용 )이 정당화됩니다. 작업 제출 창을 통한 반복.

닫는 중괄호가 없으면 닫히지 않은 중괄호가 무엇인지 알기가 어렵습니다. (컴파일러는 학습 된 추측을하기 위해 들여 쓰기를 구문 분석해야 할 수도 있습니다.) 함수 내에서 닫는 중괄호를 삭제하면 나머지 파일 전체가 해당 함수의 일부인 것처럼 보이며 도움이되지 않는 오류 메시지가 나타납니다. end function구문 이있는 경우 컴파일러는 잘못된 함수가 끝나는 위치를 추론하고 후속 함수를 올바르게 구문 분석하고 구문 분석하여 의미있는 추가 진단을 제공합니다.

코드를 자동으로 들여 쓰고 색상을 지정하는 코드 인식 텍스트 편집기에서 작업 할 때 60 개 이상의 줄을 볼 수있는 고해상도 화면에서 더 이상 서투른 언어에 대한 인수가 적용되지 않습니다. 한 번에 하나의 오류 만 처리 할 수 ​​있도록 프로그램을 빠르게 증분 편집 및 재 구축 할 수 있습니다. 또한 화면에서 프로그램의 큰 부분을 동시에보고 적절한 들여 쓰기를 유지하면 이러한 종류의 중첩 오류 발생을 줄일 수 있습니다. 그리고 좋은 프로그래밍 텍스트 편집기는 입력 할 때 어떤 종류의 구문 오류를 표시합니다. 또한, 구문에 따라 프로그램의 블록을 축소하여 구조에 대한 "개요"와 같은보기를 제공하는 접는 편집기가 있습니다.

Lisp 해커는 처음부터 괄호를 사용했으며 우연히는 아니지만 괄호를 사용하여 프로그램을 작은 덩어리 (표현)로 받아들이는 시스템을 구축하여 대화 형 환경으로 프로그래밍을 개척했습니다.

사실, 파이썬 언어에서 알 수 있듯이 끝 기호는 전혀 필요하지 않습니다. 식별은 구조 일 수 있습니다 . 인간은 이미 기계가 끝 기호 나 구에 의존하는 언어에서도 들여 쓰기를 사용하여 코드의 구조를 파악했습니다.


-1

IDE를 사용하는 경우 Crtl+ k+ D를 누르면 IDE가 나머지 작업을 수행합니다.


어느 IDE 이클립스가 들여 쓰기에 ctrl-shift-i를 사용하고 형식화에 ctrl-shift-f를 사용합니다
ratchet freak

Visual Studio에서 체크인
Jagz W
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.