어떤 시점에서 루프 내에 루프를 갖는 것이 금기입니까?


23

그냥 궁금해서 Linus Torvalds 에서 이것을 읽은 후 for 루프 내에서 for 루프가 가장 많이 사용되었습니다 .

탭은 8 자이므로 들여 쓰기도 8 자입니다. 들여 쓰기를 4 자 (또는 2 자)까지 만들려고하는 이단 운동이 있으며, PI의 값을 3으로 정의하려고하는 것과 비슷합니다.

이론적 근거 : 들여 쓰기의 기본 개념은 제어 블록이 시작하고 끝나는 위치를 명확하게 정의하는 것입니다. 특히 20 시간 동안 화면을보고있을 때 들여 쓰기가 큰 경우 들여 쓰기가 어떻게 작동하는지 훨씬 쉽게 알 수 있습니다.

이제 어떤 사람들은 8 자 들여 쓰기를하면 코드가 오른쪽으로 너무 멀리 이동하여 80 자 터미널 화면에서 읽기가 어렵다고 주장 할 것입니다. 이에 대한 답은 3 단계 이상의 들여 쓰기가 필요한 경우 어쨌든 망쳐 져 프로그램을 수정해야한다는 것입니다.

https://www.kernel.org/doc/Documentation/CodingStyle

루프의 세 번째 레이어로 이동하는 것이 용납 할 수없는 관행이라고 생각하고 내 코드 (기본적으로 Qt)를 재구성 할 것입니다.

Linus가 농담 했습니까?

언어 나 응용 프로그램에 따라 달라 집니까?

3 단계 이상의 루핑 레벨이 절대적으로 필요한 것이 있습니까?


8
들여 쓰기에서 루핑 수준으로 점프하는 이유가 혼란 스럽습니까? 들여 쓰기에 대해 큰 따옴표가 있으며 갑자기 중첩 된 루프에 대한 질문이 이어집니다.
Pieter B

5
리누스는 아마도 그 섹션에서 농담이 아닐 수도 있지만, 이것은 하나의 스타일 가이드 일 뿐이며, 같은 스타일 가이드는 "커널 코딩 스타일이 매우 단순하다"고 강조합니다. 즉, 다른 스타일보다 더 중요합니다.

5
@Akiva 네 개의 중첩 루프가 없으면 4 차원 행렬을 통과 할 수 없습니다. 누군가가 당신이 가질 수있는 중첩 루프의 양을 제한한다는 것은 미친 짓입니다. 리누스는 분명히 매우 일반적이었고, 당신이 읽은 모든 것을 성서로 받아 들여서는 안됩니다.
Alternatex

9
@Alternatex 4 개의 루프가 필요하다는 것은 어휘 적으로 중첩 되어야한다는 것을 의미하지는 않습니다 . 인용에서 우리는 실행에 대한 것이 아니라 코드를 구성하는 방법에 대해 이야기하고 있습니다.

4
@delnan 나는 4 개의 중첩 루프가 시각적으로 즐겁다는 것을 말하지 않고 그것에 대해 갈 수있는 다른 방법이 있다는 것을 알고 있지만 OP가 Linus의 단어를 문자 그대로 사용하는 방법이 어리 석다는 것을 알았습니다. 들여 쓰기의 4 단계 = 세계의 끝. 휴식 좀 줘
Alternatex

답변:


19

커널은 간단한 알고리즘을 강력하게 선호합니다

다양한 알고리즘에는 루프 내에 깊게 중첩 된 루프가 필요할 수 있지만 Linux 커널과 관련하여 (견적이 언급 된) 일반적으로 빠른 실시간 응답이 필요합니다. 이러한 맥락에서 딥 네 스팅은 코드 흐름이이 도메인에 비해 너무 복잡하고 가독성이나 들여 쓰기 문제가 아니라 실행 특성으로 인해 변경되어야 할 수도 있음을 나타내는 냄새입니다.

