> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Design Pattern Implementation Review

> Review of design patterns in an Express.js login demo with JWT and PostgreSQL, recommending repositories, services, token factory, middleware, and refactors for maintainability, security, and testability.

This lesson performs common software design-pattern reviews you would do for either legacy or greenfield code. The goal is to verify the codebase is extensible, maintainable, and secure, and to recommend small, concrete fixes you can apply incrementally.

Below is the CLI interaction used to generate the analysis (cleaned for clarity). It shows the tool collecting a structured report into the `audits` folder.

```bash theme={null}
# Saved to audits/SOFTWARE_DESIGN_ARCHITECTURE_ANALYSIS.md
jeremy@MACSTUDIO Express-login-demo % claude

* Welcome to Claude Code!
/help for help, /status for your current setup
cwd: /Users/jeremy/Repos/Claude Code Course/Express-login-demo

What's new:
• Fixed issue causing "OAuth authentication is currently not supported"
• Status line input now includes `exceeds_200k_tokens`
• Fixed incorrect usage tracking in /cost
• Introduced `ANTHROPIC_DEFAULT_SONNET_MODEL` and `ANTHROPIC_DEFAULT_OPUS_MODEL` for controlling model aliases opusplan, opus, and sonnet.
• Bedrock: Updated default Sonnet model to Sonnet 4

> Try "how do I log an error?"

? for shortcuts
```

We used the tool to produce a structured findings report with precise code-level remediation. The report evaluates creational, structural, behavioral, and domain patterns and recommends concrete refactors for an Express.js login demo using JWT and PostgreSQL.

## Overview

This report analyzes design patterns in the Express Login Demo application, evaluates correctness and appropriateness, and identifies actionable improvements that increase maintainability, testability, and security.

Project highlights:

* Stack: Express.js, PostgreSQL (pg), bcrypt, jsonwebtoken, express-validator
* Authentication: JWT (access + refresh pattern)
* Files of note: `server.js`, `routes/auth.js`, `config/database.js`
* Database: PostgreSQL connection pool (singleton)

## Project Structure (summary)

* Simple Express REST application
* Auth routes currently contain SQL and token logic inline
* Database access uses `pg` Pool (connection pooling)

***

## 1. CREATIONAL PATTERNS

### 1.1 Singleton Pattern

Found: PostgreSQL connection pool\
Location: `config/database.js:3`

```javascript theme={null}
// config/database.js
const { Pool } = require('pg');

const pool = new Pool({
  host: process.env.DB_HOST,
  // ... other config
});

module.exports = pool;
```

Assessment:

* Correct: single Pool instance exported and reused across modules.
* Appropriate: DB pools should be application-scoped.
* Tip: Ensure connect/error listeners log useful diagnostics and exit gracefully when necessary.

Status: Working — no immediate changes required.

***

### 1.2 Factory Pattern

Status: Not present (recommended)

Rationale:

* Token creation is currently inline in controllers. A `TokenFactory` centralizes JWT creation, expiration policies, and secret usage, which simplifies secret rotation and testing.

Recommendation (drop-in):

```javascript theme={null}
// lib/TokenFactory.js
const jwt = require('jsonwebtoken');

class TokenFactory {
  static createAccessToken(user) {
    return jwt.sign(
      { userId: user.id, email: user.email, type: 'access' },
      process.env.JWT_SECRET,
      { expiresIn: '15m' }
    );
  }

  static createRefreshToken(user) {
    return jwt.sign(
      { userId: user.id, type: 'refresh' },
      process.env.JWT_REFRESH_SECRET,
      { expiresIn: '7d' }
    );
  }
}

module.exports = TokenFactory;
```

Importance: 6/10 — recommended for maintainability and secure rotation.

***

### 1.3 Builder Pattern

Status: Not present / Not necessary

Assessment:

* Validation chains from `express-validator` already provide a builder-like API.
* No complex object construction that warrants a Builder pattern in the current scope.

Importance: 2/10

***

## 2. STRUCTURAL PATTERNS

### 2.1 Facade Pattern

