C# 순환 복잡도(CC), 계산법부터 CA1502 임계값과 리팩터링 예제까지 정리
- 순환 복잡도(CC)는 메서드의 독립 실행 경로 수를 세는 지표로, 분기문 개수에 1을 더해 계산함. if, while, for, case, &&, ||, ?:, ?? 등은 세고 else, do, try, return, 메서드 호출은 세지 않음.
- 1976년 Thomas McCabe가 그래프 이론으로 도입했고 M=E-N+2P 공식으로 정의함. 도구들은 대개 1에 결정점 개수를 더한 형태로 계산함.
- 점수가 곧 메서드를 완전히 커버하는 최소 테스트 케이스 수를 뜻함. 10이 전통적 상한이고 25 초과는 Microsoft CA1502 분석기가 과도로 표시함.
- if 6개와 && 1개를 쓴 주문 처리 예제의 CC는 8로 완전 커버에 테스트 8개가 필요함. 글은 이를 CC 2, 2, 5짜리 작은 메서드 여러 개로 쪼개는 리팩터링을 보여줌.
- else는 짝이 되는 if가 이미 대안 경로를 만들어 점수를 올리지 않고, switch는 키워드가 아니라 case마다 1씩 더함. C# 패턴 매칭(and, or, switch 식)도 같은 방식으로 가산됨.
Hacker News opinions
ndepend 같은 도구로 에이전트 리팩터링을 유도하는 사람 있음? 나는 C#이랑 파이썬 의존성 그래프를 만들어서 로컬 DB에 넣어두는데, 에이전트가 이걸 잘 파고들어서 리팩터 아이디어를 뽑아내더라. 순환 의존성은 단순 도구로도 잡히고, 클러스터링 같은 더 복잡한 도구를 쓰라고 시키는 편임.
나는 의존성 그래프에 CC랑 커버리지 데이터까지 로컬 스토어에서 먹여주는데 잘 먹힘. 순환 의존성이나 CC 높은 핫스팟 찾는 데 특히 좋았음.
보안 관점에서 CC는 꽤 중요함. 나는 파이썬 코드 보안 등급 매길 때 쓰는데, nocomplexity.com에 정리된 방법이 검증돼 있고 탄탄함.
복잡도가 낮으면 보안이 실제로 좋아진다는 연구가 있음? 얼마나 개선되는지 수치로 본 자료가 궁금함.
CC는 유용하지만 다형성이 자리 잡기 전에 만들어져서 명시적 분기만 셈. C#에서 가상 메서드 호출은 점수를 안 올리는데, IEnumerable 같은 흔한 인터페이스면 경로가 수천 개, 라이브러리면 사실상 무한임. 고차 함수도 마찬가지고. CC 상한이 유지보수 만능은 아님. 내가 해독한 제일 이해 안 되는 함수들이 오히려 CC가 낮았음.
글 읽으면서 뭔가 어긋난다고 느꼈는데 이 댓글 보고 알겠음. 예제에서 리팩터링한 새 코드가 더 복잡해 보임. 중첩 if를 다른 언어 기능으로 아예 뜯어고치는 게 맞을 듯.
CC 낮은데 이해 안 되는 함수 얘기 공감함. EEG로 인지 부하랑 소요 시간을 측정한 연구를 보면 우리가 쓰는 복잡도·가독성 지표가 실제와 부분적으로만 맞음.
전 회사에서 CC가 갑자기 중요해진 시점이 AI 툴로 코드 변경을 남발하던 때랑 겹쳤음. 그 뒤로 리뷰 불가능한 diff가 쏟아졌음.
나는 에이전트용 결정론적 품질 게이트에 CC를 넣었음. 플라시보인지는 모르겠지만, 에이전트가 프로젝트 제약을 벗어나는 경우를 꽤 많이 잡아냄.