또한 Linux 커널은 감사 및 테스트 요구 사항과 관련하여 대부분의 응용 프로그램 코드와 다르므로 단일 함수에 4+ 수준의 중첩 알고리즘 을 사용 하지 않는 것이 좋습니다. 가능한 모든 제어 흐름 및 엣지 사례를 포함하여 각 코드 조각이 정확 하고 상세하게 수행하는 작업을 확인해야합니다 . 깊게 중첩 된 코드는 방해가됩니다.


C와 같은 하위 수준의 언어에서 깊게 중첩 된 루프는 일반적으로 because하위 수준의 언어를 사용하는 더 많은 금기 프로젝트가 간단한 알고리즘에 중점을 둔 코딩 스타일의 이점을 얻는다고 생각하십니까?
Akiva

4
@ Akiva 나는 그것을 더 낮은 수준의 언어 또는 C와 같은 것이 아니라 코드 영역에 묶을 것입니다. 나는 유사한 지침을 신청할 것이라고 생각하는 어떤 코드를 작성할 때 언어 해야한다 견고를, 보안 집중하고 다른 것들의 비용 감사. 예를 들어 Java 또는 Haskell로 작성된 암호화 라이브러리는 가능한 한 간단하게 유지하고 중첩을 제한하며 가능한 모든 결과로 쉽게 분석 할 수있는 덩어리로 모든 것을 분리하려는 스타일로 작성해야합니다.
Peteris

매우 통찰력 있고 유용한 의견 / 응답. 그냥 궁금하다. 낮은 수준의 언어를 사용하는 오늘날 어떤 종류의 프로젝트가 강력하고 감사 가능하며 안전하지 않은가?
Akiva

7
예를 들어 @Akiva는 성능상의 이유로 C를 사용하고 싶지만 제어 된 조건에서 내부적으로 실행되므로 견고성이나 보안에 대해서는 크게 신경 쓰지 않는 기계 학습 코드입니다. 또한 소형 임베디드 마이크로 컨트롤러에서 간단한 비즈니스 기능을 구현합니다. 실제로 품질 및 보안을 희생하면서 기능 및 개발 속도에 중점을 둔 비즈니스가 있지만, 저수준 언어를 사용합니다.
Peteris

49

어느 정도까지, 나는 "Tabs are 8 characters" 에서이 인용을 진지하게 받아들이지 않았다 . Tabulators의 요점은 고정 된 수의 문자가 아니라는 것입니다 (만약 탭이 하나의 문자입니다). 얼마나 많은 똥. 마찬가지로, 나는 완전히 (대한 하드 및 빠른 규칙을 설정하는만큼 "들여 쓰기의 세 가지 수준"의 하드 및 빠른 규칙을 설정하는 것은 제정신이라고 확신 아니에요 아무것도 제정신입니다).

그러나 들여 쓰기 수준을 제한하는 것은 일반적으로 합리적인 제안이며, 당신에게 놀라운 일이 아닙니다.

궁극적으로 프로그램에 세 가지 수준의 반복이 필요한 경우 프로그램에 필요한 것 입니다. 인용의 정신은 프로젝트의 요구 사항을 마술처럼 완화시키는 것이 아니라 코드가 더 선명하고 표현력이 있도록 논리를 함수와 유형으로 끌어 올리는 것입니다.

이것은 들여 쓰기 수준과 관련하여 위에서 주어진 동일한 지침으로 다시 피드백됩니다. 코드를 구성하고 앞으로 몇 년 동안 코드를 읽고, 유지 관리 가능하며, 재미있게 수정하는 방법에 관한 것입니다.


6
탭이 8 자라는 "선언"은 특히 커널 개발과 관련이 있다고 생각합니다. 이 인용문은 특정 프로젝트에 대한 코딩 가이드 라인에서 발췌 한 것으로 일반적인 사용 가이드 라인이 아니므로 상당히 의견이 많이 필요합니다.
Lie Ryan

