@su-record/vibe 2.0.0 → 2.0.2

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 (69) hide show
  1. package/.claude/agents/explorer.md +48 -48
  2. package/.claude/agents/implementer.md +53 -53
  3. package/.claude/agents/searcher.md +54 -54
  4. package/.claude/agents/simplifier.md +119 -119
  5. package/.claude/agents/tester.md +49 -49
  6. package/.claude/commands/vibe.analyze.md +239 -239
  7. package/.claude/commands/vibe.continue.md +88 -88
  8. package/.claude/commands/vibe.diagram.md +178 -178
  9. package/.claude/commands/vibe.reason.md +306 -306
  10. package/.claude/commands/vibe.run.md +760 -760
  11. package/.claude/commands/vibe.spec.md +339 -339
  12. package/.claude/commands/vibe.tool.md +153 -153
  13. package/.claude/commands/vibe.ui.md +137 -137
  14. package/.claude/commands/vibe.verify.md +238 -238
  15. package/.claude/settings.json +152 -152
  16. package/.claude/settings.local.json +4 -57
  17. package/.vibe/config.json +9 -0
  18. package/.vibe/constitution.md +184 -184
  19. package/.vibe/rules/core/communication-guide.md +104 -104
  20. package/.vibe/rules/core/development-philosophy.md +52 -52
  21. package/.vibe/rules/core/quick-start.md +120 -120
  22. package/.vibe/rules/quality/bdd-contract-testing.md +388 -388
  23. package/.vibe/rules/quality/checklist.md +276 -276
  24. package/.vibe/rules/quality/testing-strategy.md +437 -437
  25. package/.vibe/rules/standards/anti-patterns.md +369 -369
  26. package/.vibe/rules/standards/code-structure.md +291 -291
  27. package/.vibe/rules/standards/complexity-metrics.md +312 -312
  28. package/.vibe/rules/standards/naming-conventions.md +198 -198
  29. package/.vibe/rules/tools/mcp-hi-ai-guide.md +665 -665
  30. package/.vibe/rules/tools/mcp-workflow.md +51 -51
  31. package/.vibe/setup.sh +31 -31
  32. package/CLAUDE.md +122 -122
  33. package/LICENSE +21 -21
  34. package/README.md +568 -568
  35. package/dist/cli/index.d.ts.map +1 -1
  36. package/dist/cli/index.js +391 -406
  37. package/dist/cli/index.js.map +1 -1
  38. package/dist/lib/MemoryManager.js +92 -92
  39. package/dist/lib/PythonParser.js +108 -108
  40. package/dist/lib/gemini-mcp.js +15 -15
  41. package/dist/lib/gemini-oauth.d.ts.map +1 -1
  42. package/dist/lib/gemini-oauth.js +41 -38
  43. package/dist/lib/gemini-oauth.js.map +1 -1
  44. package/dist/lib/gpt-mcp.js +17 -17
  45. package/dist/lib/gpt-oauth.d.ts.map +1 -1
  46. package/dist/lib/gpt-oauth.js +50 -45
  47. package/dist/lib/gpt-oauth.js.map +1 -1
  48. package/dist/tools/analytics/getUsageAnalytics.js +12 -12
  49. package/dist/tools/memory/createMemoryTimeline.js +10 -10
  50. package/dist/tools/memory/getMemoryGraph.js +12 -12
  51. package/dist/tools/memory/getSessionContext.js +9 -9
  52. package/dist/tools/memory/linkMemories.js +14 -14
  53. package/dist/tools/memory/listMemories.js +4 -4
  54. package/dist/tools/memory/recallMemory.js +4 -4
  55. package/dist/tools/memory/saveMemory.js +4 -4
  56. package/dist/tools/memory/searchMemoriesAdvanced.js +22 -22
  57. package/dist/tools/planning/generatePrd.js +46 -46
  58. package/dist/tools/prompt/enhancePromptGemini.js +160 -160
  59. package/dist/tools/reasoning/applyReasoningFramework.js +56 -56
  60. package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
  61. package/package.json +67 -67
  62. package/templates/constitution-template.md +184 -184
  63. package/templates/contract-backend-template.md +517 -517
  64. package/templates/contract-frontend-template.md +594 -594
  65. package/templates/feature-template.md +96 -96
  66. package/templates/hooks-template.json +103 -103
  67. package/templates/spec-template.md +199 -199
  68. package/dist/lib/vibe-mcp.d.ts.map +0 -1
  69. package/dist/lib/vibe-mcp.js.map +0 -1