Found: Express Router\
Location: `routes/auth.js`

```javascript theme={null}
// routes/auth.js
const express = require('express');
const router = express.Router();

// router acts as a facade for auth-related HTTP endpoints
```

Assessment:

* Router is correctly used as a facade to group auth endpoints and hide implementation details.

Importance: 2/10 — no change needed.

***

### 2.2 Decorator / Middleware Pattern

Found: Express middleware chain and validation middleware

```javascript theme={null}
// server.js
app.use(express.json());

// routes/auth.js (validation middleware example)
router.post('/login', [
  body('email').isEmail().normalizeEmail(),
  body('password').isLength({ min: 8 })
], async (req, res) => {
  // handler
});
```

Assessment:

* Middleware separation (validation, parsing) is well applied.
* Missing: a reusable JWT authentication middleware applied to protected routes.

Remediation (add to `middleware/` and apply to endpoints):

```javascript theme={null}
// middleware/authenticateToken.js
const jwt = require('jsonwebtoken');

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) return res.sendStatus(401);

  jwt.verify(token, process.env.JWT_SECRET, (err, payload) => {
    if (err) return res.sendStatus(403);
    req.user = { id: payload.userId, email: payload.email };
    next();
  });
}

module.exports = authenticateToken;
```

Importance: 8/10 — high priority to protect endpoints.

***

### 2.3 Proxy Pattern (Query Caching)

Status: Not implemented (recommended)

Assessment:

* No caching layer for frequent read queries.
* A lightweight DB proxy with TTL-based in-memory caching reduces load for read-heavy endpoints.

Suggested minimal proxy:

```javascript theme={null}
// lib/DatabaseProxy.js
class DatabaseProxy {
  constructor(pool, cacheTTL = 5 * 60 * 1000) {
    this.pool = pool;
    this.cache = new Map();
    this.cacheTTL = cacheTTL;
  }

  async query(text, params = []) {
    const key = `${text}:${JSON.stringify(params)}`;
    const cached = this.cache.get(key);

    if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
      return cached.result;
    }

    const result = await this.pool.query(text, params);
    this.cache.set(key, { timestamp: Date.now(), result });
    return result;
  }
}

module.exports = DatabaseProxy;
```

Importance: 6/10 — valuable for performance if reads dominate.

***

## 3. BEHAVIORAL PATTERNS

### 3.1 Chain of Responsibility

Found: Express middleware chain

Assessment:

* Properly used — express middleware implements this naturally.
* Error-handling middleware should remain last in the chain.

Importance: 1/10 — working correctly.

***

### 3.2 Strategy Pattern (Authentication)

Status: Missing (recommended)

Assessment:

* Current implementation supports only local email/password auth.
* If you plan to add OAuth, SSO, or LDAP, a strategy-based design keeps route code clean and extensible.

Recommendation: Create a strategy interface plus concrete implementations (LocalAuthStrategy shown).

```javascript theme={null}
// lib/auth/strategies/AuthStrategy.js
class AuthStrategy {
  async authenticate(credentials) {
    throw new Error('Must implement authenticate method');
  }
}

module.exports = AuthStrategy;
```

```javascript theme={null}
// lib/auth/strategies/LocalAuthStrategy.js
const AuthStrategy = require('./AuthStrategy');

class LocalAuthStrategy extends AuthStrategy {
  constructor(userRepository) {
    super();
    this.userRepository = userRepository;
  }

  async authenticate({ email, password }) {
    const user = await this.userRepository.findByEmail(email);
    if (!user) return null;
    const match = await bcrypt.compare(password, user.password);
    if (!match) return null;
    return user;
  }
}

module.exports = LocalAuthStrategy;
```

```javascript theme={null}
// lib/auth/AuthenticationService.js
class AuthenticationService {
  constructor(strategies = {}) {
    this.strategies = strategies;
  }

  async authenticate(type, credentials) {
    const strategy = this.strategies[type];
    if (!strategy) throw new Error('Authentication strategy not supported');
    return strategy.authenticate(credentials);
  }
}

module.exports = AuthenticationService;
```

