Strategic architecture, tactical design, and testable code principles (SOLID, Clean Architecture, Design Patterns, Testable Design)
97
97%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
The following NotificationService constructs notification senders with complex conditional logic inside the constructor. Refactor using the Factory pattern.
// src/NotificationService.ts
export class NotificationService {
private sender: { send(to: string, message: string): Promise<void> }
constructor(channel: string, config: Record<string, string>) {
if (channel === 'email') {
const smtpHost = config.smtpHost
const smtpPort = parseInt(config.smtpPort)
// ... complex SMTP setup
this.sender = {
send: async (to, message) => {
console.log(`SMTP to ${to} via ${smtpHost}:${smtpPort}: ${message}`)
}
}
} else if (channel === 'sms') {
const apiKey = config.twilioApiKey
const from = config.twilioFrom
this.sender = {
send: async (to, message) => {
console.log(`SMS from ${from} via Twilio apiKey=${apiKey}: ${to} - ${message}`)
}
}
} else if (channel === 'slack') {
const webhookUrl = config.slackWebhook
this.sender = {
send: async (to, message) => {
console.log(`Slack webhook ${webhookUrl}: @${to} ${message}`)
}
}
} else {
throw new Error(`Unknown channel: ${channel}`)
}
}
async notify(to: string, message: string): Promise<void> {
await this.sender.send(to, message)
}
}Produce:
INotificationSender.ts — the sender interface with send(to: string, message: string): Promise<void>.EmailSender.ts, SmsSender.ts, SlackSender.ts — one file per channel implementation.NotificationSenderFactory.ts — a factory class with a create(channel: string, config: Record<string, string>): INotificationSender method containing all the construction logic.NotificationService.ts — refactored to accept an INotificationSender via constructor (the factory is used externally to construct it).All TypeScript files must be valid.
clean-architecture
evals
references
design-patterns
solid-principles
testable-design