sdd-mcp-server 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,639 @@
1
+ # Core Coding Principles and Patterns
2
+
3
+ ## Overview
4
+
5
+ This document defines the fundamental software engineering principles that MUST be followed in all code development. These principles ensure code quality, maintainability, scalability, and team collaboration.
6
+
7
+ **Golden Rule**: Always ask "Does this code follow SOLID, DRY, KISS, YAGNI, Separation of Concerns, and Modularity?" before committing.
8
+
9
+ ---
10
+
11
+ ## SOLID Principles (Object-Oriented Design)
12
+
13
+ ### S - Single Responsibility Principle (SRP)
14
+
15
+ **Definition**: A class/module should have one, and only one, reason to change. Each component should do one thing well.
16
+
17
+ **✅ Good Example**:
18
+ ```typescript
19
+ // Good: Separate responsibilities
20
+ class UserRepository {
21
+ save(user: User): Promise<void> { /* DB logic */ }
22
+ findById(id: string): Promise<User> { /* DB logic */ }
23
+ }
24
+
25
+ class UserValidator {
26
+ validate(user: User): ValidationResult { /* Validation logic */ }
27
+ }
28
+
29
+ class EmailService {
30
+ sendWelcomeEmail(user: User): Promise<void> { /* Email logic */ }
31
+ }
32
+ ```
33
+
34
+ **❌ Bad Example**:
35
+ ```typescript
36
+ // Bad: Multiple responsibilities in one class
37
+ class UserManager {
38
+ save(user: User) { /* DB logic */ }
39
+ validate(user: User) { /* Validation */ }
40
+ sendEmail(user: User) { /* Email */ }
41
+ generateReport(user: User) { /* Reporting */ }
42
+ }
43
+ ```
44
+
45
+ **Application**:
46
+ - Functions should do ONE thing
47
+ - Classes should have ONE reason to change
48
+ - Modules should have ONE clear purpose
49
+
50
+ ---
51
+
52
+ ### O - Open/Closed Principle (OCP)
53
+
54
+ **Definition**: Software entities should be open for extension, but closed for modification.
55
+
56
+ **✅ Good Example**:
57
+ ```typescript
58
+ // Good: Use interfaces/abstractions for extension
59
+ interface PaymentProcessor {
60
+ process(amount: number): Promise<void>;
61
+ }
62
+
63
+ class CreditCardProcessor implements PaymentProcessor {
64
+ process(amount: number) { /* Credit card logic */ }
65
+ }
66
+
67
+ class PayPalProcessor implements PaymentProcessor {
68
+ process(amount: number) { /* PayPal logic */ }
69
+ }
70
+
71
+ // Adding new payment method doesn't modify existing code
72
+ class CryptoProcessor implements PaymentProcessor {
73
+ process(amount: number) { /* Crypto logic */ }
74
+ }
75
+ ```
76
+
77
+ **❌ Bad Example**:
78
+ ```typescript
79
+ // Bad: Modifying existing code to add features
80
+ class PaymentProcessor {
81
+ process(amount: number, type: 'card' | 'paypal' | 'crypto') {
82
+ if (type === 'card') { /* Card logic */ }
83
+ else if (type === 'paypal') { /* PayPal logic */ }
84
+ else if (type === 'crypto') { /* Crypto logic */ } // Modified existing code
85
+ }
86
+ }
87
+ ```
88
+
89
+ **Application**:
90
+ - Use interfaces/abstract classes
91
+ - Favor composition over inheritance
92
+ - Use dependency injection
93
+
94
+ ---
95
+
96
+ ### L - Liskov Substitution Principle (LSP)
97
+
98
+ **Definition**: Derived classes must be substitutable for their base classes without altering correctness.
99
+
100
+ **✅ Good Example**:
101
+ ```typescript
102
+ // Good: Subclass maintains expected behavior
103
+ class Rectangle {
104
+ constructor(protected width: number, protected height: number) {}
105
+
106
+ getArea(): number {
107
+ return this.width * this.height;
108
+ }
109
+ }
110
+
111
+ class Square extends Rectangle {
112
+ constructor(size: number) {
113
+ super(size, size);
114
+ }
115
+
116
+ getArea(): number {
117
+ return super.getArea(); // Maintains expected behavior
118
+ }
119
+ }
120
+ ```
121
+
122
+ **❌ Bad Example**:
123
+ ```typescript
124
+ // Bad: Subclass violates parent contract
125
+ class Rectangle {
126
+ setWidth(w: number) { this.width = w; }
127
+ setHeight(h: number) { this.height = h; }
128
+ }
129
+
130
+ class Square extends Rectangle {
131
+ setWidth(w: number) {
132
+ this.width = w;
133
+ this.height = w; // Violates rectangle behavior!
134
+ }
135
+ }
136
+ ```
137
+
138
+ **Application**:
139
+ - Subclasses should honor parent contracts
140
+ - Don't surprise callers with unexpected behavior
141
+ - Use composition when inheritance doesn't fit
142
+
143
+ ---
144
+
145
+ ### I - Interface Segregation Principle (ISP)
146
+
147
+ **Definition**: No client should be forced to depend on methods it doesn't use.
148
+
149
+ **✅ Good Example**:
150
+ ```typescript
151
+ // Good: Small, focused interfaces
152
+ interface Readable {
153
+ read(): string;
154
+ }
155
+
156
+ interface Writable {
157
+ write(data: string): void;
158
+ }
159
+
160
+ class File implements Readable, Writable {
161
+ read() { return "data"; }
162
+ write(data: string) { /* write */ }
163
+ }
164
+
165
+ class ReadOnlyFile implements Readable {
166
+ read() { return "data"; }
167
+ // Not forced to implement write()
168
+ }
169
+ ```
170
+
171
+ **❌ Bad Example**:
172
+ ```typescript
173
+ // Bad: Bloated interface
174
+ interface FileOperations {
175
+ read(): string;
176
+ write(data: string): void;
177
+ delete(): void;
178
+ compress(): void;
179
+ encrypt(): void;
180
+ }
181
+
182
+ class ReadOnlyFile implements FileOperations {
183
+ read() { return "data"; }
184
+ write() { throw new Error("Not supported"); } // Forced to implement!
185
+ delete() { throw new Error("Not supported"); }
186
+ compress() { throw new Error("Not supported"); }
187
+ encrypt() { throw new Error("Not supported"); }
188
+ }
189
+ ```
190
+
191
+ **Application**:
192
+ - Keep interfaces small and focused
193
+ - Split large interfaces into smaller ones
194
+ - Use role interfaces
195
+
196
+ ---
197
+
198
+ ### D - Dependency Inversion Principle (DIP)
199
+
200
+ **Definition**: High-level modules should not depend on low-level modules. Both should depend on abstractions.
201
+
202
+ **✅ Good Example**:
203
+ ```typescript
204
+ // Good: Depend on abstractions
205
+ interface Logger {
206
+ log(message: string): void;
207
+ }
208
+
209
+ class UserService {
210
+ constructor(private logger: Logger) {} // Depends on abstraction
211
+
212
+ createUser(user: User) {
213
+ this.logger.log(`Creating user: ${user.name}`);
214
+ // ...
215
+ }
216
+ }
217
+
218
+ // Can inject any logger implementation
219
+ class ConsoleLogger implements Logger {
220
+ log(message: string) { console.log(message); }
221
+ }
222
+
223
+ class FileLogger implements Logger {
224
+ log(message: string) { /* write to file */ }
225
+ }
226
+ ```
227
+
228
+ **❌ Bad Example**:
229
+ ```typescript
230
+ // Bad: Direct dependency on concrete class
231
+ class UserService {
232
+ private logger = new ConsoleLogger(); // Tightly coupled!
233
+
234
+ createUser(user: User) {
235
+ this.logger.log(`Creating user: ${user.name}`);
236
+ }
237
+ }
238
+ ```
239
+
240
+ **Application**:
241
+ - Use dependency injection
242
+ - Program to interfaces, not implementations
243
+ - Invert control flow
244
+
245
+ ---
246
+
247
+ ## DRY (Don't Repeat Yourself)
248
+
249
+ **Definition**: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
250
+
251
+ **✅ Good Example**:
252
+ ```typescript
253
+ // Good: Extract common logic
254
+ function calculateDiscount(price: number, discountPercent: number): number {
255
+ return price * (1 - discountPercent / 100);
256
+ }
257
+
258
+ const regularPrice = calculateDiscount(100, 10);
259
+ const premiumPrice = calculateDiscount(200, 15);
260
+ const vipPrice = calculateDiscount(300, 20);
261
+ ```
262
+
263
+ **❌ Bad Example**:
264
+ ```typescript
265
+ // Bad: Repeated logic
266
+ const regularPrice = 100 * (1 - 10 / 100);
267
+ const premiumPrice = 200 * (1 - 15 / 100);
268
+ const vipPrice = 300 * (1 - 20 / 100);
269
+ ```
270
+
271
+ **When to Break DRY**:
272
+ - **Accidental Duplication**: Similar code, different concerns
273
+ - **Premature Abstraction**: Wait until you have 3+ instances
274
+ - **Different Change Reasons**: Code that looks similar but changes for different business reasons
275
+
276
+ **Application**:
277
+ - Extract common functions/classes
278
+ - Use inheritance/composition for shared behavior
279
+ - Apply at data level (single source of truth)
280
+
281
+ ---
282
+
283
+ ## KISS (Keep It Simple, Stupid)
284
+
285
+ **Definition**: Simplicity should be a key goal in design. Avoid unnecessary complexity.
286
+
287
+ **✅ Good Example**:
288
+ ```typescript
289
+ // Good: Simple and clear
290
+ function isEven(num: number): boolean {
291
+ return num % 2 === 0;
292
+ }
293
+ ```
294
+
295
+ **❌ Bad Example**:
296
+ ```typescript
297
+ // Bad: Overly complex
298
+ function isEven(num: number): boolean {
299
+ return ((num / 2) === Math.floor(num / 2)) &&
300
+ (parseInt(num.toString()) % 2 === 0) &&
301
+ ((num & 1) === 0);
302
+ }
303
+ ```
304
+
305
+ **Guidelines**:
306
+ - Write code that's easy to understand
307
+ - Avoid clever tricks that sacrifice readability
308
+ - Break complex functions into smaller, simple ones
309
+ - Use clear naming over comments
310
+
311
+ **Application**:
312
+ - Prefer straightforward solutions
313
+ - Avoid premature optimization
314
+ - Refactor complex code into simple pieces
315
+
316
+ ---
317
+
318
+ ## YAGNI (You Aren't Gonna Need It)
319
+
320
+ **Definition**: Don't implement functionality until it's actually needed. Avoid speculative features.
321
+
322
+ **✅ Good Example**:
323
+ ```typescript
324
+ // Good: Implement only what's needed now
325
+ class User {
326
+ constructor(
327
+ public id: string,
328
+ public email: string,
329
+ public name: string
330
+ ) {}
331
+ }
332
+ ```
333
+
334
+ **❌ Bad Example**:
335
+ ```typescript
336
+ // Bad: Anticipating future needs
337
+ class User {
338
+ constructor(
339
+ public id: string,
340
+ public email: string,
341
+ public name: string,
342
+ public secondaryEmail?: string, // Not needed yet
343
+ public phoneNumbers?: string[], // Not needed yet
344
+ public socialProfiles?: object[], // Not needed yet
345
+ public preferences?: UserPrefs, // Not needed yet
346
+ public metadata?: Record<string, any> // Not needed yet
347
+ ) {}
348
+ }
349
+ ```
350
+
351
+ **Guidelines**:
352
+ - Implement features only when required
353
+ - Don't add "might need" functionality
354
+ - Refactor when new requirements come
355
+ - Focus on current user stories
356
+
357
+ **Application**:
358
+ - Stick to requirements
359
+ - Avoid gold-plating
360
+ - Iterate based on real needs
361
+
362
+ ---
363
+
364
+ ## Separation of Concerns (SoC)
365
+
366
+ **Definition**: Separate a system into distinct sections, each addressing a separate concern.
367
+
368
+ **✅ Good Example**:
369
+ ```typescript
370
+ // Good: Layered architecture
371
+ // Presentation Layer
372
+ class UserController {
373
+ createUser(req, res) {
374
+ const user = this.userService.create(req.body);
375
+ res.json(user);
376
+ }
377
+ }
378
+
379
+ // Business Logic Layer
380
+ class UserService {
381
+ create(data: UserData): User {
382
+ this.validate(data);
383
+ return this.repository.save(data);
384
+ }
385
+ }
386
+
387
+ // Data Access Layer
388
+ class UserRepository {
389
+ save(data: UserData): User {
390
+ return db.users.insert(data);
391
+ }
392
+ }
393
+ ```
394
+
395
+ **❌ Bad Example**:
396
+ ```typescript
397
+ // Bad: Mixed concerns
398
+ class UserController {
399
+ createUser(req, res) {
400
+ // Validation (business logic)
401
+ if (!req.body.email) throw new Error('Email required');
402
+
403
+ // Database access (data layer)
404
+ const user = db.users.insert(req.body);
405
+
406
+ // Email sending (external service)
407
+ emailService.send(user.email, 'Welcome!');
408
+
409
+ // Response (presentation)
410
+ res.json(user);
411
+ }
412
+ }
413
+ ```
414
+
415
+ **Common Separations**:
416
+ - **Presentation** (UI, API) ↔ **Business Logic** ↔ **Data Access**
417
+ - **Domain Model** ↔ **Infrastructure**
418
+ - **Configuration** ↔ **Implementation**
419
+
420
+ **Application**:
421
+ - Use layered architecture
422
+ - Keep business logic independent of frameworks
423
+ - Separate I/O from computation
424
+
425
+ ---
426
+
427
+ ## Modularity
428
+
429
+ **Definition**: Design systems as a collection of independent, interchangeable modules with well-defined interfaces.
430
+
431
+ **Principles**:
432
+ - **High Cohesion**: Elements within a module are strongly related
433
+ - **Low Coupling**: Modules have minimal dependencies on each other
434
+ - **Encapsulation**: Hide internal details, expose only necessary interfaces
435
+
436
+ **✅ Good Example**:
437
+ ```typescript
438
+ // Good: Modular design
439
+ // auth/index.ts (Authentication Module)
440
+ export interface AuthService {
441
+ login(email: string, password: string): Promise<Token>;
442
+ logout(token: string): Promise<void>;
443
+ }
444
+
445
+ export class JWTAuthService implements AuthService {
446
+ login(email, password) { /* JWT logic */ }
447
+ logout(token) { /* JWT logout */ }
448
+ }
449
+
450
+ // payment/index.ts (Payment Module)
451
+ export interface PaymentService {
452
+ charge(amount: number): Promise<Receipt>;
453
+ }
454
+
455
+ export class StripePaymentService implements PaymentService {
456
+ charge(amount) { /* Stripe logic */ }
457
+ }
458
+
459
+ // Each module is independent, replaceable, testable
460
+ ```
461
+
462
+ **❌ Bad Example**:
463
+ ```typescript
464
+ // Bad: Tightly coupled, non-modular
465
+ class Application {
466
+ doEverything() {
467
+ // Auth logic mixed in
468
+ const user = db.users.find(email);
469
+ if (bcrypt.compare(password, user.hash)) {
470
+ // Payment logic mixed in
471
+ const charge = stripe.charges.create({amount: 100});
472
+ // Email logic mixed in
473
+ sendgrid.send({to: user.email, body: 'Thanks!'});
474
+ // Logging mixed in
475
+ winston.log('Charged user');
476
+ }
477
+ }
478
+ }
479
+ ```
480
+
481
+ **Module Design Guidelines**:
482
+ - One module = one responsibility
483
+ - Minimal cross-module dependencies
484
+ - Clear public interfaces
485
+ - Hide implementation details
486
+
487
+ **Application**:
488
+ - Organize code by feature/domain, not by type
489
+ - Use dependency injection for inter-module communication
490
+ - Create facade interfaces for complex modules
491
+
492
+ ---
493
+
494
+ ## Integration of Principles
495
+
496
+ ### How Principles Work Together
497
+
498
+ **Example: User Registration Feature**
499
+
500
+ ```typescript
501
+ // SOLID + SoC + Modularity
502
+ interface UserRepository { // DIP: Depend on abstraction
503
+ save(user: User): Promise<User>; // ISP: Focused interface
504
+ }
505
+
506
+ interface EmailService { // ISP: Separate interface
507
+ send(to: string, subject: string, body: string): Promise<void>;
508
+ }
509
+
510
+ class UserRegistrationService { // SRP: Single responsibility
511
+ constructor(
512
+ private userRepo: UserRepository, // DIP: Inject dependencies
513
+ private emailService: EmailService
514
+ ) {}
515
+
516
+ async register(data: UserData): Promise<User> { // KISS: Simple method
517
+ // YAGNI: Only what's needed for registration
518
+ const user = this.validate(data); // SoC: Separate validation
519
+ const saved = await this.userRepo.save(user);
520
+ await this.emailService.send(saved.email, 'Welcome', 'Thanks for registering!');
521
+ return saved;
522
+ }
523
+
524
+ private validate(data: UserData): User { // DRY: Reusable validation
525
+ if (!data.email || !data.password) {
526
+ throw new ValidationError('Email and password required');
527
+ }
528
+ return new User(data);
529
+ }
530
+ }
531
+ ```
532
+
533
+ **Principles Applied**:
534
+ - ✅ **SRP**: UserRegistrationService only handles registration
535
+ - ✅ **OCP**: Can extend with new validators without modifying
536
+ - ✅ **DIP**: Depends on interfaces, not concrete implementations
537
+ - ✅ **ISP**: Small, focused interfaces
538
+ - ✅ **SoC**: Validation, persistence, and email are separated
539
+ - ✅ **Modularity**: Can swap UserRepository or EmailService implementations
540
+ - ✅ **KISS**: Clear, simple logic
541
+ - ✅ **YAGNI**: No speculative features
542
+ - ✅ **DRY**: Validation extracted to private method
543
+
544
+ ---
545
+
546
+ ## Code Review Checklist
547
+
548
+ Use this checklist when reviewing code:
549
+
550
+ ### SOLID
551
+ - [ ] Does each class/module have a single responsibility?
552
+ - [ ] Can I extend functionality without modifying existing code?
553
+ - [ ] Are abstractions used instead of concrete implementations?
554
+ - [ ] Are interfaces small and focused?
555
+ - [ ] Do dependencies point toward abstractions?
556
+
557
+ ### DRY
558
+ - [ ] Is there any duplicated logic that should be extracted?
559
+ - [ ] Is duplication intentional (different concerns)?
560
+ - [ ] Are magic numbers/strings extracted to constants?
561
+
562
+ ### KISS
563
+ - [ ] Is the solution as simple as possible?
564
+ - [ ] Can complex logic be broken into simpler pieces?
565
+ - [ ] Are variable/function names clear without comments?
566
+
567
+ ### YAGNI
568
+ - [ ] Is every feature actually needed now?
569
+ - [ ] Are there "future-proofing" additions that can be removed?
570
+ - [ ] Does the code solve current requirements without speculation?
571
+
572
+ ### Separation of Concerns
573
+ - [ ] Are different concerns (UI, business logic, data) separated?
574
+ - [ ] Is business logic independent of frameworks?
575
+ - [ ] Are responsibilities clearly divided?
576
+
577
+ ### Modularity
578
+ - [ ] Are modules cohesive (related functionality together)?
579
+ - [ ] Are modules loosely coupled (minimal dependencies)?
580
+ - [ ] Are implementation details hidden?
581
+ - [ ] Are public interfaces clear and minimal?
582
+
583
+ ---
584
+
585
+ ## Common Anti-Patterns to Avoid
586
+
587
+ | Anti-Pattern | Violates | Fix |
588
+ |--------------|----------|-----|
589
+ | God Object/Class | SRP, SoC | Split into focused classes |
590
+ | Copy-Paste Programming | DRY | Extract common logic |
591
+ | Premature Optimization | KISS, YAGNI | Optimize when needed |
592
+ | Big Ball of Mud | All principles | Refactor with clear architecture |
593
+ | Shotgun Surgery | OCP, Modularity | Centralize related changes |
594
+ | Feature Envy | SRP, SoC | Move behavior to appropriate class |
595
+ | Long Parameter List | KISS, ISP | Use parameter objects |
596
+ | Magic Numbers | DRY | Extract to named constants |
597
+
598
+ ---
599
+
600
+ ## Language-Specific Guidance
601
+
602
+ ### TypeScript/JavaScript
603
+ - Use interfaces for contracts (ISP, DIP)
604
+ - Favor composition with functions (OCP)
605
+ - Use modules for separation (SoC, Modularity)
606
+ - Apply principles to React components (SRP, DRY)
607
+
608
+ ### Java
609
+ - Abstract classes and interfaces for SOLID
610
+ - Annotations for dependency injection (DIP)
611
+ - Packages for modularity
612
+ - Design patterns (Strategy, Factory) for OCP
613
+
614
+ ### Python
615
+ - Duck typing supports ISP naturally
616
+ - Modules and packages for SoC
617
+ - Decorators for cross-cutting concerns
618
+ - ABC (Abstract Base Classes) for interfaces
619
+
620
+ ### Go
621
+ - Interfaces for DIP and ISP
622
+ - Packages for modularity
623
+ - Composition over inheritance
624
+ - Simple, explicit code (KISS)
625
+
626
+ ---
627
+
628
+ ## References and Further Reading
629
+
630
+ - **SOLID**: Robert C. Martin (Uncle Bob) - "Clean Architecture"
631
+ - **DRY**: Andy Hunt & Dave Thomas - "The Pragmatic Programmer"
632
+ - **KISS**: Kelly Johnson - Lockheed Skunk Works
633
+ - **YAGNI**: Extreme Programming (XP) practices
634
+ - **Separation of Concerns**: Edsger W. Dijkstra
635
+ - **Modularity**: David Parnas - "On the Criteria to be Used in Decomposing Systems into Modules"
636
+
637
+ ---
638
+
639
+ **Remember**: These principles are guidelines, not absolute rules. Use judgment to apply them appropriately for your context. When principles conflict, prioritize based on your project's specific needs.