Importance: 7/10 — useful when supporting multiple auth methods.

***

### 3.3 Observer Pattern (Eventing)

Found: DB connection events (limited application eventing)

Assessment:

* App-level events (e.g., `user:login:success`) are not centralized.
* Introduce an event emitter to decouple side effects (audit logs, metrics, rate-limiting) from core logic.

Example:

```javascript theme={null}
// lib/events/authEvents.js
const EventEmitter = require('events');
class AuthEventEmitter extends EventEmitter {}
const authEvents = new AuthEventEmitter();

module.exports = authEvents;

// usage in routes
authEvents.emit('user:login:success', { userId: user.id, ip: req.ip });

// listener
authEvents.on('user:login:failed', ({ email, ip }) => {
  console.log(`Failed login attempt for ${email} from ${ip}`);
  // attach rate-limiting or alerting logic
});
```

Importance: 5/10 — good for observability and decoupling.

***

### 3.4 Command Pattern

Status: Not implemented / Not required for current scope

Assessment:

* Not necessary for synchronous HTTP request/response flows.
* Consider when adding background job queues or task orchestration.

Importance: 3/10

***

## 4. DOMAIN PATTERNS

### 4.1 Repository Pattern

Status: Missing — raw SQL in route handlers

Issue:

* Routes contain SQL and DB logic, violating separation of concerns.
* Tests and business logic become harder to maintain.

Remediation: Add a `UserRepository` and move DB queries out of routes.

```javascript theme={null}
// repositories/UserRepository.js
class UserRepository {
  constructor(db) {
    this.db = db; // db is DatabaseProxy or pool
  }

  async findByEmail(email) {
    const res = await this.db.query('SELECT id, email, name, password FROM users WHERE email = $1', [email]);
    return res.rows[0] || null;
  }

  async create(user) {
    const res = await this.db.query(
      'INSERT INTO users (email, name, password) VALUES ($1, $2, $3) RETURNING id, email, name',
      [user.email, user.name, user.password]
    );
    return res.rows[0];
  }
}

module.exports = UserRepository;
```

Importance: 9/10 — critical for maintainability and testability.

***

### 4.2 Service Layer Pattern

Status: Missing — business logic lives in routes

Issue:

* Authentication and token generation are in HTTP handlers.
* Moving core logic to a service layer isolates business rules and simplifies testing.

Remediation: Create an `AuthService` dependent on `UserRepository` and `TokenFactory`.

```javascript theme={null}
// services/AuthService.js
const TokenFactory = require('../lib/TokenFactory');

class AuthService {
  constructor(userRepository) {
    this.userRepository = userRepository;
  }

  async authenticateUser(email, password) {
    const user = await this.userRepository.findByEmail(email);
    if (!user) throw new Error('Invalid credentials');

    const passwordValid = await bcrypt.compare(password, user.password);
    if (!passwordValid) throw new Error('Invalid credentials');

    const accessToken = TokenFactory.createAccessToken(user);
    const refreshToken = TokenFactory.createRefreshToken(user);

    return { user, accessToken, refreshToken };
  }
}

module.exports = AuthService;
```

Importance: 9/10 — high-priority refactor.

***

### 4.3 DTO Pattern

Status: Partial / Informal

Issue:

* Responses build objects inline; there is no consistent public view.
* Introduce simple DTOs to standardize API responses and avoid leaking internal fields.

Example:

```javascript theme={null}
// dtos/UserDTO.js
class UserDTO {
  constructor(user) {
    this.id = user.id;
    this.email = user.email;
    this.name = user.name;
  }
}

module.exports = UserDTO;
```

Use in responses: `res.json({ token, user: new UserDTO(user) });`

Importance: 5/10 — useful for API contract consistency.

***

### 4.4 Domain Model Pattern

Status: Anemic domain (missing domain entities)

Issue:

* No domain entities with encapsulated behavior; business logic is scattered.

Recommendation:

* Introduce a minimal `User` domain object that owns behavior like password verification and public projection.

