A focused code-quality audit of an Express login demo assessing complexity, coupling, cohesion, and LOC, with concrete refactor recommendations to improve readability, testability, and maintainability.
This article walks through a focused code-quality audit for an Express login demo. The audit inspects code complexity, maintainability, and coupling, and it provides concrete refactor recommendations to improve readability and testability.You can fetch the full set of prompts used for these audits from the repository:
> Analyze code complexity across the codebase: Look for complex functions/methods. Also look at functions/methods and calculate/evaluate: 1. CYCLOMATIC COMPLEXITY - Functions with complexity > 10 - Nested if/else depth - Switch statement complexity - Recommend refactoring for high complexity 2. COGNITIVE COMPLEXITY - How hard is the code to understand? - Nested loops and conditions - Recursive calls - Mixed levels of abstraction 3. LINES OF CODE METRICS - Functions over 50 lines - Files over 300 lines - Classes over 500 lines - Identify candidates for splitting 4. COUPLING METRICS - Afferent coupling (dependencies on this module) - Efferent coupling (dependencies of this module) - Instability index - Identify tightly coupled modules 5. COHESION ANALYSIS - Are related functions grouped?Provide specific refactoring recommendations for complex areas.
The codebase is generally small and well-structured at a module level.
The principal hotspot is the authentication route handler (routes/auth.js): the login handler mixes validation, DB access, credential verification, token creation, and error mapping in a single long function.
Recommended immediate actions: split responsibilities (validation, service layer, token utility, error mapping) to reduce cyclomatic and cognitive complexity and to enable easier unit testing.
The authentication module depends on several external libraries (validation, DB client, JWT).
Afferent/efferent coupling is moderate — expected for authentication—but introducing dependency injection for the DB client and token utility will improve testability and reduce tight coupling.
Overall project modules are cohesive (server, config, routes), but the login handler violates single-responsibility by handling multiple concerns within one function.
Recommendation: reorganize into smaller cohesive modules (validation, authService, tokenUtil, errorMapper).
Extract validation into a helper function (throws structured error on validation failure).
Move authentication logic into an authService that encapsulates user lookup and password verification.
Create a tokenUtil for JWT generation.
Consolidate DB/infrastructure error mapping into a small errorMapper utility.
Example helper implementations (illustrative — keep for guidance):
Reduce cyclomatic complexity of login handler by extracting branching and error handling
Lowers maintenance burden and simplifies testing
High (7–8/10)
Split the login handler into multiple single-responsibility functions or an authService module
Improves readability and unit-testability
Medium (5–6/10)
Flatten nested conditionals and separate DB/business logic
Reduces cognitive complexity
Medium (5–6/10)
Introduce a centralized errorMapper for DB/infrastructure errors
Centralized mapping simplifies handler logic
Low (1–4/10)
Apply dependency injection for DB and token utilities
Facilitates mocking in unit tests
Low (1–4/10)
Monitor LOC growth and add tests
Prevents regressions and complexity creep
Prioritize splitting the login handler and creating the authService. These actions yield the highest immediate benefit for maintainability and test coverage.
The codebase has a solid module-level structure, but the authentication route handler concentrates unnecessary complexity.
Breaking the handler into smaller functions/services (validation, service layer, token util, error mapper) will reduce cyclomatic and cognitive complexity and make the code easier to test and maintain.
After refactors, re-run complexity analysis and add unit tests to validate improvements.