@venizia/ignis-docs 0.0.3 → 0.0.4-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.
Files changed (131) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -2
  3. package/wiki/best-practices/api-usage-examples.md +591 -0
  4. package/wiki/best-practices/architectural-patterns.md +415 -0
  5. package/wiki/best-practices/architecture-decisions.md +488 -0
  6. package/wiki/{get-started/best-practices → best-practices}/code-style-standards.md +406 -17
  7. package/wiki/{get-started/best-practices → best-practices}/common-pitfalls.md +109 -4
  8. package/wiki/{get-started/best-practices → best-practices}/contribution-workflow.md +34 -7
  9. package/wiki/best-practices/data-modeling.md +376 -0
  10. package/wiki/best-practices/deployment-strategies.md +698 -0
  11. package/wiki/best-practices/index.md +27 -0
  12. package/wiki/best-practices/performance-optimization.md +196 -0
  13. package/wiki/best-practices/security-guidelines.md +218 -0
  14. package/wiki/{get-started/best-practices → best-practices}/troubleshooting-tips.md +97 -1
  15. package/wiki/changelogs/2025-12-16-initial-architecture.md +1 -1
  16. package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +1 -1
  17. package/wiki/changelogs/2025-12-17-refactor.md +1 -1
  18. package/wiki/changelogs/2025-12-18-performance-optimizations.md +5 -5
  19. package/wiki/changelogs/2025-12-18-repository-validation-security.md +13 -7
  20. package/wiki/changelogs/2025-12-26-nested-relations-and-generics.md +2 -2
  21. package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
  22. package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
  23. package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
  24. package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
  25. package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
  26. package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
  27. package/wiki/changelogs/index.md +6 -0
  28. package/wiki/changelogs/planned-schema-migrator.md +0 -8
  29. package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
  30. package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
  31. package/wiki/guides/core-concepts/components-guide.md +509 -0
  32. package/wiki/{get-started → guides}/core-concepts/components.md +24 -17
  33. package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
  34. package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
  35. package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
  36. package/wiki/guides/core-concepts/persistent/index.md +119 -0
  37. package/wiki/guides/core-concepts/persistent/models.md +241 -0
  38. package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
  39. package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
  40. package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
  41. package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
  42. package/wiki/guides/get-started/philosophy.md +682 -0
  43. package/wiki/guides/get-started/setup.md +157 -0
  44. package/wiki/guides/index.md +89 -0
  45. package/wiki/guides/reference/glossary.md +243 -0
  46. package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
  47. package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
  48. package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
  49. package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
  50. package/wiki/guides/tutorials/realtime-chat.md +1261 -0
  51. package/wiki/guides/tutorials/testing.md +723 -0
  52. package/wiki/index.md +176 -37
  53. package/wiki/references/base/application.md +27 -0
  54. package/wiki/references/base/bootstrapping.md +31 -26
  55. package/wiki/references/base/components.md +24 -7
  56. package/wiki/references/base/controllers.md +50 -20
  57. package/wiki/references/base/datasources.md +30 -0
  58. package/wiki/references/base/dependency-injection.md +39 -3
  59. package/wiki/references/base/filter-system/application-usage.md +224 -0
  60. package/wiki/references/base/filter-system/array-operators.md +132 -0
  61. package/wiki/references/base/filter-system/comparison-operators.md +109 -0
  62. package/wiki/references/base/filter-system/default-filter.md +428 -0
  63. package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
  64. package/wiki/references/base/filter-system/index.md +127 -0
  65. package/wiki/references/base/filter-system/json-filtering.md +197 -0
  66. package/wiki/references/base/filter-system/list-operators.md +71 -0
  67. package/wiki/references/base/filter-system/logical-operators.md +156 -0
  68. package/wiki/references/base/filter-system/null-operators.md +58 -0
  69. package/wiki/references/base/filter-system/pattern-matching.md +108 -0
  70. package/wiki/references/base/filter-system/quick-reference.md +431 -0
  71. package/wiki/references/base/filter-system/range-operators.md +63 -0
  72. package/wiki/references/base/filter-system/tips.md +190 -0
  73. package/wiki/references/base/filter-system/use-cases.md +452 -0
  74. package/wiki/references/base/index.md +90 -0
  75. package/wiki/references/base/middlewares.md +604 -0
  76. package/wiki/references/base/models.md +215 -23
  77. package/wiki/references/base/providers.md +731 -0
  78. package/wiki/references/base/repositories/advanced.md +555 -0
  79. package/wiki/references/base/repositories/index.md +228 -0
  80. package/wiki/references/base/repositories/mixins.md +331 -0
  81. package/wiki/references/base/repositories/relations.md +486 -0
  82. package/wiki/references/base/repositories.md +40 -635
  83. package/wiki/references/base/services.md +28 -4
  84. package/wiki/references/components/authentication.md +22 -2
  85. package/wiki/references/components/health-check.md +12 -0
  86. package/wiki/references/components/index.md +23 -0
  87. package/wiki/references/components/mail.md +687 -0
  88. package/wiki/references/components/request-tracker.md +16 -0
  89. package/wiki/references/components/socket-io.md +18 -0
  90. package/wiki/references/components/static-asset.md +14 -26
  91. package/wiki/references/components/swagger.md +17 -0
  92. package/wiki/references/configuration/environment-variables.md +427 -0
  93. package/wiki/references/configuration/index.md +73 -0
  94. package/wiki/references/helpers/cron.md +14 -0
  95. package/wiki/references/helpers/crypto.md +15 -0
  96. package/wiki/references/helpers/env.md +16 -0
  97. package/wiki/references/helpers/error.md +17 -0
  98. package/wiki/references/helpers/index.md +14 -0
  99. package/wiki/references/helpers/inversion.md +24 -4
  100. package/wiki/references/helpers/logger.md +19 -0
  101. package/wiki/references/helpers/network.md +11 -0
  102. package/wiki/references/helpers/queue.md +19 -0
  103. package/wiki/references/helpers/redis.md +21 -0
  104. package/wiki/references/helpers/socket-io.md +24 -5
  105. package/wiki/references/helpers/storage.md +18 -10
  106. package/wiki/references/helpers/testing.md +18 -0
  107. package/wiki/references/helpers/types.md +16 -0
  108. package/wiki/references/helpers/uid.md +167 -0
  109. package/wiki/references/helpers/worker-thread.md +16 -0
  110. package/wiki/references/index.md +177 -0
  111. package/wiki/references/quick-reference.md +634 -0
  112. package/wiki/references/src-details/boot.md +3 -3
  113. package/wiki/references/src-details/dev-configs.md +0 -4
  114. package/wiki/references/src-details/docs.md +2 -2
  115. package/wiki/references/src-details/index.md +86 -0
  116. package/wiki/references/src-details/inversion.md +1 -6
  117. package/wiki/references/src-details/mcp-server.md +3 -15
  118. package/wiki/references/utilities/index.md +86 -10
  119. package/wiki/references/utilities/jsx.md +577 -0
  120. package/wiki/references/utilities/request.md +0 -2
  121. package/wiki/references/utilities/statuses.md +740 -0
  122. package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
  123. package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
  124. package/wiki/get-started/best-practices/data-modeling.md +0 -177
  125. package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
  126. package/wiki/get-started/best-practices/performance-optimization.md +0 -97
  127. package/wiki/get-started/best-practices/security-guidelines.md +0 -99
  128. package/wiki/get-started/core-concepts/persistent.md +0 -539
  129. package/wiki/get-started/index.md +0 -65
  130. package/wiki/get-started/philosophy.md +0 -296
  131. package/wiki/get-started/prerequisites.md +0 -113
