단일 방법에서 순환 복잡성이 중요한 이유는 무엇입니까?


10

최근부터 Eclipse에 SonarLint를 사용 하고 있으며 많은 도움이되었습니다. 그러나 그것은 순환 복잡성에 대한 의문을 제기했습니다.

SonarLint는 CC 10을 수용 할 수있는 것으로 간주하며, 5 또는 6 개 정도의 경우가 있습니다. 이러한 부분은 값이 다른 변수에 의존하는 맵퍼와 관련이 있습니다 (예 :

  • 필드 A는 문자열 sA에 의존합니다.
  • 필드 B는 문자열 sB에 의존합니다.
  • 필드 C는 문자열 sC에 의존합니다.
  • 등 ...

if각 분야마다 다른 선택을 할 수 없습니다 . 이것은 (다행스럽게도) 나의 선택이 아니라, 스스로 바꿀 수없는 기존의 복잡한 시스템입니다.


내 질문의 핵심은 하나의 방법 으로 너무 높은 CC 가지지 않는 것이 그렇게 중요한가 ? 복잡성을 줄이기 위해 하나 이상의 하위 방법으로 일부 조건을 이동하면 전체 기능의 비용이 감소하지 않고 문제를 다른 곳으로 이동시키는 것 같습니다.

(있는 경우 작은 실수에 대해 죄송합니다).


편집하다

내 질문은 전역 순환 복잡성에 관한 것이 아니라 단일 방법 복잡성 및 방법 분할에만 관한 것입니다 (정확하게 의미하는 바를 설명하는 데 어려움이 있습니다. 나는 여전히 모든 수퍼 메소드를 실행하여 알고리즘에 복잡성을 추가하는 '슈퍼 메소드'에 속하는 경우 조건을 더 작은 메소드로 나눌 수있는 이유를 묻습니다.

그러나 ( 반 패턴에 관한) 두 번째 링크 는 큰 도움이됩니다.




^^^ "화살표"질문은 아마도 코드를 개선하는 방법을 설명한다는 의미에서 더 나은 복제본 일 것입니다. 그러나 순환 복잡성에 대한 귀하의 질문에 대한 자세한 설명으로 인해 첫 번째 질문을 선택했습니다
gnat

메서드를 더 작은 부분으로 나누면 실행되는 총 코드 양이 줄어들지 않지만 발생하는 개별 작업이 명확 해집니다. 그들은 모두 더 큰 전체에 얽혀있을 때보 다 훨씬 더 개별적으로 훨씬 쉽게 이해할 수 있습니다. 최소한 더 큰 범위에서 많은 일회성 중간 변수를 제거합니다.
Doval

1
당신의 특별한 경우를 위해, 나는 "A = extractAFrom (sA);"와 같은 당신의 주요 방법으로 무언가를 할 것입니다. 각 분야. 실제 필드와 그 용도를 알고 있기 때문에 더 나은 이름을 생각해 낼 수 있습니다.
Tin Man

답변:


32

여기서 핵심은 "뇌 용량"입니다.

코드 의 주요 기능 중 하나 는 ... 읽는 것 입니다. 코드는 읽고 이해하기 쉬울 수 있습니다. 또는 어렵다.

CC 가 높으면 하나의 방법 내에서 많은 "레벨"을 의미합니다. 그리고 그것은 암시합니다 : 당신은 인간 독자로서 그 방법을 이해하는데 어려움을 겪을 것입니다.

소스 코드를 읽을 때, 뇌는 자동으로 사물을 원근법에 넣습니다. 즉, 어떤 형태의 "문맥"을 만들려고합니다.

그리고 몇 줄로 구성되고 CC가 매우 작은 작은 방법 (이름이 좋은)이있을 때; 당신의 두뇌는이 "블록"을 쉽게 받아 들일 수 있습니다. 당신은 그것을 읽고 이해합니다. 끝난.

반면에 코드의 CC가 높으면 뇌는 진행중인 작업을 차감하기 위해 많은 "사이클"을 더 많이 소비하게됩니다.

다른 말로 표현하면 , 복잡한 사물 네트워크를 통해 복잡한 사물 네트워크 를 선호하는 경향이 있습니다 . 당신의 두뇌는 작은 것을 이해하는 데 더 좋습니다.


9
기본적으로 기술적 인 문제가 아니라 인간관한 것입니다 . 이것은 참으로 영리한 것처럼 들리지만, 내가 전에 어떻게 생각하지 않았는지 모르겠습니다. 감사 !
Yassine Badache

4
그렇다면 Robert Martin의 "Clean Code"를 구입하는 것을 진심으로 권합니다 (net에서 무료로 pdf를 찾을 수 있음). 읽을 수있는 코드를 만드는 것은 좋은 프로그래머 덕분에 가장 중요하지만 종종 무시 되는 것 중 하나입니다 .
GhostCat 인사말 Monica C.

@YassineBadache CC는 또한 모든 구석과 성기를 테스트하기 어렵게 만듭니다 (전체 적용 범위).
Tulains Córdova

이것도 Dijkstra의 goto paper의 핵심이었습니다 .
Seth Battin

내 경험상 버그는 거의 항상 CC가 높은 메소드에 있으며 버그가 CC가 낮은 메소드에있을 때는 일반적으로 코드의 첫 번째 실행을 숨길 수있는 방법이 전혀 없습니다. 또한 CC가 낮은 방법을 수정할 필요가 거의 없다는 것을 알게되었습니다.
Loren Pechtel

6

CC는 코드 냄새에 대한 다른 모든 규칙과 마찬가지로 휴리스틱 입니다. 절대적인 진실을 알려주는 확실한 안전 기준은 아닙니다. 그렇다면 언어에서 그러한 방법을 불법으로 만들고 사람들이 다른 방식으로 목표를 달성하도록 강요하는 것이 합리적 일 것입니다.

그러나 그것은 지표가 작동하는 방식이 아닙니다. 그 기능들은 것들의 경고 사람들에게 대부분의 시간 없었다 알고. 귀하의 경우, 논리가 복잡하고 대안 솔루션이 논리를 더욱 복잡하게 만든다는 것을 알고 있습니다. 따라서 문제의 주된 목적이 문제 있음을 모르는 사람들에게 경고를 발행하는 것이기 때문에 원시 경험 법칙을 만족시키려는 시도 는 없습니다 .


2
"FieldA가 String sA에 의존하는"OP 상태로 이것을 CalculateFieldA (String sA)로 옮기면 더 복잡한 코드가 생성된다고 확신 할 수 없습니다.
Taemyr

2

요컨대, 코드의 가독성과 유지 관리 가능성에 관한 것입니다.

많은 (중첩 된) 길고 복잡한 방법을 사용하는 if경우 실제로 수행하는 작업을 말하기가 어렵습니다. 비공개 메소드를 추출하여 의미있는 방식으로 이름을 지정하면 훨씬 쉽습니다.


이것은 좋은 대답이지만 조금 짧습니다. 당신이하는 말의 예를 제공 할 수 있고 OP가 요청한 질문에 대해 더 구체적으로 설명하는 것이 좋을 것입니다. "단일 방법으로 너무 높은 CC를 가지지 않는 것이 왜 그렇게 중요한가?"
Machado

2

방법의 순환 복잡성은 방법에 필요한 테스트 사례 수와 관련이 있습니다. 구체적으로, 10의 순환 복잡도는 테스트 케이스가 분석법에 대한 전체 분기 적용 범위를 갖기위한 상한이라는 의미입니다. 또한 테스트해야 할 경로 수에서 불가능한 경로를 뺀 것과 관련이 있습니다.

- 그건 그렇고, 내가 다른 고려 사항에 대한 다른 답변에 동의 정신 개발자의 용량 또는 잠재적 인 문제 또는 리팩토링의 지표 또는 가독성을 측정하고 코드의 유지 보수 .


0

CC는 단지 휴리스틱이며 특정 점수가 '나쁜'방법은 여러 가지에 달려 있습니다.

즉, 항상 높은 CC를 리팩토링해야 할 코드를 강조하는 것으로 간주해야합니다. if문장을 다른 방법으로 옮기는 것이 문제를 숨기고 있다고 말하지만 n 번 복사하는 대신 추상화 할 수있는 패턴이 있습니까? 그것이 긴 if-else사슬 이라면 그것을 switch 문으로 바꾸거나 다형성 또는 다른 것을 사용할 수 있습니까? 깊은 중첩이있는 경우 일부 조건절을 결합 할 수 있습니까? 아니면 다른 클래스로 분리해야하는 별도의 책임을 나타 냅니까?


0

나는 순환 적 복잡성을 경고로 본다. 코드를 읽을 수 있고 이해하기가 너무 복잡하지 않은 경우 코드에 대해 크게 걱정하지 않아도 될 것입니다. 걱정해야 할 더 중요한 것이있을 수 있습니다.

언급 한 CC의 종류를 줄이는 한 가지 방법은 질문에 Java 태그를 달아 다형성을 사용하는 것입니다. 따라서 코드 경로를 문자열로 입력하는 대신 잘 명명 된 클래스를 사용할 수 있습니다. 이것은 도움이 될 수 있지만 때로는 과도하며 코드를 이해하기가 더 어려워 질 수 있습니다.

그러나 유지 관리하기 어려운 코드의 표시 일 수 있습니다. 메소드를 읽을 때 각 코드마다 어떤 코드 경로를 내려갈 수 있는지 쉽게 알 수 있습니까? 코드 기반을 잘 모르고 코드에서 관련이 있지만 더 많은 것을 찾고 있다면이 방법을 건너 뛸 수 있습니까? 일부 사람들은 설명적인 이름을 가진 많은 1/2 줄 방법으로 분할 방법을 옹호하지만 때로는 교체하려는 코드보다 읽기가 더 어렵다고 생각합니다.

궁극적으로 유지 관리는 어려운 문제이며 어떤 것이 더 읽기 쉬운 지 결정하는 것은 사용자의 몫입니다. 당신이 이것에 대해 생각하고 있다는 사실은 당신이 올바른 길을 가고 있다는 것을 의미합니다. 몇 년 만에이 코드를 해독해야하는 관리자는 여러분 일 것입니다. 따라서 가능한 한 쉽게 만드십시오.


0

코드를보고 (브레인 사이클) 얼마나 많은 시간을 소비하고 코드가하는 일을 이해하는지에 달려 있습니다.

  • 10 라인 방법을 고려하십시오-아마도 그것이하는 일을 이해하는 데 몇 분이 걸릴 것입니다.
  • 100 라인 방법을 고려하십시오. 현재 수행중인 작업을 이해하려면 1 시간 이상이 소요될 수 있습니다.
  • 1000 라인 방식을 고려하십시오-현재 수행중인 작업을 이해하려면 하루 이상이 소요될 수 있습니다.

또한 더 큰 방법은 테스트하기가 어렵고 어떤 종류의 동작이 발생할 수 있는지 예측하기가 더 어렵습니다.

순환 복잡도는 척도입니다. 이 경우 값이 클수록 잠재적 인 문제를 나타냅니다. 복잡한 코드는 이해하는 데 시간이 오래 걸리고 덜 복잡한 방법만큼 철저하게 테스트되지는 않습니다. 따라서 리팩토링 및 유지 관리 목적으로이 측정법과 복잡한 코드 영역을 확인하는 것이 중요합니다.

고려해야 할 또 다른 사항은 복잡한 코드를 업데이트하는 것입니다. 개발자는 분석을 수행 할 때 코드의 복잡성을보고 코드를 변경하는 것이 다소 위험하다고보고 할 수 있습니다.

따라서 의사 결정을 위해 활용되고 사용될 수있는 복잡성을 측정하는 데 많은 가치가 있습니다.


1
죄송합니다 Ghost Cat 답변이 매우 유사하므로 페이지를 새로 고쳐야합니다.
Jon Raynor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.