6
@LieRyan : 그렇다면 여전히 어려워요. 탭을 얼마나 넓게 설정해야하는지에 대한 코딩 가이드 라인이 없습니다! 그러나 나는 Linus가 그것을 알고 있다고 생각합니다.
Monica와의 가벼움 경주

6
물론 그것의 언어 별 - 당신이 당신의 클래스, 네임 스페이스 안에 들여 쓰기, 그리고 당신도 전에 당신의 방법에 ... 당신이 들여 쓰기의 3 단계에서 이미 걸 일반적인 C #에서 이야기 제어 흐름 문 기관이 인에 관하여 들여 쓰기.
PeterL

3
@LightnessRacesinOrbit "탭은 8 자입니다."라는 의견을 해석하는 것은 편집기에서 탭을 8 개 너비로 개인적으로보아야한다는 것을 의미하는 것이 아니라 스타일 가이드의 다른 규칙 (예 : "줄 길이 제한")을 의미합니다. "는 열이 80 개이며 이것이 가장 바람직한 제한입니다.") 탭을 8 열로 처리해야합니다. 이는 함수 호출의 인수 정렬에 관한 다른 규칙과도 관련이 있습니다. 다시, 나는 그 줄의 의도가 당신이 탭을 전혀 그렇게 보도록 강요하지 않는다고 생각합니다. 전 4 개의 넓은 탭으로 커널 패치를 수행했으며 마지막에 코드를 리플 로우했습니다.
Vality

4
@underscore_d : 내가 틀린 것 같습니다 :-OP Outside of comments, documentation and except in Kconfig, spaces are never used for indentation, and the above example is deliberately broken.의 인용문에서 6 단락.
slebetman

16

요점은 모든 흐름 제어 구문과 동일합니다. 코드를 이해하기 어려운 경우 리팩터링해야합니다. 다차원 배열을 약간 조작하는 경우 가장 안쪽 루프의 논리가 간단하다면 5-6 깊이의 루프를 중첩하는 것이 적절할 수 있습니다. 그러나 복잡한 비즈니스 로직을 처리하고 있고 루프 본문이 12 줄 이상인 경우 둘 이상의 루프를 중첩하지 않을 수 있습니다. 코드 의 순환 복잡성 을 계산해 볼 수는 있지만 문제의 코드는 가독성과 유지 관리 가능성입니다.


11
정확하게. 토발즈가 허술하다고 제안하기는 너무 쉽다. (물론 그는 당신의 취향에 비해 너무 단단 할 수 있지만, 실제 문제를 일으키는 실제 개발 문제를 설명하고 있습니다. 당신은 그가 말한 것을 정확하게 할 필요는 없지만, 그가 말하는 이유에 대해 생각해야합니다.
Scant Roger

7
@ScantRoger 사실, 그 Torvalds-quote는 유머 감각이 없다면 너무 딱딱하게 들립니다. 내가 기억 하듯이, 같은 문서의 앞부분에서 그는 GNU 코딩 스타일 가이드 라인의 사본을 인쇄하여 일종의 의식으로 태울 것을 제안합니다. 그렇게 진지하게 받아들이지 않습니까? 이 인용에서 그의 주요 요점은 리눅스 커널의 들여 쓰기를 8 칸, 더 많거나 더 적은 것으로 정의하는 것입니다. 마지막 문장은 그 점에 밑줄을 긋고 더 많은 들여 쓰기 수준을 사용해서는 안된다는 말은 아닙니다. 단단하지 않습니다.
cmaster

1
@cmaster 컨텍스트에 감사드립니다. 귀하의 질문에 대한 답변으로, 나는 진지하게 아무것도 취하지 않습니다. ;)
Scant Roger

2
@cmaster 다음 github pull 요청과 커밋 메시지의 줄 길이에 대한 응답을 읽습니다. 그는 총체적인 견해입니다.
Gusdor

3
의식적으로 GNU 코딩 지침을 태울 필요는 없지만 실제로는 어느 시점에서나 순서대로 진행됩니다.
dmckee

