인지복잡도
인지복잡도는 순환복잡도의 단점을 보완하기 위해 제안된 지표이다.
순환복잡도의 단점
순환복잡도는 계산 및 설명이 간단하다는 장점이 있지만 여러 단점들이 있다.1
- 순환복잡도 점수와 실제 인지적 복잡성 사이에 간극이 있는 경우가 많다.
- 순환복잡도는 람다식이나
try-catch
등 순환복잡도가 처음 제안된 1976년 이후에 널리 쓰이기 시작한 문법들을 고려하지 않는다. (원래 논문2에서 예시로 쓴 언어는 포트란이었다.) - 순환복잡도는 기본 점수가 1점이기 때문에, 클래스에 메서드가 세 개 있으면 각 메서드에 분기가 하나도 없더라도 클래스 전체의 순환복잡도가 3점이 된다.
위와 같은 문제로 인해 순환복잡도는 테스트가능성(testability)을 측정하기엔 좋지만 유지보수성(maintainability)을 측정하기엔 부족한 면이 있다. 인지복잡도는 이러한 문제를 개선한다.
인지복잡도 계산
- 왼쪽에서 오른쪽으로, 위에서 아래로 읽는 선형적 흐름에 분기가 생기면 증가3
- 중첩된 분기인 경우 추가로 증가3
- 조건문 안에 여러 변수가 쓰였더라도 동일한 논리 연산자로 연속적으로 묶여 있으면 한 덩어리로 취급(예:
a && b && c
는 한 덩어리,a && b || c
는 두 덩어리)3 - 옵셔널 체이닝 등 이해가능성을 낮추지 않는 분기는 무시3
인지복잡도 암산을 위한 휴리스틱
코드의 제어 구조를 그래프 구조로 단순화한 뒤 경로를 세는 방식인 순환복잡도와 비교하면 인지복잡도는 계산 방식이 상대적으로 너저분하다(백서1 참고). 실질적인 인지 부하를 고려해겠다는 취지를 고려하면 어쩔 수 없기는 하다. 자동으로 순환복잡도를 계산해주는 도구를 쓰는 경우라면 상관 없지만 코드 리뷰를 하거나 머리 속으로 복잡도를 직접 계산해보려고 하는 상황이라면 인지복잡도를 너무 정직하게 따지려고 하면 오히려 부작용이 클 것 같다. 이런 상황이라면 순환복잡도를 아래와 같이 최소한으로만 개선해서 생각해도 충분히 유용하다.
- 기본값을 0으로. 즉, 선형 흐름이면 1점이 아니라 0점으로 계산.
- 중첩된 분기에 가중치 부여.
위 두 가지만으로도 상당히 많은 상황에서 순환복잡도를 개선할 수 있다.
Tools
- eslint-plugin-sonarjs: SonarJS rules for ESLint