code-ai-installer 1.4.0 → 1.5.0

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,694 @@
1
+ ---
2
+ name: design_patterns_reference
3
+ description: Design patterns reference with DO/DON'T examples — SOLID, DRY/KISS/YAGNI, GoF (Strategy, Observer, Factory, Adapter, Facade, Decorator, Command, State, Template Method), architectural (Repository, Service Layer, DI, Event-Driven, CQRS), microservices (Saga, Circuit Breaker). Language-agnostic pseudocode. Use when designing modules, reviewing architecture, or when asked "which pattern to apply".
4
+ ---
5
+
6
+ # Skill: Design Patterns Reference
7
+
8
+ DO/DON'T reference for design patterns. Language-agnostic pseudocode.
9
+
10
+ **Sections:**
11
+ 1. [SOLID](#1-solid)
12
+ 2. [Fundamental Principles](#2-fundamental-principles)
13
+ 3. [GoF Patterns](#3-gof-patterns)
14
+ 4. [Architectural Patterns](#4-architectural-patterns)
15
+ 5. [Microservices Patterns](#5-microservices-patterns)
16
+ 6. [Pattern Selection Guide](#6-pattern-selection)
17
+
18
+ ---
19
+
20
+ ## 1. SOLID
21
+
22
+ ### S — Single Responsibility Principle (SRP)
23
+ > A class/module has exactly one reason to change.
24
+
25
+ ```
26
+ // ✅ DO: each class — one responsibility
27
+ class UserValidator
28
+ validate(user) → ValidationResult
29
+
30
+ class UserRepository
31
+ save(user) → void
32
+
33
+ class EmailNotifier
34
+ sendWelcome(user) → void
35
+ ```
36
+
37
+ ```
38
+ // ❌ DON'T: one class does everything
39
+ class UserManager
40
+ validate(user) → ...
41
+ saveToDb(user) → ...
42
+ sendEmail(user) → ...
43
+ generateReport() → ...
44
+ // Changing email logic breaks validation and DB
45
+ ```
46
+
47
+ ### O — Open/Closed Principle (OCP)
48
+ > Open for extension, closed for modification.
49
+
50
+ ```
51
+ // ✅ DO: new type = new class, without modifying existing code
52
+ interface DiscountStrategy
53
+ calculate(order) → number
54
+
55
+ class PercentDiscount implements DiscountStrategy
56
+ calculate(order) → order.total * this.percent
57
+
58
+ class FixedDiscount implements DiscountStrategy
59
+ calculate(order) → this.amount
60
+
61
+ class OrderService
62
+ applyDiscount(order, strategy: DiscountStrategy)
63
+ order.discount = strategy.calculate(order)
64
+ ```
65
+
66
+ ```
67
+ // ❌ DON'T: every new discount type — editing if/switch
68
+ class OrderService
69
+ applyDiscount(order, type)
70
+ if type == "percent" → ...
71
+ else if type == "fixed" → ...
72
+ else if type == "seasonal" → ... // modifying this method every time
73
+ ```
74
+
75
+ ### L — Liskov Substitution Principle (LSP)
76
+ > Subtypes can be substituted for the base type without breaking behavior.
77
+
78
+ ```
79
+ // ✅ DO: subtypes honestly implement the contract
80
+ interface Shape
81
+ area() → number
82
+
83
+ class Rectangle implements Shape
84
+ area() → this.width * this.height
85
+
86
+ class Circle implements Shape
87
+ area() → π * this.radius²
88
+
89
+ // Any Shape can be passed to calculateTotalArea(shapes[])
90
+ ```
91
+
92
+ ```
93
+ // ❌ DON'T: subtype violates parent's contract
94
+ class Rectangle
95
+ setWidth(w), setHeight(h)
96
+
97
+ class Square extends Rectangle
98
+ setWidth(w) → this.width = w; this.height = w // surprise: setWidth changes height
99
+ // Code that expects Rectangle breaks
100
+ ```
101
+
102
+ ### I — Interface Segregation Principle (ISP)
103
+ > Many small interfaces are better than one fat one.
104
+
105
+ ```
106
+ // ✅ DO: client depends only on needed methods
107
+ interface Readable
108
+ read() → Data
109
+
110
+ interface Writable
111
+ write(data) → void
112
+
113
+ interface Deletable
114
+ delete(id) → void
115
+
116
+ class FileStore implements Readable, Writable, Deletable
117
+ class ReadOnlyCache implements Readable
118
+ ```
119
+
120
+ ```
121
+ // ❌ DON'T: one fat interface — clients depend on what they don't need
122
+ interface Storage
123
+ read() → Data
124
+ write(data) → void
125
+ delete(id) → void
126
+ backup() → void
127
+ migrate() → void
128
+
129
+ class SimpleCache implements Storage
130
+ backup() → throw "Not supported" // contract violation
131
+ migrate() → throw "Not supported"
132
+ ```
133
+
134
+ ### D — Dependency Inversion Principle (DIP)
135
+ > Depend on abstractions, not on concrete implementations.
136
+
137
+ ```
138
+ // ✅ DO: business logic depends on an interface
139
+ interface PaymentGateway
140
+ charge(amount) → Result
141
+
142
+ class OrderService
143
+ constructor(gateway: PaymentGateway) // abstraction injection
144
+ checkout(order) → this.gateway.charge(order.total)
145
+
146
+ // Easy to swap: StripeGateway, PayPalGateway, TestGateway
147
+ ```
148
+
149
+ ```
150
+ // ❌ DON'T: direct dependency on a concrete implementation
151
+ class OrderService
152
+ checkout(order)
153
+ stripe = new StripeClient(API_KEY) // hardcoded to Stripe
154
+ stripe.charge(order.total)
155
+ // Cannot test, cannot replace
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 2. Fundamental Principles
161
+
162
+ ### DRY — Don't Repeat Yourself
163
+ ```
164
+ // ✅ DO: reusable function
165
+ function formatCurrency(amount, currency)
166
+ return currency.symbol + amount.toFixed(2)
167
+
168
+ // Used in Invoice, Cart, Report
169
+ ```
170
+
171
+ ```
172
+ // ❌ DON'T: copy-pasting the same logic
173
+ // In Invoice: "$" + amount.toFixed(2)
174
+ // In Cart: "$" + amount.toFixed(2)
175
+ // In Report: "$" + amount.toFixed(2)
176
+ // Changing the format → editing 3+ places
177
+ ```
178
+
179
+ > ⚠️ **Caution:** DRY is about knowledge, not code. Two identical code snippets with different reasons to change are NOT duplication.
180
+
181
+ ### KISS — Keep It Simple, Stupid
182
+ ```
183
+ // ✅ DO: simple and readable solution
184
+ function isAdult(age)
185
+ return age >= 18
186
+ ```
187
+
188
+ ```
189
+ // ❌ DON'T: overengineering
190
+ function isAdult(age)
191
+ ageValidator = new AgeValidatorFactory.create("adult")
192
+ rule = ageValidator.getRuleEngine().getRule("minimum")
193
+ return rule.evaluate(new AgeContext(age))
194
+ ```
195
+
196
+ ### YAGNI — You Aren't Gonna Need It
197
+ ```
198
+ // ✅ DO: implement what is needed now
199
+ class UserService
200
+ getUser(id) → User
201
+ createUser(data) → User
202
+
203
+ // ❌ DON'T: "just in case"
204
+ class UserService
205
+ getUser(id) → User
206
+ createUser(data) → User
207
+ exportToXml() → ... // nobody asked
208
+ syncWithLdap() → ... // no requirement
209
+ generatePdfReport() → ... // "might come in handy"
210
+ ```
211
+
212
+ ### Composition over Inheritance
213
+ ```
214
+ // ✅ DO: composition — flexible, testable
215
+ class Logger
216
+ log(msg) → ...
217
+
218
+ class HttpClient
219
+ constructor(logger: Logger)
220
+ get(url) → this.logger.log(...); fetch(url)
221
+
222
+ class CachedHttpClient
223
+ constructor(client: HttpClient, cache: Cache)
224
+ get(url) → cache.get(url) ?? client.get(url)
225
+ ```
226
+
227
+ ```
228
+ // ❌ DON'T: deep inheritance hierarchy
229
+ class BaseClient → class HttpClient → class AuthHttpClient → class CachedAuthHttpClient
230
+ // 4 levels of inheritance — fragile, hard to modify
231
+ ```
232
+
233
+ ### Fail Fast
234
+ ```
235
+ // ✅ DO: validate inputs immediately
236
+ function transfer(from, to, amount)
237
+ if amount <= 0 → throw InvalidAmountError
238
+ if from.balance < amount → throw InsufficientFundsError
239
+ // ... main logic only if everything is valid
240
+
241
+ // ❌ DON'T: error surfaces deep inside
242
+ function transfer(from, to, amount)
243
+ from.balance -= amount // may go negative
244
+ to.balance += amount // data already corrupted
245
+ if from.balance < 0 → ... // too late!
246
+ ```
247
+
248
+ ---
249
+
250
+ ## 3. GoF Patterns
251
+
252
+ ### Strategy — swappable algorithms
253
+ ```
254
+ // ✅ DO: algorithm as an injectable strategy
255
+ interface SortStrategy
256
+ sort(items[]) → items[]
257
+
258
+ class BubbleSort implements SortStrategy
259
+ class QuickSort implements SortStrategy
260
+ class MergeSort implements SortStrategy
261
+
262
+ class DataProcessor
263
+ constructor(strategy: SortStrategy)
264
+ process(data) → this.strategy.sort(data)
265
+ ```
266
+
267
+ **When:** multiple algorithm variants, runtime selection.
268
+
269
+ ### Observer — change notifications
270
+ ```
271
+ // ✅ DO: subscribe/notify without tight coupling
272
+ class EventBus
273
+ subscribers = Map<string, Function[]>
274
+ subscribe(event, handler)
275
+ publish(event, data) → subscribers[event].forEach(h => h(data))
276
+
277
+ // Components subscribe without knowing about each other
278
+ bus.subscribe("order.created", sendEmail)
279
+ bus.subscribe("order.created", updateInventory)
280
+ bus.subscribe("order.created", logAudit)
281
+ ```
282
+
283
+ **When:** one event source, many consumers.
284
+
285
+ ### Factory Method — creation without binding to a specific class
286
+ ```
287
+ // ✅ DO: factory selects the implementation
288
+ class NotificationFactory
289
+ static create(type) →
290
+ if type == "email" → new EmailNotification()
291
+ if type == "sms" → new SmsNotification()
292
+ if type == "push" → new PushNotification()
293
+ throw UnknownTypeError
294
+
295
+ // Client doesn't know about specific classes
296
+ notification = NotificationFactory.create(user.preference)
297
+ notification.send(message)
298
+ ```
299
+
300
+ **When:** object type determined at runtime; client should not know the specifics.
301
+
302
+ ### Adapter — compatibility for incompatible interfaces
303
+ ```
304
+ // ✅ DO: adapter wraps a foreign interface into yours
305
+ interface PaymentGateway
306
+ charge(amount, currency) → Result
307
+
308
+ class StripeAdapter implements PaymentGateway
309
+ constructor(stripeClient)
310
+ charge(amount, currency) →
311
+ this.stripeClient.createPaymentIntent({
312
+ amount: amount * 100, // Stripe accepts cents
313
+ currency: currency
314
+ })
315
+ ```
316
+
317
+ **When:** integrating with an external API/library whose interface doesn't match yours.
318
+
319
+ ### Facade — simple interface to a complex subsystem
320
+ ```
321
+ // ✅ DO: facade hides complexity
322
+ class OrderFacade
323
+ constructor(inventory, payment, shipping, notification)
324
+
325
+ placeOrder(cart, user) →
326
+ inventory.reserve(cart.items)
327
+ payment.charge(user, cart.total)
328
+ shipping.createShipment(user.address, cart.items)
329
+ notification.sendConfirmation(user, cart)
330
+
331
+ // Client calls one method instead of four subsystems
332
+ orderFacade.placeOrder(cart, user)
333
+ ```
334
+
335
+ **When:** complex subsystem of multiple components; client needs a simple entry point.
336
+
337
+ ### Decorator — dynamic behavior extension
338
+ ```
339
+ // ✅ DO: wrappers add behavior without modifying the original
340
+ interface DataSource
341
+ read() → Data
342
+ write(data) → void
343
+
344
+ class FileDataSource implements DataSource
345
+ class EncryptionDecorator implements DataSource
346
+ constructor(source: DataSource)
347
+ write(data) → this.source.write(encrypt(data))
348
+ read() → decrypt(this.source.read())
349
+
350
+ class CompressionDecorator implements DataSource
351
+ constructor(source: DataSource)
352
+ write(data) → this.source.write(compress(data))
353
+
354
+ // Combining: compression + encryption + file
355
+ source = new CompressionDecorator(new EncryptionDecorator(new FileDataSource()))
356
+ ```
357
+
358
+ **When:** need to combine behaviors in various combinations without a subclass explosion.
359
+
360
+ ### Command — action encapsulated as an object
361
+ ```
362
+ // ✅ DO: each action = object with execute/undo
363
+ interface Command
364
+ execute() → void
365
+ undo() → void
366
+
367
+ class AddItemCommand implements Command
368
+ constructor(cart, item)
369
+ execute() → this.cart.add(this.item)
370
+ undo() → this.cart.remove(this.item)
371
+
372
+ class CommandHistory
373
+ stack = []
374
+ execute(cmd) → cmd.execute(); stack.push(cmd)
375
+ undo() → stack.pop().undo()
376
+ ```
377
+
378
+ **When:** undo/redo, operation queues, deferred execution.
379
+
380
+ ### State — behavior depends on state
381
+ ```
382
+ // ✅ DO: each state = separate class
383
+ interface OrderState
384
+ next(order) → void
385
+ cancel(order) → void
386
+
387
+ class PendingState implements OrderState
388
+ next(order) → order.setState(new PaidState())
389
+ cancel(order) → order.setState(new CancelledState())
390
+
391
+ class PaidState implements OrderState
392
+ next(order) → order.setState(new ShippedState())
393
+ cancel(order) → throw "Cannot cancel paid order"
394
+
395
+ class Order
396
+ state: OrderState = new PendingState()
397
+ next() → this.state.next(this)
398
+ cancel() → this.state.cancel(this)
399
+ ```
400
+
401
+ ```
402
+ // ❌ DON'T: switch/if on string status
403
+ class Order
404
+ status = "pending"
405
+ next()
406
+ if status == "pending" → status = "paid"
407
+ else if status == "paid" → status = "shipped"
408
+ // grows infinitely with new statuses
409
+ ```
410
+
411
+ **When:** object with multiple states and different behavior in each.
412
+
413
+ ### Template Method — algorithm skeleton with overridable steps
414
+ ```
415
+ // ✅ DO: base class defines the skeleton, steps are overridden
416
+ abstract class DataImporter
417
+ import(source) // template method
418
+ data = this.read(source)
419
+ validated = this.validate(data)
420
+ transformed = this.transform(validated)
421
+ this.save(transformed)
422
+
423
+ abstract read(source) → RawData
424
+ abstract validate(data) → ValidData
425
+ abstract transform(data) → FinalData
426
+ save(data) → db.insert(data) // shared implementation
427
+
428
+ class CsvImporter extends DataImporter
429
+ read(source) → parseCsv(source)
430
+ validate(data) → validateCsvRows(data)
431
+ transform(data) → mapCsvToEntities(data)
432
+
433
+ class JsonImporter extends DataImporter
434
+ read(source) → parseJson(source)
435
+ validate(data) → validateJsonSchema(data)
436
+ transform(data) → mapJsonToEntities(data)
437
+ ```
438
+
439
+ **When:** same algorithm skeleton, different implementation details.
440
+
441
+ ---
442
+
443
+ ## 4. Architectural Patterns
444
+
445
+ ### Repository — data access isolation
446
+ ```
447
+ // ✅ DO: repository encapsulates storage access
448
+ interface UserRepository
449
+ findById(id) → User | null
450
+ findByEmail(email) → User | null
451
+ save(user) → User
452
+ delete(id) → void
453
+
454
+ class PostgresUserRepository implements UserRepository
455
+ findById(id) → db.query("SELECT ... WHERE id = $1", [id])
456
+
457
+ class MongoUserRepository implements UserRepository
458
+ findById(id) → collection.findOne({ _id: id })
459
+
460
+ // Business logic doesn't know about SQL/Mongo
461
+ class UserService
462
+ constructor(repo: UserRepository)
463
+ getUser(id) → this.repo.findById(id)
464
+ ```
465
+
466
+ ```
467
+ // ❌ DON'T: SQL in business logic
468
+ class UserService
469
+ getUser(id)
470
+ result = db.query("SELECT * FROM users WHERE id = $1", [id])
471
+ // Bound to PostgreSQL, cannot test without DB
472
+ ```
473
+
474
+ ### Service Layer — business logic not in controllers
475
+ ```
476
+ // ✅ DO: controller → service → repository
477
+ class OrderController
478
+ constructor(orderService)
479
+ handleCreateOrder(req)
480
+ order = this.orderService.create(req.body)
481
+ return Response(201, order)
482
+
483
+ class OrderService
484
+ constructor(orderRepo, paymentGateway, inventory)
485
+ create(data)
486
+ this.inventory.reserve(data.items)
487
+ order = Order.create(data)
488
+ this.paymentGateway.charge(order.total)
489
+ this.orderRepo.save(order)
490
+ return order
491
+
492
+ // ❌ DON'T: business logic in controller
493
+ class OrderController
494
+ handleCreateOrder(req)
495
+ db.query("INSERT INTO orders ...") // SQL in controller
496
+ stripe.charge(...) // payment in controller
497
+ sendEmail(...) // and email too
498
+ ```
499
+
500
+ ### Dependency Injection (DI)
501
+ ```
502
+ // ✅ DO: dependencies passed from outside
503
+ class Application
504
+ start()
505
+ db = new PostgresConnection(config.db)
506
+ userRepo = new PostgresUserRepository(db)
507
+ emailService = new SmtpEmailService(config.smtp)
508
+ userService = new UserService(userRepo, emailService)
509
+ controller = new UserController(userService)
510
+ server.register(controller)
511
+
512
+ // Each component receives dependencies via constructor
513
+ // Easy to test: substitute mock repository
514
+ ```
515
+
516
+ ```
517
+ // ❌ DON'T: components create their own dependencies
518
+ class UserService
519
+ repo = new PostgresUserRepository(new PostgresConnection("hardcoded"))
520
+ email = new SmtpEmailService("smtp://hardcoded")
521
+ // Cannot test without real PostgreSQL and SMTP
522
+ ```
523
+
524
+ ### Event-Driven — reacting to events
525
+ ```
526
+ // ✅ DO: loose coupling through events
527
+ // Service creates order and publishes event
528
+ class OrderService
529
+ createOrder(data)
530
+ order = Order.create(data)
531
+ orderRepo.save(order)
532
+ eventBus.publish("order.created", { orderId: order.id })
533
+
534
+ // Independent handlers subscribed to the event
535
+ class InventoryHandler
536
+ on("order.created") → reserveItems(event.orderId)
537
+
538
+ class NotificationHandler
539
+ on("order.created") → sendConfirmation(event.orderId)
540
+
541
+ class AnalyticsHandler
542
+ on("order.created") → trackConversion(event.orderId)
543
+
544
+ // Adding a new handler → not a single line in OrderService changes
545
+ ```
546
+
547
+ ```
548
+ // ❌ DON'T: OrderService knows about all dependent components
549
+ class OrderService
550
+ createOrder(data)
551
+ order = Order.create(data)
552
+ orderRepo.save(order)
553
+ inventoryService.reserve(order) // tight coupling
554
+ notificationService.send(order) // tight coupling
555
+ analyticsService.track(order) // tight coupling
556
+ ```
557
+
558
+ ### CQRS — Command Query Responsibility Segregation
559
+ ```
560
+ // ✅ DO: separate models for writing and reading
561
+ // Command side — normalized model; business rules
562
+ class CreateOrderCommand
563
+ execute(data)
564
+ order = Order.create(data)
565
+ orderRepo.save(order)
566
+ eventBus.publish("order.created", order)
567
+
568
+ // Query side — denormalized model; optimized for reading
569
+ class OrderQueryService
570
+ getOrderSummary(id) →
571
+ readDb.query("SELECT ... FROM order_summaries WHERE id = $1", [id])
572
+
573
+ getOrdersByUser(userId, page) →
574
+ readDb.query("SELECT ... FROM user_orders_view WHERE user_id = $1 LIMIT ...", [userId])
575
+
576
+ // Writes update the read model via events
577
+ on("order.created") → updateOrderSummaryView(event)
578
+ ```
579
+
580
+ **When:** read and write patterns differ significantly; high read load; denormalization needed for fast queries.
581
+
582
+ ---
583
+
584
+ ## 5. Microservices Patterns
585
+
586
+ ### Saga — distributed transactions via compensations
587
+ ```
588
+ // ✅ DO: each step has a compensation (rollback)
589
+ class OrderSaga
590
+ steps = [
591
+ { action: reserveInventory, compensate: releaseInventory },
592
+ { action: chargePayment, compensate: refundPayment },
593
+ { action: createShipment, compensate: cancelShipment },
594
+ { action: sendConfirmation, compensate: sendCancellation },
595
+ ]
596
+
597
+ execute(orderData)
598
+ completed = []
599
+ for step in steps
600
+ try
601
+ step.action(orderData)
602
+ completed.push(step)
603
+ catch error
604
+ // Roll back all completed steps in reverse order
605
+ for s in completed.reverse()
606
+ s.compensate(orderData)
607
+ throw SagaFailedError(error)
608
+ ```
609
+
610
+ **When:** transaction spans multiple services; cannot use distributed 2PC.
611
+
612
+ ### Circuit Breaker — protection against cascading failures
613
+ ```
614
+ // ✅ DO: Circuit Breaker before calling an external service
615
+ class CircuitBreaker
616
+ state = CLOSED // normal operation
617
+ failureCount = 0
618
+ threshold = 5
619
+ resetTimeout = 30s
620
+
621
+ call(fn)
622
+ if state == OPEN
623
+ if elapsed > resetTimeout → state = HALF_OPEN
624
+ else → throw ServiceUnavailableError // don't send request
625
+
626
+ try
627
+ result = fn()
628
+ if state == HALF_OPEN → state = CLOSED; failureCount = 0
629
+ return result
630
+ catch error
631
+ failureCount++
632
+ if failureCount >= threshold → state = OPEN; startTimer()
633
+ throw error
634
+
635
+ // Usage
636
+ breaker = new CircuitBreaker()
637
+ userData = breaker.call(() => externalUserApi.getUser(id))
638
+ ```
639
+
640
+ **When:** dependency on an external service that may fail; preventing cascading failure.
641
+
642
+ ### Mediator — central coordinator for interactions
643
+ ```
644
+ // ✅ DO: components communicate through mediator, not directly
645
+ class OrderMediator
646
+ handlers = Map<string, Handler>
647
+
648
+ register(commandType, handler)
649
+ send(command)
650
+ handler = this.handlers.get(command.type)
651
+ return handler.handle(command)
652
+
653
+ // Registration
654
+ mediator.register("CreateOrder", new CreateOrderHandler(orderRepo, inventory))
655
+ mediator.register("CancelOrder", new CancelOrderHandler(orderRepo, payment))
656
+
657
+ // Call — controller doesn't know about specific handlers
658
+ class OrderController
659
+ handleCreate(req) → mediator.send(new CreateOrderCommand(req.body))
660
+ handleCancel(req) → mediator.send(new CancelOrderCommand(req.params.id))
661
+ ```
662
+
663
+ **When:** many interacting components; need to centralize coordination and remove direct dependencies.
664
+
665
+ ---
666
+
667
+ ## 6. Pattern Selection
668
+
669
+ | Problem | Pattern | Example |
670
+ |---------|---------|---------|
671
+ | Multiple algorithm variants | Strategy | Sorting algorithms, discount calculations |
672
+ | Reacting to changes | Observer / Event-Driven | Notifications, audit, analytics |
673
+ | Conditional object creation | Factory Method | Notifications: email/sms/push |
674
+ | Integration with foreign API | Adapter | Stripe/PayPal wrapper |
675
+ | Complex subsystem | Facade | Order placement (inventory + payment + shipping) |
676
+ | Behavior combinations | Decorator | Caching + encryption + logging |
677
+ | Undo/redo, queues | Command | Text editor, batch operations |
678
+ | Multiple object states | State | Order workflow, tasks |
679
+ | Same skeleton, different details | Template Method | CSV/JSON/XML import |
680
+ | Storage isolation | Repository | DB access without SQL in business logic |
681
+ | Business logic not in controllers | Service Layer | REST API |
682
+ | Loose component coupling | DI | Dependency injection via constructor |
683
+ | Different read/write models | CQRS | Dashboard + admin panel |
684
+ | Distributed transactions | Saga | Order: inventory → payment → shipping |
685
+ | Protection against cascading failures | Circuit Breaker | External APIs |
686
+ | Component coordination | Mediator | Request → Handler routing |
687
+
688
+ ---
689
+
690
+ ## See also
691
+ - `architecture_doc` → where to document chosen patterns
692
+ - `architecture_compliance_review` → verifying adherence to architecture
693
+ - `adr_log` → recording pattern selection decisions
694
+ - `code_review_checklist` → verifying pattern implementation
@@ -7,6 +7,9 @@ description: TanStack (Query v5, Table v8, Virtual v3): caching, invalidation, p
7
7
 
8
8
  Copy-paste patterns for predictable work with data, tables, and virtualization.
9
9
 
10
+ > [!IMPORTANT]
11
+ > **MCP priority:** If the `tanstack-docs` MCP server is available, **always use its tools first** (`tanstack_doc`, `tanstack_search_docs`, `listTanStackAddOns`, `getAddOnDetails`, `createTanStackApplication`) — they provide up-to-date documentation directly from official TanStack sources. Use the patterns in this skill as a fallback or as additional architectural context (fetcher/adapter/hook, queryKey factory, optimistic updates, virtualization) when the MCP is unavailable or does not contain the required information.
12
+
10
13
  **Sections:**
11
14
  1. [Query: fetcher/adapter architecture](#1-query-architecture)
12
15
  2. [Query: caching and staleTime](#2-query-cache)
@@ -49,6 +49,7 @@ Use skills (folders with `SKILL.md`). Full list:
49
49
  - $system_design_checklist
50
50
  - $architecture_doc
51
51
  - $architecture_compliance_review
52
+ - $design_patterns_reference
52
53
  - $adr_log
53
54
  - $api_contracts
54
55
  - $data_model