13

Linus가 농담 했습니까?

이 작품은 장난스러운 스타일로 작성되어 저자가 코딩 스타일이 심각한 실무자들 사이에서 논의되는 방식에 익숙하다는 것을 암시합니다. 우리는 그것이 개인적인 취향의 문제라는 것을 완벽하게 이해합니다. 그는 많은 말로, "Coding style is very personal, and I won't _force_ my views on anybody"적어도 개인적으로 유지하는 코드 외부에 있다고 말합니다 . 그러나 주어진 프로젝트에서 스타일의 일관성은 매우 좋습니다. 주어진 함수에서 여러 스타일을 처리하는 것보다 싫어하는 스타일로 코딩하는 것이 좋습니다.

다음은 분명히 재미있는 글쓰기의 예입니다.

However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:

int function(int x)
{
    body of function
}

Heretic people all over the world have claimed that this inconsistency
is ...  well ...  inconsistent, but all right-thinking people know that
(a) K&R are _right_ and (b) K&R are right.  Besides, functions are
special anyway (you can't nest them in C).

장난이 심하다 (1).

3 단계 최대 값은 쌍곡선 일 수 있지만, 들여 쓰기를 제어 할 수 없도록 유지하는 것이 좋습니다. 나는 커널 소스를 grep하지 않고 네 개의 탭 문자 시퀀스를 세지 않을 것이지만 Torvalds가 쓴 적어도 하나를 찾을 수있을 것이라고 확신합니다.

반면에 누군가가 종종 3 단계의 들여 쓰기를 초과하지 않고 Linux 커널을 작성할 수 있다면 3 단계 한계는 자신의 코드에서 잠시 동안 시도해 볼 가치가있는 운동 일 수 있습니다. 이것은 섹스 변화와는 다릅니다. 평생의 약속이 아닙니다.

인터넷에서 Torvalds (2)보다 프로그래밍을 훨씬 잘 이해한다고 생각하는 사람을 만나면 어떤 종류의 사람들이 인터넷에서 큰 대화를 좋아하는지 알 수 있습니다.

다른 한편으로, 그는 여덟 개의 공백 탭에 대해 범죄 적으로 잘못되었습니다. 그것은 감금 상태로 유지되고 슬롯을 통해 공급되어야하는 사람의 열망입니다. 네 개의 공백이 분명히 맞습니다.

(1) 그러나 어떻게 그가 타원 앞에 공백을 두 개, 그 뒤에 공백 두 개를, 그리고 완전히 멈춘 후 두 공백을 잘못 두는지를 주목하십시오. 잘못된, 잘못된, 잘못된. 그리고 나서 그는 이단자들을 징계 할 용감한 담즙을 가지고 있습니다. 이단은 너야, 토발즈! 그건 너다!

(2) " 소스 제어 시스템을 설계하는 방법 이해 "에 대해 이야기하고 싶다면 토론의 여지가있을 수 있습니다.

참고 : 동일한 편집을 반복적으로 제출 한 친애하는 사용자 : 인용 된 자료의 형식은 작성자가 의도 한대로 정확하게 유지됩니다. 고정 너비 텍스트의 형식을 공정하게 생각한 사람이 고정 너비 텍스트로 작성된 고정 너비 텍스트의 형식에 대한 에세이에서 나온 것이기 때문입니다. 형식은 저자의 의도의 의식적이고 의도적 인 부분이며 주제와 관련이 있습니다.

또한 나는 내 자신의 텍스트에서 그 형식을 다시 언급했다. 사전 서식을 설정하면 각주 (1)가 횡설수설됩니다. 사전 서식이 제거되면 문장 끝에서 완전히 멈춘 후 공백 쌍을 참조하는 각주 (1)의 텍스트가 있어야합니다. 어쨌든 그 주석을 작성했을 때보 다 덜 재미있어서 각주를 제거하는 근거를 알 수 있습니다. 그러나 각주를 제거하지 않고 서식을 제거하는 것은 도움이되지 않습니다.


3
훌륭한 답변. +2 ... 자격 것이다 사례 중 하나 (참고 : 주위에 잘못된 공간 .이 댓글 ;-)에서)
cmaster

