Skip to main content
This article walks through a practical code complexity audit and the kinds of metrics and remediation recommendations an automated or manual audit should produce. The worked example analyzes an Express “login” demo codebase with a focus on:
  • Cyclomatic complexity
  • Cognitive complexity
  • Lines-of-code thresholds
  • Coupling and cohesion
  • Concrete refactoring suggestions and drop-in code snippets
A presentation slide titled "Code Quality Metrics & Standards" with a dark, curved shape on the right containing the blue word "Demo." A small "© Copyright KodeKloud" notice appears in the bottom-left.
Getting started — run the auditor/assistant from the project directory:
Repository containing prompts and examples referenced in this lesson:
Audit scope
  • Analyze code complexity across the codebase
  • Identify high-complexity functions and methods
  • Calculate or evaluate:
    1. Cyclomatic complexity
    2. Cognitive complexity
    3. Lines-of-code (LOC) metrics
    4. Coupling metrics
    5. Cohesion analysis
  • Produce a structured findings report including an importance scale (1–10) and remediation with precise code-level fixes where possible
Common thresholds used in this audit (configurable) Key considerations
  • Cyclomatic complexity is deterministic (counts decision points).
  • Cognitive complexity models human understanding and is more subjective.
  • LOC thresholds are human-oriented aids to improve maintainability.
  • Coupling and cohesion are architectural metrics that guide refactors and design choices.
Audit — condensed report

Executive summary

The Express Login Demo is generally low to moderate in complexity. Most modules are concise and well-scoped, but there is a hotspot in the authentication route handler that exceeds recommended thresholds for cyclomatic complexity, cognitive complexity, and function length. Primary remediation: refactor the login handler into smaller single-responsibility functions, extract error handling and database access into separate layers, and simplify nested conditionals to reduce cognitive load and complexity. Overall assessment: LOW to MODERATE complexity with targeted hotspots.

1. Cyclomatic complexity

Finding: a single high-complexity function in the auth route.
  • Finding #1: Login route handler
    • Location: routes/auth.js:17-96
    • Cyclomatic complexity: 12 (threshold > 10 flagged)
    • Importance: 8/10
    • Why: multiple decision points (validation, user lookup, password verification, error handling switch), with nested if/else branches
Recommended remediation
  • Extract validation, user lookup, password verification, token generation, and error mapping into separate functions.
  • Replace complex switch-based error handling with a small reusable error-mapper function (see remediation snippets below).

2. Cognitive complexity

Finding: the same login handler has high cognitive load.
  • Finding #2: Login handler — high cognitive complexity
    • Location: routes/auth.js:17-96
    • Cognitive complexity: ~15
    • Importance: 7/10
    • Contributing factors:
      • Nested conditionals (validation → user check → password check)
      • Database queries interleaved with business logic (mixed abstractions)
      • Inline switch with multiple DB-specific error cases
      • Single function performing validation, auth logic, token generation, and error formatting
Recommended remediation
  • Move database operations into a repository/service layer.
  • Move validation to a dedicated validator function or middleware.
  • Keep the route handler as a thin coordinator that calls small helpers and returns early on failures.
Example refactor snippets (drop-in helpers)
Note: the above helpers are intentionally minimal — they separate concerns and reduce nesting in the route handler.

3. Lines-of-code metrics

  • Functions over 50 LOC: 1 (auth/login handler ~80 LOC)
  • Files over 300 LOC: 0
  • Classes over 500 LOC: 0
Recommendation
  • Break the large login function into smaller functions with clear responsibilities (validation, user repository lookup, password verification, token creation, error mapping). This improves testability and readability.

4. Coupling metrics

  • Efferent dependencies for auth module:
    • express, bcrypt, jsonwebtoken, express-validator, ../config/database
  • Afferent coupling:
    • config/database.js is used by 1 module (routes/auth.js) — low afferent coupling
  • Instability index:
    • Auth module shows moderate instability because it depends on several external libraries (typical for an auth module)
Recommendation
  • Keep dependency usage explicit and consider dependency injection for easier testing (pass a database client or userRepository into service constructors).

5. Cohesion analysis

  • config/database.js is cohesive: it focuses on database connection management.
  • routes/auth.js currently violates single responsibility: it performs validation, business logic, DB access, token creation, and error formatting in a single function.
  • Recommendation: increase cohesion by grouping related functions and moving unrelated concerns to separate modules (authService, userRepository, errorMapper).

Specific findings and remediation (prioritized)

High priority (7–8/10)
  1. Reduce cyclomatic complexity in the login handler by extracting validation, repository, password check, token creation, and error mapping into separate functions.
  2. Split the login handler into multiple single-responsibility functions so each is < 50 LOC and has a low cyclomatic complexity.
Medium priority (5–6/10) 3. Simplify nested conditionals by returning early on failure conditions (fail-fast) rather than deeply nesting success paths. 4. Move DB-specific error handling into an errorMapper utility that translates DB errors into stable HTTP responses. Low priority (1–4/10) 5. Consider dependency injection for the database and JWT signing to make unit testing easier. 6. Monitor file growth and split files when they exceed the team’s readability thresholds. Recommended error mapper (drop-in)
Usage pattern in a simplified route handler
Verification guidance
  • If a reported finding cannot be fully verified due to missing files or lines, add a note “Unable to verify” and list which file(s) and line ranges are required to confirm it (e.g., repositories/userRepository.js or the exact routes/auth.js content).
If you cannot verify a finding because the exact file or lines are not available, annotate the report as “Unable to verify” and list the specific files/line ranges needed (for example: routes/auth.js:17-96, repositories/userRepository.js). This ensures follow-up reviews can target the missing artifacts.

Implementation plan (phased)

Phase 1 — Immediate fixes (1–2 days)
  • Extract validation logic into helper functions or express-validator middleware.
  • Extract token generation function into a small utility.
  • Add an errorMapper utility for predictable DB-to-HTTP mapping.
Phase 2 — Service/repository separation (2–4 days)
  • Create services/authService.js with methods: loginUser, verifyPassword, createToken.
  • Create repositories/userRepository.js to encapsulate DB queries.
  • Update routes to be thin coordinators that call services.
Phase 3 — Tests and monitoring (2–3 days)
  • Add unit tests for authService and userRepository (use DI/mocks for DB).
  • Add a static analyzer check for cyclomatic/cognitive complexity as part of CI (optional).
  • Monitor function/file sizes and complexity regressions in CI.

Metrics summary

Top priorities
  1. Reduce cyclomatic complexity of login handler to <= 10.
  2. Break the ~80-line login function into smaller, testable functions.
  3. Extract DB error handling to an errorMapper to simplify error logic.
Positive notes
  • Good separation between server/bootstrap code and configuration (e.g., server.js, config/database.js).
  • Reasonable dependency choices for authentication (bcrypt, jsonwebtoken).
  • Small, focused modules across the codebase make incremental improvements low-risk.
You can find the prompts and example audit inputs used to generate reports at: https://github.com/JeremyMorgan/Claude-Code-Reviewing-Prompts
Further reading and references A future article could cover automated detection and remediation of code duplication and patterns for introducing shared utilities or libraries to consolidate repeated logic.

Watch Video