@@ -0,0 +1,488 @@
1
+ # Architecture Decisions Guide
2
+
3
+ This guide helps you make informed architectural decisions when building applications with Ignis. Learn when to use different patterns and how to scale your application.
4
+
5
+ ## Common Decision Points
6
+
7
+ | Decision | Options | Recommendation |
8
+ |----------|---------|----------------|
9
+ | Service layer? | Direct repo vs Service | Use Service for business logic |
10
+ | Component vs inline? | Reusable vs one-off | Component if used 2+ times |
11
+ | Repository methods? | CRUD only vs custom | Start CRUD, add custom as needed |
12
+ | Error handling? | Service vs Controller | Handle in Controller, log in Service |
13
+ | Transactions? | Manual vs automatic | Use repository transaction support |
14
+
15
+ ---
16
+
17
+ ## 1. When to Use Services vs Direct Repository
18
+
19
+ ### Use Direct Repository Access When:
20
+
21
+ ```typescript
22
+ // Simple CRUD with no business logic
23
+ @controller({ path: '/items' })
24
+ export class ItemController extends BaseController {
25
+ constructor(
26
+ @inject('repositories.ItemRepository')
27
+ private itemRepo: ItemRepository,
28
+ ) {
29
+ super({ scope: 'ItemController', path: '/items' });
30
+ }
31
+
32
+ @get({ configs: { path: '/:id' } })
33
+ async getItem(c: Context) {
34
+ const item = await this.itemRepo.findById(c.req.param('id'));
35
+ return c.json(item);
36
+ }
37
+ }
38
+ ```
39
+
40
+ **Good for:**
41
+ - Simple read operations
42
+ - Basic CRUD endpoints
43
+ - Prototypes and MVPs
44
+ - Admin panels
45
+
46
+ ### Use Service Layer When:
47
+
48
+ ```typescript
49
+ // Complex business logic needs a service
50
+ @controller({ path: '/orders' })
51
+ export class OrderController extends BaseController {
52
+ constructor(
53
+ @inject('services.OrderService')
54
+ private orderService: OrderService,
55
+ ) {
56
+ super({ scope: 'OrderController', path: '/orders' });
57
+ }
58
+
59
+ @post({ configs: { path: '/' } })
60
+ async createOrder(c: Context) {
61
+ const data = await c.req.json();
62
+ // Service handles: validation, inventory check, payment, notifications
63
+ const order = await this.orderService.createOrder(data);
64
+ return c.json(order, 201);
65
+ }
66
+ }
67
+ ```
68
+
69
+ **Good for:**
70
+ - Multiple repository interactions
71
+ - External service calls (payments, email)
72
+ - Complex validation rules
73
+ - Transaction management
74
+ - Business rule enforcement
75
+
76
+ ### Decision Matrix
77
+
78
+ | Scenario | Repository | Service |
79
+ |----------|------------|---------|
80
+ | Get user by ID | Yes | No |
81
+ | Create order with payment | No | Yes |
82
+ | List products with filters | Yes | No |
83
+ | User registration with email | No | Yes |
84
+ | Update product price | Yes | Maybe |
85
+ | Process refund | No | Yes |
86
+
87
+ ---
88
+
89
+ ## 2. When to Create Components
90
+
91
+ ### Create a Component When:
92
+
93
+ 1. **Functionality is used across multiple applications**
94
+ 2. **Feature is self-contained with its own configuration**
95
+ 3. **You want to share with the team/community**
96
+
97
+ ```typescript
98
+ // Component: Self-contained, configurable, reusable
99
+ @component({ scope: 'NotificationComponent' })
100
+ export class NotificationComponent extends BaseComponent {
101
+ private emailService: EmailService;
102
+ private smsService: SMSService;
103
+ private pushService: PushService;
104
+
105
+ override configure() {
106
+ // Setup services based on configuration
107
+ this.emailService = new EmailService(this.config.email);
108
+ if (this.config.sms?.enabled) {
109
+ this.smsService = new SMSService(this.config.sms);
110
+ }
111
+ }
112
+
113
+ async notify(opts: NotifyOptions) {
114
+ // Unified notification API
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Keep Inline When:
120
+
121
+ 1. **Feature is specific to one application**
122
+ 2. **Logic is simple and unlikely to change**
123
+ 3. **No configuration needed**
124
+
125
+ ```typescript
126
+ // Inline: Simple, one-off, no need for abstraction
127
+ @controller({ path: '/health' })
128
+ export class HealthController extends BaseController {
129
+ @get({ configs: { path: '/' } })
130
+ healthCheck(c: Context) {
131
+ return c.json({ status: 'ok', timestamp: new Date() });
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Component vs Service vs Inline
137
+
138
+ | Pattern | Scope | Reusability | Configuration |
139
+ |---------|-------|-------------|---------------|
140
+ | **Component** | Cross-app | High | External config |
141
+ | **Service** | Single app | Medium | Internal |
142
+ | **Inline** | Single controller | None | None |
143
+
144
+ ---
145
+
146
+ ## 3. Repository Method Design
147
+
148
+ ### Start with Standard CRUD
149
+
150
+ Every repository gets these methods from `BaseRepository`:
151
+
152
+ ```typescript
153
+ // Inherited methods - use these first
154
+ find(filter) // List with filters
155
+ findById(id) // Get by ID
156
+ findOne(filter) // Get first match
157
+ create(data) // Create new
158
+ updateById(id, data) // Update existing
159
+ deleteById(id) // Delete
160
+ count(filter) // Count matches
161
+ ```
162
+
163
+ ### Add Custom Methods When:
164
+
165
+ 1. **Query is complex and reusable**
166
+ 2. **Business logic belongs at data layer**
167
+ 3. **Performance optimization needed**
168
+
169
+ ```typescript
170
+ // Custom repository methods
171
+ export class OrderRepository extends BaseRepository<Order> {
172
+ // Complex query that's used in multiple places
173
+ async findPendingOrdersOlderThan(hours: number) {
174
+ const cutoff = new Date(Date.now() - hours * 60 * 60 * 1000);
175
+ return this.find({
176
+ where: {
177
+ status: 'pending',
178
+ createdAt: { lt: cutoff },
179
+ },
180
+ orderBy: { createdAt: 'asc' },
181
+ });
182
+ }
183
+
184
+ // Performance-optimized query
185
+ async getOrderStats(userId: string) {
186
+ return this.db.execute(sql`
187
+ SELECT
188
+ COUNT(*) as total,
189
+ SUM(total) as revenue,
190
+ AVG(total) as average
191
+ FROM orders
192
+ WHERE user_id = ${userId}
193
+ `);
194
+ }
195
+
196
+ // Business logic at data layer
197
+ async softDelete(id: string) {
198
+ return this.updateById(id, {
199
+ deletedAt: new Date(),
200
+ status: 'deleted',
201
+ });
202
+ }
203
+ }
204
+ ```
205
+
206
+ ---
207
+
208
+ ## 4. Error Handling Strategy
209
+
210
+ ### Controller Level: Format Response
211
+
212
+ ```typescript
213
+ @controller({ path: '/users' })
214
+ export class UserController extends BaseController {
215
+ @post({ configs: { path: '/' } })
216
+ async createUser(c: Context) {
217
+ try {
218
+ const data = await c.req.json();
219
+ const user = await this.userService.create(data);
220
+ return c.json(user, 201);
221
+ } catch (error) {
222
+ // Format error for API response
223
+ if (error.code === 'DUPLICATE_EMAIL') {
224
+ return c.json({ error: 'Email already exists' }, 400);
225
+ }
226
+ throw error; // Let global handler catch unknown errors
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ### Service Level: Throw Domain Errors
233
+
234
+ ```typescript
235
+ @injectable()
236
+ export class UserService extends BaseService {
237
+ async create(data: CreateUserInput) {
238
+ // Validate and throw domain-specific errors
239
+ const existing = await this.userRepo.findByEmail(data.email);
240
+ if (existing) {
241
+ throw getError({
242
+ statusCode: 400,
243
+ code: 'DUPLICATE_EMAIL',
244
+ message: 'User with this email already exists',
245
+ });
246
+ }
247
+
248
+ // Log operations
249
+ this.logger.info('Creating user', { email: data.email });
250
+
251
+ return this.userRepo.create(data);
252
+ }
253
+ }
254
+ ```
255
+
256
+ ### Repository Level: Let Errors Bubble
257
+
258
+ ```typescript
259
+ export class UserRepository extends BaseRepository<User> {
260
+ // Don't catch database errors here
261
+ // Let them bubble up to service/controller
262
+ async findByEmail(email: string) {
263
+ return this.findOne({ where: { email } });
264
+ }
265
+ }
266
+ ```
267
+
268
+ ### Error Handling Flow
269
+
270
+ ```
271
+ Repository (DB errors)
272
+ ↓ bubbles up
273
+ Service (catches, transforms to domain errors, logs)
274
+ ↓ throws
275
+ Controller (catches, formats for API response)
276
+ ↓ responds
277
+ Client (receives formatted error)
278
+ ```
279
+
280
+ ---
281
+
282
+ ## 5. Scaling Decisions
283
+
284
+ ### When to Split Services
285
+
286
+ **Before:**
287
+ ```typescript
288
+ // Monolithic service doing too much
289
+ class UserService {
290
+ async register(data) { /* ... */ }
291
+ async login(data) { /* ... */ }
292
+ async updateProfile(data) { /* ... */ }
293
+ async sendPasswordReset(email) { /* ... */ }
294
+ async verifyEmail(token) { /* ... */ }
295
+ async sendWelcomeEmail(userId) { /* ... */ }
296
+ }
297
+ ```
298
+
299
+ **After:**
300
+ ```typescript
301
+ // Split by domain
302
+ class AuthService {
303
+ async register(data) { /* ... */ }
304
+ async login(data) { /* ... */ }
305
+ async sendPasswordReset(email) { /* ... */ }
306
+ }
307
+
308
+ class ProfileService {
309
+ async updateProfile(data) { /* ... */ }
310
+ async verifyEmail(token) { /* ... */ }
311
+ }
312
+
313
+ class NotificationService {
314
+ async sendWelcomeEmail(userId) { /* ... */ }
315
+ }
316
+ ```
317
+
318
+ ### Signs You Need to Split
319
+
320
+ | Symptom | Solution |
321
+ |---------|----------|
322
+ | Service > 500 lines | Split by domain |
323
+ | > 10 dependencies | Extract sub-services |
324
+ | Circular dependencies | Restructure or use events |
325
+ | Hard to test | Smaller, focused services |
326
+
327
+ ### Microservices vs Monolith
328
+
329
+ | Factor | Stay Monolith | Consider Microservices |
330
+ |--------|---------------|------------------------|
331
+ | Team size | < 10 developers | > 20 developers |
332
+ | Deployment | Single deploy OK | Need independent deploys |
333
+ | Scale | Uniform scaling | Different scaling needs |
334
+ | Data | Shared database OK | Need data isolation |
335
+ | Complexity | Keep simple | Worth the overhead |
336
+
337
+ ---
338
+
339
+ ## 6. Data Access Patterns
340
+
341
+ ### Repository per Aggregate
342
+
343
+ ```typescript
344
+ // Good: One repository per aggregate root
345
+ OrderRepository // Manages Order + OrderItems
346
+ UserRepository // Manages User + UserSettings
347
+ ProductRepository // Manages Product + ProductVariants
348
+ ```
349
+
350
+ ### Avoid: Repository per Table
351
+
352
+ ```typescript
353
+ // Avoid: Too granular, leads to anemic domain model
354
+ OrderRepository
355
+ OrderItemRepository // Should be part of OrderRepository
356
+ OrderStatusRepository // Probably doesn't need its own repo
357
+ ```
358
+
359
+ ### When to Use Raw Queries
360
+
361
+ ```typescript
362
+ // Use repository methods for most cases
363
+ const orders = await orderRepo.find({ where: { userId } });
364
+
365
+ // Use raw queries for:
366
+ // 1. Complex aggregations
367
+ const stats = await db.execute(sql`
368
+ SELECT category, COUNT(*), AVG(price)
369
+ FROM products
370
+ GROUP BY category
371
+ `);
372
+
373
+ // 2. Performance-critical paths
374
+ const results = await db.execute(sql`
375
+ SELECT * FROM products
376
+ WHERE tsv @@ plainto_tsquery(${search})
377
+ LIMIT 10
378
+ `);
379
+
380
+ // 3. Database-specific features
381
+ const nearby = await db.execute(sql`
382
+ SELECT * FROM stores
383
+ WHERE ST_DWithin(location, ${point}, 5000)
384
+ `);
385
+ ```
386
+
387
+ ---
388
+
389
+ ## 7. Configuration Strategy
390
+
391
+ ### Environment Variables
392
+
393
+ ```typescript
394
+ // Use for: secrets, environment-specific values
395
+ const config = {
396
+ database: {
397
+ host: EnvHelper.get('APP_ENV_POSTGRES_HOST'),
398
+ password: EnvHelper.get('APP_ENV_POSTGRES_PASSWORD'),
399
+ },
400
+ stripe: {
401
+ secretKey: EnvHelper.get('STRIPE_SECRET_KEY'),
402
+ },
403
+ };
404
+ ```
405
+
406
+ ### Application Config
407
+
408
+ ```typescript
409
+ // Use for: application defaults, feature flags
410
+ const appConfig = {
411
+ pagination: {
412
+ defaultLimit: 20,
413
+ maxLimit: 100,
414
+ },
415
+ features: {
416
+ enableBetaFeatures: process.env.NODE_ENV !== 'production',
417
+ },
418
+ };
419
+ ```
420
+
421
+ ### Component Config
422
+
423
+ ```typescript
424
+ // Use for: component-specific settings
425
+ this.component(SwaggerComponent, {
426
+ title: 'My API',
427
+ version: '1.0.0',
428
+ path: '/doc',
429
+ });
430
+ ```
431
+
432
+ ---
433
+
434
+ ## 8. Testing Strategy
435
+
436
+ ### What to Test at Each Layer
437
+
438
+ | Layer | Test Type | Focus |
439
+ |-------|-----------|-------|
440
+ | **Controller** | Integration | HTTP, validation, response format |
441
+ | **Service** | Unit | Business logic, edge cases |
442
+ | **Repository** | Integration | Queries, data integrity |
443
+ | **Component** | Unit | Configuration, lifecycle |
444
+
445
+ ### Test Pyramid
446
+
447
+ ```
448
+ /\
449
+ / \ E2E (few)
450
+ /----\
451
+ / \ Integration (some)
452
+ /--------\
453
+ / \ Unit (many)
454
+ --------------
455
+ ```
456
+
457
+ ---
458
+
459
+ ## Quick Reference
460
+
461
+ ### Checklist for New Features
462
+
463
+ 1. **[ ] Is it cross-cutting?** → Component
464
+ 2. **[ ] Has business logic?** → Service
465
+ 3. **[ ] Simple CRUD?** → Repository directly
466
+ 4. **[ ] Reusable query?** → Custom repository method
467
+ 5. **[ ] Complex validation?** → Service layer
468
+ 6. **[ ] External API?** → Service with error handling
469
+ 7. **[ ] Needs transactions?** → Service orchestrating repos
470
+
471
+ ### Common Mistakes to Avoid
472
+
473
+ | Mistake | Better Approach |
474
+ |---------|-----------------|
475
+ | Fat controllers | Move logic to services |
476
+ | Anemic services | Add business logic, not just pass-through |
477
+ | Repository per table | Repository per aggregate |
478
+ | Catching all errors | Let appropriate errors bubble |
479
+ | Premature optimization | Start simple, optimize when needed |
480
+ | Over-engineering | YAGNI - build what you need now |
481
+
482
+ ---
483
+
484
+ ## See Also
485
+
486
+ - [Architectural Patterns](./architectural-patterns.md) - Layered architecture details
487
+ - [Core Concepts](../guides/core-concepts/application/) - Framework fundamentals
488
+ - [Performance Optimization](./performance-optimization.md) - Scaling techniques