@@ -1,312 +1,312 @@
1
- # 🔬 소프트웨어 엔지니어링 복잡도 측정
2
-
3
- ## 4.1 복잡도 메트릭
4
-
5
- ### Cyclomatic Complexity (순환 복잡도)
6
-
7
- **정의**: 코드의 독립적인 실행 경로 수
8
-
9
- **목표**: ≤ 10
10
-
11
- ```typescript
12
- // ❌ 높은 순환 복잡도 (6)
13
- function processUser(user) {
14
- if (user.isActive) { // +1
15
- if (user.hasPermission) { // +1
16
- if (user.email) { // +1
17
- if (user.verified) { // +1
18
- return processData();
19
- }
20
- }
21
- }
22
- }
23
- return null;
24
- }
25
-
26
- // ✅ 낮은 순환 복잡도 (4) - Early returns 사용
27
- function processUser(user) {
28
- if (!user.isActive) return null; // +1
29
- if (!user.hasPermission) return null; // +1
30
- if (!user.email) return null; // +1
31
- if (!user.verified) return null; // +1
32
-
33
- return processData();
34
- }
35
- ```
36
-
37
- ### Cognitive Complexity (인지 복잡도)
38
-
39
- **정의**: 코드를 이해하는 데 필요한 정신적 노력
40
-
41
- **목표**: ≤ 15
42
-
43
- ```typescript
44
- // ❌ 높은 인지 복잡도
45
- function calculateDiscount(user, items) {
46
- let discount = 0;
47
- if (user.isPremium) { // +1
48
- for (let item of items) { // +1 (nesting)
49
- if (item.category === 'electronics') { // +2 (nested if)
50
- discount += item.price * 0.1;
51
- } else if (item.category === 'books') { // +1
52
- discount += item.price * 0.05;
53
- }
54
- }
55
- }
56
- return discount;
57
- }
58
-
59
- // ✅ 낮은 인지 복잡도 - 함수 분리
60
- function calculateDiscount(user, items) {
61
- if (!user.isPremium) return 0; // +1
62
- return items.reduce((total, item) => total + getItemDiscount(item), 0);
63
- }
64
-
65
- function getItemDiscount(item) {
66
- const discountRates = {
67
- electronics: 0.1,
68
- books: 0.05,
69
- };
70
- return item.price * (discountRates[item.category] || 0);
71
- }
72
- ```
73
-
74
- ### Halstead Metrics (할스테드 메트릭)
75
-
76
- **측정 항목**:
77
- - **Operators**: 연산자 (=, +, -, *, if, for 등)
78
- - **Operands**: 피연산자 (변수, 상수, 함수명)
79
- - **Vocabulary**: 고유 연산자 + 고유 피연산자
80
- - **Length**: 전체 토큰 수
81
- - **Difficulty**: 코드 이해 난이도
82
- - **Effort**: 코드 작성에 필요한 정신적 노력
83
-
84
- ```typescript
85
- // Halstead 메트릭 측정 예시
86
- function calculateArea(radius: number): number {
87
- const pi = 3.14159;
88
- return pi * radius * radius;
89
- }
90
-
91
- /*
92
- Operators: =, *, const, function, :, return (6개)
93
- Operands: calculateArea, radius, number, pi, 3.14159 (5개)
94
- Vocabulary: 6 + 5 = 11
95
- Length: 전체 토큰 수
96
- Difficulty: Vocabulary와 operand 반복으로 계산
97
- Effort: Difficulty × Volume
98
- */
99
- ```
100
-
101
- ## 4.2 결합도 & 응집도
102
-
103
- ### 느슨한 결합 (Loose Coupling)
104
-
105
- **목표**: 모듈 간 의존성 최소화
106
-
107
- ```typescript
108
- // ❌ 강한 결합 - 직접 의존성
109
- class UserService {
110
- constructor() {
111
- this.database = new PostgreSQLDatabase(); // 직접 의존
112
- this.emailService = new SendGridEmail(); // 직접 의존
113
- }
114
- }
115
-
116
- // ✅ 느슨한 결합 - 의존성 주입
117
- interface IDatabase {
118
- save(data: unknown): Promise<void>;
119
- load(id: string): Promise<unknown>;
120
- }
121
-
122
- interface IEmailService {
123
- send(to: string, message: string): Promise<void>;
124
- }
125
-
126
- class UserService {
127
- constructor(
128
- private database: IDatabase,
129
- private emailService: IEmailService
130
- ) {}
131
- }
132
-
133
- // 사용
134
- const userService = new UserService(
135
- new PostgreSQLDatabase(),
136
- new SendGridEmail()
137
- );
138
- ```
139
-
140
- ### 높은 응집도 (High Cohesion)
141
-
142
- **목표**: 관련된 기능만 모음
143
-
144
- ```typescript
145
- // ❌ 낮은 응집도 - 관련 없는 기능들
146
- class Utils {
147
- validateEmail(email: string) { /* */ }
148
- formatCurrency(amount: number) { /* */ }
149
- sendNotification(message: string) { /* */ }
150
- calculateTax(income: number) { /* */ }
151
- }
152
-
153
- // ✅ 높은 응집도 - 관련 기능만
154
- class EmailValidator {
155
- validateFormat(email: string) { /* */ }
156
- validateDomain(email: string) { /* */ }
157
- validateMX(email: string) { /* */ }
158
- }
159
-
160
- class CurrencyFormatter {
161
- formatKRW(amount: number) { /* */ }
162
- formatUSD(amount: number) { /* */ }
163
- parseAmount(formatted: string) { /* */ }
164
- }
165
-
166
- class TaxCalculator {
167
- calculateIncomeTax(income: number) { /* */ }
168
- calculateVAT(amount: number) { /* */ }
169
- calculateTotal(income: number) { /* */ }
170
- }
171
- ```
172
-
173
- ## 복잡도 감소 전략
174
-
175
- ### 1. Early Return 패턴
176
-
177
- ```typescript
178
- // ❌ 중첩된 if문
179
- function processOrder(order: Order) {
180
- if (order) {
181
- if (order.isValid) {
182
- if (order.items.length > 0) {
183
- if (order.user.isActive) {
184
- return processItems(order.items);
185
- }
186
- }
187
- }
188
- }
189
- return null;
190
- }
191
-
192
- // ✅ Early return
193
- function processOrder(order: Order) {
194
- if (!order) return null;
195
- if (!order.isValid) return null;
196
- if (order.items.length === 0) return null;
197
- if (!order.user.isActive) return null;
198
-
199
- return processItems(order.items);
200
- }
201
- ```
202
-
203
- ### 2. 전략 패턴 (Strategy Pattern)
204
-
205
- ```typescript
206
- // ❌ 복잡한 if-else 체인
207
- function calculateShipping(type: string, weight: number) {
208
- if (type === 'express') {
209
- return weight * 5 + 10;
210
- } else if (type === 'standard') {
211
- return weight * 3 + 5;
212
- } else if (type === 'economy') {
213
- return weight * 2;
214
- }
215
- return 0;
216
- }
217
-
218
- // ✅ 전략 패턴
219
- interface ShippingStrategy {
220
- calculate(weight: number): number;
221
- }
222
-
223
- class ExpressShipping implements ShippingStrategy {
224
- calculate(weight: number) {
225
- return weight * 5 + 10;
226
- }
227
- }
228
-
229
- class StandardShipping implements ShippingStrategy {
230
- calculate(weight: number) {
231
- return weight * 3 + 5;
232
- }
233
- }
234
-
235
- const strategies: Record<string, ShippingStrategy> = {
236
- express: new ExpressShipping(),
237
- standard: new StandardShipping(),
238
- };
239
-
240
- function calculateShipping(type: string, weight: number) {
241
- const strategy = strategies[type];
242
- return strategy ? strategy.calculate(weight) : 0;
243
- }
244
- ```
245
-
246
- ### 3. 함수 추출 (Extract Function)
247
-
248
- ```typescript
249
- // ❌ 긴 함수
250
- function processUserRegistration(userData: UserData) {
251
- // 20줄: 이메일 검증
252
- // 15줄: 비밀번호 해싱
253
- // 10줄: 데이터베이스 저장
254
- // 5줄: 환영 이메일 발송
255
- }
256
-
257
- // ✅ 함수 추출
258
- function processUserRegistration(userData: UserData) {
259
- validateEmail(userData.email);
260
- const hashedPassword = hashPassword(userData.password);
261
- const user = saveToDatabase({ ...userData, password: hashedPassword });
262
- sendWelcomeEmail(user.email);
263
- return user;
264
- }
265
-
266
- function validateEmail(email: string) { /* ... */ }
267
- function hashPassword(password: string) { /* ... */ }
268
- function saveToDatabase(data: UserData) { /* ... */ }
269
- function sendWelcomeEmail(email: string) { /* ... */ }
270
- ```
271
-
272
- ## 측정 도구
273
-
274
- ### TypeScript/JavaScript
275
-
276
- ```bash
277
- # ESLint (복잡도 측정 플러그인)
278
- npm install eslint-plugin-complexity
279
-
280
- # .eslintrc.js
281
- {
282
- "rules": {
283
- "complexity": ["error", 10],
284
- "max-depth": ["error", 3],
285
- "max-lines-per-function": ["error", 20]
286
- }
287
- }
288
- ```
289
-
290
- ### Python
291
-
292
- ```bash
293
- # Radon (복잡도 측정 도구)
294
- pip install radon
295
-
296
- # Cyclomatic Complexity
297
- radon cc app/ -a -nc
298
-
299
- # Maintainability Index
300
- radon mi app/
301
- ```
302
-
303
- ## 목표 메트릭 요약
304
-
305
- | 메트릭 | 목표 | 설명 |
306
- |--------|------|------|
307
- | Cyclomatic Complexity | ≤ 10 | 독립적 실행 경로 |
308
- | Cognitive Complexity | ≤ 15 | 이해하기 쉬움 |
309
- | Function Length | ≤ 20 lines | 짧고 집중된 함수 |
310
- | Nesting Depth | ≤ 3 levels | 평탄한 구조 |
311
- | Parameters | ≤ 5 | 함수 매개변수 제한 |
312
- | Dependencies | ≤ 7 | 모듈 의존성 제한 |
1
+ # 🔬 소프트웨어 엔지니어링 복잡도 측정
2
+
3
+ ## 4.1 복잡도 메트릭
4
+
5
+ ### Cyclomatic Complexity (순환 복잡도)
6
+
7
+ **정의**: 코드의 독립적인 실행 경로 수
8
+
9
+ **목표**: ≤ 10
10
+
11
+ ```typescript
12
+ // ❌ 높은 순환 복잡도 (6)
13
+ function processUser(user) {
14
+ if (user.isActive) { // +1
15
+ if (user.hasPermission) { // +1
16
+ if (user.email) { // +1
17
+ if (user.verified) { // +1
18
+ return processData();
19
+ }
20
+ }
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+
26
+ // ✅ 낮은 순환 복잡도 (4) - Early returns 사용
27
+ function processUser(user) {
28
+ if (!user.isActive) return null; // +1
29
+ if (!user.hasPermission) return null; // +1
30
+ if (!user.email) return null; // +1
31
+ if (!user.verified) return null; // +1
32
+
33
+ return processData();
34
+ }
35
+ ```
36
+
37
+ ### Cognitive Complexity (인지 복잡도)
38
+
39
+ **정의**: 코드를 이해하는 데 필요한 정신적 노력
40
+
41
+ **목표**: ≤ 15
42
+
43
+ ```typescript
44
+ // ❌ 높은 인지 복잡도
45
+ function calculateDiscount(user, items) {
46
+ let discount = 0;
47
+ if (user.isPremium) { // +1
48
+ for (let item of items) { // +1 (nesting)
49
+ if (item.category === 'electronics') { // +2 (nested if)
50
+ discount += item.price * 0.1;
51
+ } else if (item.category === 'books') { // +1
52
+ discount += item.price * 0.05;
53
+ }
54
+ }
55
+ }
56
+ return discount;
57
+ }
58
+
59
+ // ✅ 낮은 인지 복잡도 - 함수 분리
60
+ function calculateDiscount(user, items) {
61
+ if (!user.isPremium) return 0; // +1
62
+ return items.reduce((total, item) => total + getItemDiscount(item), 0);
63
+ }
64
+
65
+ function getItemDiscount(item) {
66
+ const discountRates = {
67
+ electronics: 0.1,
68
+ books: 0.05,
69
+ };
70
+ return item.price * (discountRates[item.category] || 0);
71
+ }
72
+ ```
73
+
74
+ ### Halstead Metrics (할스테드 메트릭)
75
+
76
+ **측정 항목**:
77
+ - **Operators**: 연산자 (=, +, -, *, if, for 등)
78
+ - **Operands**: 피연산자 (변수, 상수, 함수명)
79
+ - **Vocabulary**: 고유 연산자 + 고유 피연산자
80
+ - **Length**: 전체 토큰 수
81
+ - **Difficulty**: 코드 이해 난이도
82
+ - **Effort**: 코드 작성에 필요한 정신적 노력
83
+
84
+ ```typescript
85
+ // Halstead 메트릭 측정 예시
86
+ function calculateArea(radius: number): number {
87
+ const pi = 3.14159;
88
+ return pi * radius * radius;
89
+ }
90
+
91
+ /*
92
+ Operators: =, *, const, function, :, return (6개)
93
+ Operands: calculateArea, radius, number, pi, 3.14159 (5개)
94
+ Vocabulary: 6 + 5 = 11
95
+ Length: 전체 토큰 수
96
+ Difficulty: Vocabulary와 operand 반복으로 계산
97
+ Effort: Difficulty × Volume
98
+ */
99
+ ```
100
+
101
+ ## 4.2 결합도 & 응집도
102
+
103
+ ### 느슨한 결합 (Loose Coupling)
104
+
105
+ **목표**: 모듈 간 의존성 최소화
106
+
107
+ ```typescript
108
+ // ❌ 강한 결합 - 직접 의존성
109
+ class UserService {
110
+ constructor() {
111
+ this.database = new PostgreSQLDatabase(); // 직접 의존
112
+ this.emailService = new SendGridEmail(); // 직접 의존
113
+ }
114
+ }
115
+
116
+ // ✅ 느슨한 결합 - 의존성 주입
117
+ interface IDatabase {
118
+ save(data: unknown): Promise<void>;
119
+ load(id: string): Promise<unknown>;
120
+ }
121
+
122
+ interface IEmailService {
123
+ send(to: string, message: string): Promise<void>;
124
+ }
125
+
126
+ class UserService {
127
+ constructor(
128
+ private database: IDatabase,
129
+ private emailService: IEmailService
130
+ ) {}
131
+ }
132
+
133
+ // 사용
134
+ const userService = new UserService(
135
+ new PostgreSQLDatabase(),
136
+ new SendGridEmail()
137
+ );
138
+ ```
139
+
140
+ ### 높은 응집도 (High Cohesion)
141
+
142
+ **목표**: 관련된 기능만 모음
143
+
144
+ ```typescript
145
+ // ❌ 낮은 응집도 - 관련 없는 기능들
146
+ class Utils {
147
+ validateEmail(email: string) { /* */ }
148
+ formatCurrency(amount: number) { /* */ }
149
+ sendNotification(message: string) { /* */ }
150
+ calculateTax(income: number) { /* */ }
151
+ }
152
+
153
+ // ✅ 높은 응집도 - 관련 기능만
154
+ class EmailValidator {
155
+ validateFormat(email: string) { /* */ }
156
+ validateDomain(email: string) { /* */ }
157
+ validateMX(email: string) { /* */ }
158
+ }
159
+
160
+ class CurrencyFormatter {
161
+ formatKRW(amount: number) { /* */ }
162
+ formatUSD(amount: number) { /* */ }
163
+ parseAmount(formatted: string) { /* */ }
164
+ }
165
+
166
+ class TaxCalculator {
167
+ calculateIncomeTax(income: number) { /* */ }
168
+ calculateVAT(amount: number) { /* */ }
169
+ calculateTotal(income: number) { /* */ }
170
+ }
171
+ ```
172
+
173
+ ## 복잡도 감소 전략
174
+
175
+ ### 1. Early Return 패턴
176
+
177
+ ```typescript
178
+ // ❌ 중첩된 if문
179
+ function processOrder(order: Order) {
180
+ if (order) {
181
+ if (order.isValid) {
182
+ if (order.items.length > 0) {
183
+ if (order.user.isActive) {
184
+ return processItems(order.items);
185
+ }
186
+ }
187
+ }
188
+ }
189
+ return null;
190
+ }
191
+
192
+ // ✅ Early return
193
+ function processOrder(order: Order) {
194
+ if (!order) return null;
195
+ if (!order.isValid) return null;
196
+ if (order.items.length === 0) return null;
197
+ if (!order.user.isActive) return null;
198
+
199
+ return processItems(order.items);
200
+ }
201
+ ```
202
+
203
+ ### 2. 전략 패턴 (Strategy Pattern)
204
+
205
+ ```typescript
206
+ // ❌ 복잡한 if-else 체인
207
+ function calculateShipping(type: string, weight: number) {
208
+ if (type === 'express') {
209
+ return weight * 5 + 10;
210
+ } else if (type === 'standard') {
211
+ return weight * 3 + 5;
212
+ } else if (type === 'economy') {
213
+ return weight * 2;
214
+ }
215
+ return 0;
216
+ }
217
+
218
+ // ✅ 전략 패턴
219
+ interface ShippingStrategy {
220
+ calculate(weight: number): number;
221
+ }
222
+
223
+ class ExpressShipping implements ShippingStrategy {
224
+ calculate(weight: number) {
225
+ return weight * 5 + 10;
226
+ }
227
+ }
228
+
229
+ class StandardShipping implements ShippingStrategy {
230
+ calculate(weight: number) {
231
+ return weight * 3 + 5;
232
+ }
233
+ }
234
+
235
+ const strategies: Record<string, ShippingStrategy> = {
236
+ express: new ExpressShipping(),
237
+ standard: new StandardShipping(),
238
+ };
239
+
240
+ function calculateShipping(type: string, weight: number) {
241
+ const strategy = strategies[type];
242
+ return strategy ? strategy.calculate(weight) : 0;
243
+ }
244
+ ```
245
+
246
+ ### 3. 함수 추출 (Extract Function)
247
+
248
+ ```typescript
249
+ // ❌ 긴 함수
250
+ function processUserRegistration(userData: UserData) {
251
+ // 20줄: 이메일 검증
252
+ // 15줄: 비밀번호 해싱
253
+ // 10줄: 데이터베이스 저장
254
+ // 5줄: 환영 이메일 발송
255
+ }
256
+
257
+ // ✅ 함수 추출
258
+ function processUserRegistration(userData: UserData) {
259
+ validateEmail(userData.email);
260
+ const hashedPassword = hashPassword(userData.password);
261
+ const user = saveToDatabase({ ...userData, password: hashedPassword });
262
+ sendWelcomeEmail(user.email);
263
+ return user;
264
+ }
265
+
266
+ function validateEmail(email: string) { /* ... */ }
267
+ function hashPassword(password: string) { /* ... */ }
268
+ function saveToDatabase(data: UserData) { /* ... */ }
269
+ function sendWelcomeEmail(email: string) { /* ... */ }
270
+ ```
271
+
272
+ ## 측정 도구
273
+
274
+ ### TypeScript/JavaScript
275
+
276
+ ```bash
277
+ # ESLint (복잡도 측정 플러그인)
278
+ npm install eslint-plugin-complexity
279
+
280
+ # .eslintrc.js
281
+ {
282
+ "rules": {
283
+ "complexity": ["error", 10],
284
+ "max-depth": ["error", 3],
285
+ "max-lines-per-function": ["error", 20]
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### Python
291
+
292
+ ```bash
293
+ # Radon (복잡도 측정 도구)
294
+ pip install radon
295
+
296
+ # Cyclomatic Complexity
297
+ radon cc app/ -a -nc
298
+
299
+ # Maintainability Index
300
+ radon mi app/
301
+ ```
302
+
303
+ ## 목표 메트릭 요약
304
+
305
+ | 메트릭 | 목표 | 설명 |
306
+ |--------|------|------|
307
+ | Cyclomatic Complexity | ≤ 10 | 독립적 실행 경로 |
308
+ | Cognitive Complexity | ≤ 15 | 이해하기 쉬움 |
309
+ | Function Length | ≤ 20 lines | 짧고 집중된 함수 |
310
+ | Nesting Depth | ≤ 3 levels | 평탄한 구조 |
311
+ | Parameters | ≤ 5 | 함수 매개변수 제한 |
312
+ | Dependencies | ≤ 7 | 모듈 의존성 제한 |