```javascript theme={null}
// domain/User.js
class User {
  constructor({ id, email, name, password }) {
    this.id = id;
    this.email = email;
    this.name = name;
    this.password = password; // hashed
  }

  static async create(email, name, plainPassword) {
    const hashedPassword = await bcrypt.hash(plainPassword, 10);
    return new User({ id: null, email, name, password: hashedPassword });
  }

  async verifyPassword(plainPassword) {
    return bcrypt.compare(plainPassword, this.password);
  }

  toPublicObject() {
    return {
      id: this.id,
      email: this.email,
      name: this.name
    };
  }
}

module.exports = User;
```

Importance: 7/10 — improves encapsulation and validation.

***

## Summary of Recommendations

Critical (9/10)

* Extract a `UserRepository` to remove raw SQL from routes.
* Implement an `AuthService` to host authentication logic and token orchestration.

High Priority (7–8/10)

* Add JWT authentication middleware and protect endpoints.
* Consider a Strategy pattern for multiple authentication methods.
* Introduce a centralized `TokenFactory` for token creation and rotation.

Medium Priority (5–6/10)

* Add application-level events (Observer) for audit and rate-limiting hooks.
* Introduce DTOs for consistent API responses.
* Consider a small query-caching proxy (Proxy pattern) for read-heavy endpoints.

Low Priority (1–4/10)

* Enrich domain models and add domain behaviors.
* Builder/Command patterns are not necessary now but useful later for complexity.

Recommended, incremental refactor order:

1. Extract `UserRepository` and update routes to use it.
2. Create `AuthService` and move business logic from routes into it.
3. Add JWT authentication middleware and protect endpoints.
4. Implement `TokenFactory`.
5. Add app-level events and optional caching proxy.

| Area | Problem | Suggested Pattern | Priority |
| - | - | - | - |
| Routes | Raw SQL and token code in handlers | Repository + Service Layer | Critical |
| Auth | Single strategy, inline tokens | Strategy + TokenFactory | High |
| Security | Missing JWT middleware on protected endpoints | Middleware (Decorator) | High |
| Performance | No caching for frequent reads | Proxy (DB caching) | Medium |
| Observability | No centralized events | Observer/EventEmitter | Medium |

<Callout icon="lightbulb" color="#1CB2FE">
  Prioritize extracting repository and service layers first — these two changes immediately improve testability, separation of concerns, and make adding additional patterns (strategy, factory, eventing) straightforward.
</Callout>

This analysis converts findings into concrete, small, testable code changes rather than broad architectural prose. With repository and service abstractions in place you can iteratively add other patterns (strategy, proxy, DTOs, domain objects) as your application requirements grow.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/Xs8Ruv7b0QCZf7iM/images/Claude-Code-for-Beginners/Code-Review-with-Claude-Code/Design-Pattern-Implementation-Review/claude-code-reviewing-prompts-github-screenshot.jpg?fit=max&auto=format&n=Xs8Ruv7b0QCZf7iM&q=85&s=1018b3f96ca793cd719283b6899eff20" alt="A screenshot of a GitHub repository page in dark mode showing a project named &#x22;Claude‑Code‑Reviewing‑Prompts&#x22; with a list of markdown files (security and review topics) in the main pane and repository details in the right sidebar. The window sits over a code editor/IDE visible in the background." width="1920" height="1080" data-path="images/Claude-Code-for-Beginners/Code-Review-with-Claude-Code/Design-Pattern-Implementation-Review/claude-code-reviewing-prompts-github-screenshot.jpg" />
</Frame>

This set of recommendations maps directly to the concrete changes you'll make when hardening this Express login demo into a maintainable service.

## Links and References

* [Express.js documentation](https://expressjs.com/)
* [PostgreSQL node client (pg)](https://node-postgres.com/)
* [jsonwebtoken (JWT for Node.js)](https://github.com/auth0/node-jsonwebtoken)
* [express-validator](https://express-validator.github.io/docs/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/claude-code-for-beginners/module/dd033355-c556-4619-993c-ac717c0f5741/lesson/3147e16f-8b9f-456d-b856-e763dc2d543d" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.