2
당신이 지적한 Linus의 소개 단락은 매우 중요하므로 그렇게 해 주셔서 감사합니다! 첫 문장은 문맥 preferred coding style뿐만 아니라 다음과 같이 매우 중요하다고 생각합니다.but this is what goes for anything that I have to be able to maintain
Chris Haas

9

Linus는 매우 무뚝뚝한 말하기 스타일과 건조한 유머 감각을 지녔지 만이 경우 농담하지 않았습니다. 알고리즘 이 두 수준보다 깊게 중첩되어야 하는 상황이 있지만 코드 들여 쓰기 이외의 다른 방법을 사용하여이를 수행 할 수 있습니다. 리눅스 커널 스타일 가이드는 깊게 중첩 된 루프를 유지하기가 어렵 기 때문에 이러한 다른 방법을 선호합니다. 이것이 Linus가 말하는 것입니다.

대체 방법의 일부 예에서는 재귀를 사용하거나 내부 루프를 자체 함수로 분리하거나 중간 데이터 구조를 만들 수 있습니다.

과도한 중첩은 작성하기는 쉽지만 읽기가 어려운 경우 중 하나입니다. 큰 탭 깊이를 설정하는 것은 Linus가 쓰기를 더 성가 시게하는 방법입니다.


3

질문을하는 사람과 질문하지 않은 사람에 대한 조언이 다른 많은 질문이 있습니다. "두 레벨 이상으로 중첩 된 루프가 있어야합니까?"라고 묻는다면 그 질문을하는 사람은 아니오입니다. 요청하면하지 마십시오. 당신이 물어볼 필요가없는 충분한 경험이 있다면, 당신은 각 경우에 정답이 무엇인지 안다. 대답이 당신을위한 것이 아니기 때문에 대답에 동의하지 않는다면 논쟁하지 마십시오.


1

이것은 개를 흔드는 꼬리의 교과서 사례 인 것처럼 보입니다.

80 문자 디스플레이를 가지고 있다면 물론 코드에 가장 적합한 구조를 만들지 않아도 코드를 가장 잘 맞출 수 있습니다 .

나머지 포인트를 해결하려면 다음을 수행하십시오.

나는 그것이 받아 들일 수없는 관행이라고 생각했다.

나는 당신이 이것에 대해 너무 많이 읽고 있다고 생각합니다. 문맥을 제대로 이해하지 않고 복음으로 읽은 모든 것을 가져 가려는 충동에 저항하십시오.

농담 했어?

상황을 확인하기는 어렵지만 위의 원래 요점을 참조하십시오.

언어 나 응용 프로그램에 따라 달라 집니까?

매우 그렇다. 터미널 (또는 터미널 에뮬레이터)에서 코딩 할 가능성이있는 메인 프레임 / 중급 언어를 사용하십시오.

3 단계 이상의 루핑 레벨이 절대적으로 필요한 것이 있습니까?

예, 일부 무차별 알고리즘에서는 매우 일반적입니다. 프로젝트 오일러의 문제 31 을 참조하십시오 . 이것은 많은 루프 (정확히 8)를 사용하여 무차별하게 해결 될 수있는 문제의 전형적인 예입니다.


1
문제 31은 bruteforce가 필요하지 않고 동적 프로그래밍 알고리즘을 사용하여 해결할 수있는 것처럼 보입니다 (편집 : bruteforce 알고리즘을 사용하는 경우 코드 구조가 최고가 아님). 또한 Linus의 요점은 코드에 많은 수준의 들여 쓰기가 필요한 경우 코드에 가장 적합한 구조는 아니라는 것입니다.
Vincent Savard

