Code Quality Standards
Maintain high code quality standards in AI-assisted development. Learn to establish quality gates, automated checks, and best practices that ensure maintainable, secure, and performant code.
Quality Framework
GISE Quality Pillars
Quality Metrics
Code Quality Targets:
- Test Coverage: ≥90% for unit tests
- Maintainability Index: ≥80/100
- Cyclomatic Complexity: ≤10 per function
- Technical Debt Ratio: ≤5%
- Security Vulnerabilities: 0 high/critical
Automated Quality Gates
ESLint Configuration
// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
project: './tsconfig.json'
},
plugins: [
'@typescript-eslint',
'security',
'jest',
'import'
],
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'@typescript-eslint/recommended-requiring-type-checking',
'plugin:security/recommended',
'plugin:jest/recommended',
'plugin:import/typescript',
'prettier'
],
rules: {
// TypeScript specific
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/strict-boolean-expressions': 'error',
// Code quality
'complexity': ['error', 10],
'max-lines': ['error', 300],
'max-lines-per-function': ['error', 50],
'no-console': 'warn',
'no-debugger': 'error',
'prefer-const': 'error',
'no-var': 'error',
'eqeqeq': 'error',
'curly': 'error',
// Import organization
'import/order': ['error', {
'groups': [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index'
],
'newlines-between': 'always'
}],
// Security
'security/detect-object-injection': 'error',
'security/detect-non-literal-regexp': 'error',
'security/detect-possible-timing-attacks': 'error'
},
env: {
node: true,
jest: true,
es2022: true
}
};
TypeScript Configuration
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "tests"]
}
Prettier Configuration
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"arrowParens": "avoid",
"endOfLine": "lf"
}
Code Standards
Naming Conventions
// Good naming examples
class UserService {
private readonly userRepository: UserRepository;
private readonly logger: Logger;
async createUser(userData: CreateUserDto): Promise<User> {
const hashedPassword = await this.hashPassword(userData.password);
const newUser = await this.userRepository.create({
...userData,
password: hashedPassword
});
this.logger.info('User created successfully', { userId: newUser.id });
return newUser;
}
private async hashPassword(plainPassword: string): Promise<string> {
return bcrypt.hash(plainPassword, SALT_ROUNDS);
}
}
// Constants
const MAX_RETRY_ATTEMPTS = 3;
const DEFAULT_TIMEOUT_MS = 5000;
const API_BASE_URL = process.env.API_BASE_URL!;
// Enums
enum UserStatus {
ACTIVE = 'active',
INACTIVE = 'inactive',
SUSPENDED = 'suspended'
}
// Interfaces
interface CreateUserRequest {
readonly email: string;
readonly name: string;
readonly password: string;
}
Function Design
// Single Responsibility Principle
class EmailService {
constructor(
private readonly emailProvider: EmailProvider,
private readonly templateEngine: TemplateEngine,
private readonly logger: Logger
) {}
async sendWelcomeEmail(user: User): Promise<void> {
try {
const template = await this.templateEngine.render('welcome', {
userName: user.name,
loginUrl: this.buildLoginUrl()
});
await this.emailProvider.send({
to: user.email,
subject: 'Welcome to Our Platform',
html: template
});
this.logger.info('Welcome email sent', { userId: user.id });
} catch (error) {
this.logger.error('Failed to send welcome email', {
userId: user.id,
error: error.message
});
throw new EmailSendError('Failed to send welcome email', error);
}
}
private buildLoginUrl(): string {
return `${process.env.FRONTEND_URL}/login`;
}
}
Error Handling
// Custom error hierarchy
abstract class AppError extends Error {
abstract readonly statusCode: number;
abstract readonly isOperational: boolean;
constructor(message: string, public readonly context?: Record<string, any>) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
class ValidationError extends AppError {
readonly statusCode = 400;
readonly isOperational = true;
constructor(message: string, public readonly field?: string) {
super(message, { field });
}
}
class NotFoundError extends AppError {
readonly statusCode = 404;
readonly isOperational = true;
}
class DatabaseError extends AppError {
readonly statusCode = 500;
readonly isOperational = false;
}
// Error handling middleware
export const errorHandler = (
error: Error,
req: Request,
res: Response,
next: NextFunction
): void => {
const logger = Container.get<Logger>('Logger');
logger.error('Request failed', {
error: error.message,
stack: error.stack,
path: req.path,
method: req.method,
userId: req.user?.id
});
if (error instanceof AppError) {
res.status(error.statusCode).json({
error: error.message,
...(error.context && { context: error.context })
});
return;
}
// Unhandled errors
res.status(500).json({
error: 'Internal server error'
});
};
Security Standards
Input Validation
import Joi from 'joi';
// Schema definitions
const createUserSchema = Joi.object({
email: Joi.string()
.email({ minDomainSegments: 2 })
.required()
.max(255),
name: Joi.string()
.trim()
.min(2)
.max(100)
.required()
.pattern(/^[a-zA-Z\s]+$/, 'letters and spaces only'),
password: Joi.string()
.min(8)
.max(128)
.required()
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/,
'password requirements')
});
// Validation middleware
export const validateRequest = (schema: Joi.Schema) => {
return (req: Request, res: Response, next: NextFunction): void => {
const { error, value } = schema.validate(req.body, {
abortEarly: false,
stripUnknown: true
});
if (error) {
const validationErrors = error.details.map(detail => ({
field: detail.path.join('.'),
message: detail.message
}));
res.status(400).json({
error: 'Validation failed',
details: validationErrors
});
return;
}
req.body = value;
next();
};
};
SQL Injection Prevention
// Repository pattern with prepared statements
export class UserRepository {
constructor(private readonly db: Pool) {}
async findByEmail(email: string): Promise<User | null> {
const query = 'SELECT id, email, name, created_at FROM users WHERE email = $1';
const result = await this.db.query(query, [email]);
return result.rows[0] || null;
}
async create(userData: CreateUserDto): Promise<User> {
const query = `
INSERT INTO users (email, name, password_hash, created_at, updated_at)
VALUES ($1, $2, $3, NOW(), NOW())
RETURNING id, email, name, created_at
`;
const values = [userData.email, userData.name, userData.password];
const result = await this.db.query(query, values);
return result.rows[0];
}
async update(id: string, updates: Partial<UpdateUserDto>): Promise<User> {
const setClause = Object.keys(updates)
.map((key, index) => `${key} = $${index + 2}`)
.join(', ');
const query = `
UPDATE users
SET ${setClause}, updated_at = NOW()
WHERE id = $1
RETURNING id, email, name, created_at, updated_at
`;
const values = [id, ...Object.values(updates)];
const result = await this.db.query(query, values);
return result.rows[0];
}
}
Performance Standards
Database Optimization
// Efficient query patterns
export class ProjectRepository {
async findProjectsWithUsers(userId: string, limit = 20, offset = 0): Promise<Project[]> {
// Use JOIN to avoid N+1 queries
const query = `
SELECT
p.id, p.name, p.description, p.created_at,
u.id as owner_id, u.name as owner_name, u.email as owner_email
FROM projects p
JOIN users u ON p.owner_id = u.id
WHERE p.owner_id = $1
ORDER BY p.created_at DESC
LIMIT $2 OFFSET $3
`;
const result = await this.db.query(query, [userId, limit, offset]);
return result.rows.map(this.mapRowToProject);
}
// Batch operations for better performance
async createMany(projects: CreateProjectDto[]): Promise<Project[]> {
const query = `
INSERT INTO projects (name, description, owner_id, created_at, updated_at)
VALUES ${projects.map((_, i) =>
`($${i * 3 + 1}, $${i * 3 + 2}, $${i * 3 + 3}, NOW(), NOW())`
).join(', ')}
RETURNING *
`;
const values = projects.flatMap(p => [p.name, p.description, p.ownerId]);
const result = await this.db.query(query, values);
return result.rows;
}
}
Caching Strategy
import { createHash } from 'crypto';
export class CachedUserService {
constructor(
private readonly userRepository: UserRepository,
private readonly cache: Redis,
private readonly logger: Logger
) {}
async getUserById(id: string): Promise<User | null> {
const cacheKey = `user:${id}`;
try {
// Try cache first
const cached = await this.cache.get(cacheKey);
if (cached) {
this.logger.debug('User found in cache', { userId: id });
return JSON.parse(cached);
}
// Fallback to database
const user = await this.userRepository.findById(id);
if (user) {
// Cache for 1 hour
await this.cache.setex(cacheKey, 3600, JSON.stringify(user));
this.logger.debug('User cached', { userId: id });
}
return user;
} catch (error) {
this.logger.error('Cache error, falling back to database', {
userId: id,
error: error.message
});
return this.userRepository.findById(id);
}
}
async invalidateUserCache(id: string): Promise<void> {
const cacheKey = `user:${id}`;
await this.cache.del(cacheKey);
this.logger.debug('User cache invalidated', { userId: id });
}
}
Documentation Standards
JSDoc Comments
/**
* Service for managing user accounts and authentication
*
* @example
* ```typescript
* const userService = new UserService(userRepository, logger);
* const user = await userService.createUser({
* email: 'john@example.com',
* name: 'John Doe',
* password: 'securepassword'
* });
* ```
*/
export class UserService {
/**
* Creates a new user account with hashed password
*
* @param userData - User registration data
* @returns Promise resolving to created user (without password)
* @throws {ValidationError} When user data is invalid
* @throws {ConflictError} When email already exists
* @throws {DatabaseError} When database operation fails
*
* @example
* ```typescript
* const user = await userService.createUser({
* email: 'john@example.com',
* name: 'John Doe',
* password: 'securepassword123'
* });
* console.log(user.id); // Created user ID
* ```
*/
async createUser(userData: CreateUserDto): Promise<User> {
// Implementation...
}
/**
* Authenticates user credentials and returns JWT token
*
* @param email - User email address
* @param password - Plain text password
* @returns Promise resolving to authentication result
* @throws {UnauthorizedError} When credentials are invalid
*
* @internal This method handles sensitive authentication logic
*/
async authenticateUser(email: string, password: string): Promise<AuthResult> {
// Implementation...
}
}
Quality Automation
Pre-commit Hooks
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write",
"jest --findRelatedTests --passWithNoTests"
],
"*.{json,md,yml,yaml}": [
"prettier --write"
]
}
}
CI/CD Quality Pipeline
name: Quality Gates
on: [push, pull_request]
jobs:
quality-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Type checking
run: npm run type-check
- name: Linting
run: npm run lint
- name: Format checking
run: npm run format:check
- name: Security audit
run: npm audit --audit-level high
- name: Run tests with coverage
run: npm run test:coverage
- name: Coverage threshold check
run: |
COVERAGE=$(npm run test:coverage:json | jq '.total.lines.pct')
if (( $(echo "$COVERAGE < 90" | bc -l) )); then
echo "Coverage $COVERAGE% is below 90% threshold"
exit 1
fi
- name: Build check
run: npm run build
AI-Assisted Quality
Code Review Prompts
Review the following TypeScript code for quality issues:
[PASTE CODE]
Check for:
1. SOLID principles adherence
2. Error handling completeness
3. Type safety and null checks
4. Performance implications
5. Security vulnerabilities
6. Code clarity and maintainability
7. Test coverage gaps
Provide:
- Specific issues found
- Suggested improvements
- Risk assessment (low/medium/high)
- Refactoring recommendations
Quality Metrics Monitoring
// Custom quality metrics
export class QualityMetrics {
static calculateComplexity(sourceCode: string): number {
// Simplified complexity calculation
const cyclomaticKeywords = [
'if', 'else', 'while', 'for', 'case', 'catch', 'throw', '&&', '||', '?'
];
let complexity = 1; // Base complexity
cyclomaticKeywords.forEach(keyword => {
const regex = new RegExp(`\\b${keyword}\\b`, 'g');
const matches = sourceCode.match(regex);
complexity += matches ? matches.length : 0;
});
return complexity;
}
static calculateMaintainabilityIndex(
linesOfCode: number,
complexity: number,
halsteadVolume: number
): number {
// Microsoft's Maintainability Index formula (simplified)
const mi = Math.max(0, 171 - 5.2 * Math.log(halsteadVolume)
- 0.23 * complexity - 16.2 * Math.log(linesOfCode));
return Math.round(mi);
}
}
Related Topics
Next: Real-time Collaboration | Container Development
Quality is not an accident; it is always the result of intelligent effort.