2
@VincentSavard 절대 무례한 힘 이 필요 하다고 말한 적이 없다 두 번째 요점에 동의하지 않는 경우가 있습니다-때로는 가장 명확하고 간결한 접근 방식이며 어떤 경우에는 가장 효율적이지 않습니다.
Robbie Dee

1
그런 종류의 문제로 나는 보통 루프를 들여 쓰지 않습니다. 필자는 20 개의 중첩 루프가 있고 하나의 경우에 쓰기가 쉽지만 들여 쓰기가 없으므로 루프가 거의 동일하다는 것을 알 수 있습니다.
gnasher729

1
@ RobbieDee : 내 요점은 많은 루프로 해결되는 문제의 예는 알고리즘이 동적 프로그래밍 솔루션만큼 효율적이지 않으므로 많은 수준의 들여 쓰기가 필요하지 않다는 것입니다. 따라서 Linus가 말했듯이 더 나은 솔루션을 사용하면 들여 쓰기 수준을 제거 할 수 있습니다. 당신이 말한 것에 동의하기 때문에 당신은 또한 나의 두 번째 요점을 오해했습니다. 때로는 최상의 솔루션입니다. 때때로 자주 발생하지 않으며 가능성이 낮습니다.
Vincent Savard

1
Linus의 인용문에 따르면 문제 -31에 대한 무차별 강요와 같은 코드가 필요한 경우 어쨌든 망할 수 있습니다. 빠르고 간단하지 않으며 커널 작업 이 빠르고 간단 해야합니다 . 커널에 O (n ^ 4) 알고리즘을 포함 시키면 성능 또는 서비스 거부 문제가 발생할 위험이 있으므로이 권장 사항은 Linux에서 기본적으로 부적절하고 원할 수있는 코드의 표시라고 경고합니다.
Peteris

0

Linus가 농담 했습니까?

아니요, 공식 지침입니다.

언어 나 응용 프로그램에 따라 달라 집니까?

코딩 지침은 일반적으로 언어와 응용 프로그램에 따라 다르지만 깊게 중첩 된 코드는 항상 독자에게 부담을줍니다.

중첩 코드의 문제점은 일반적으로 순환 복잡성을 증가 시킨다는 것입니다. 즉, 코드가 중첩 될수록 잠재적 인 실행 경로가 함수 내에 존재한다는 것입니다. 잠재적 인 실행 경로의 조합 폭발은 코드에 대한 추론을 어렵게하므로 일반적으로 피해야합니다.

왜 3입니까? 주관적인 코딩 지침은 시행하기 어렵고 자동으로 시행하기가 불가능합니다. 최대 들여 쓰기 수준에서 객관적인 코딩 지침을 설정하려면 Linux 커널에서 3을 선택해야합니다.

그것은 임의적이며 분명히 충분합니다.

3 단계 이상의 루핑 레벨이 절대적으로 필요한 것이 있습니까?

그러나 알고리즘 측면에서는 아마도 표현력이 충분한 언어에서는 코드를 더 작은 청크로 리팩토링 할 수 있습니다 (함수 또는 클로저와 상관없이).

계약을 철자하지 않고도 서로를 호출하는 작은 중첩과 많은 작은 함수로 난독 화 된 코드를 작성할 수 있습니다 ...

... 그러나 계약이 명확한 작은 기능은 계약이 명확한 큰 기능보다 감사하기가 훨씬 쉽습니다.


2
이것이 공식적인 지침 일지 모르지만, 지침이 적용되지 않는 커널 코드에서 장소를 찾는 것은 사소한 일입니다.
MikeB

1
@MikeB : 모든 더 많은 이유는 ... 자동으로 가이드 라인을 적용하기
마티유 M.에게

1
@MatthieuM. 지침과 필수 요구 사항의 차이점을 이해하고 있습니까? 일반적인 "거짓의 법칙"(원하는 경우 지침)으로서 지침은 권장 사항과 유사하며 적용되지 않습니다.
Brendan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.