@su-record/vibe 2.0.0 โ 2.0.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.
- package/.claude/agents/explorer.md +48 -48
- package/.claude/agents/implementer.md +53 -53
- package/.claude/agents/searcher.md +54 -54
- package/.claude/agents/simplifier.md +119 -119
- package/.claude/agents/tester.md +49 -49
- package/.claude/commands/vibe.analyze.md +239 -239
- package/.claude/commands/vibe.continue.md +88 -88
- package/.claude/commands/vibe.diagram.md +178 -178
- package/.claude/commands/vibe.reason.md +306 -306
- package/.claude/commands/vibe.run.md +760 -760
- package/.claude/commands/vibe.spec.md +339 -339
- package/.claude/commands/vibe.tool.md +153 -153
- package/.claude/commands/vibe.ui.md +137 -137
- package/.claude/commands/vibe.verify.md +238 -238
- package/.claude/settings.json +152 -152
- package/.claude/settings.local.json +4 -57
- package/.vibe/config.json +9 -0
- package/.vibe/constitution.md +184 -184
- package/.vibe/rules/core/communication-guide.md +104 -104
- package/.vibe/rules/core/development-philosophy.md +52 -52
- package/.vibe/rules/core/quick-start.md +120 -120
- package/.vibe/rules/quality/bdd-contract-testing.md +388 -388
- package/.vibe/rules/quality/checklist.md +276 -276
- package/.vibe/rules/quality/testing-strategy.md +437 -437
- package/.vibe/rules/standards/anti-patterns.md +369 -369
- package/.vibe/rules/standards/code-structure.md +291 -291
- package/.vibe/rules/standards/complexity-metrics.md +312 -312
- package/.vibe/rules/standards/naming-conventions.md +198 -198
- package/.vibe/rules/tools/mcp-hi-ai-guide.md +665 -665
- package/.vibe/rules/tools/mcp-workflow.md +51 -51
- package/.vibe/setup.sh +31 -31
- package/CLAUDE.md +122 -122
- package/LICENSE +21 -21
- package/README.md +568 -568
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +391 -406
- package/dist/cli/index.js.map +1 -1
- package/dist/lib/MemoryManager.js +92 -92
- package/dist/lib/PythonParser.js +108 -108
- package/dist/lib/gemini-mcp.js +15 -15
- package/dist/lib/gemini-oauth.js +35 -35
- package/dist/lib/gpt-mcp.js +17 -17
- package/dist/lib/gpt-oauth.js +44 -44
- package/dist/tools/analytics/getUsageAnalytics.js +12 -12
- package/dist/tools/memory/createMemoryTimeline.js +10 -10
- package/dist/tools/memory/getMemoryGraph.js +12 -12
- package/dist/tools/memory/getSessionContext.js +9 -9
- package/dist/tools/memory/linkMemories.js +14 -14
- package/dist/tools/memory/listMemories.js +4 -4
- package/dist/tools/memory/recallMemory.js +4 -4
- package/dist/tools/memory/saveMemory.js +4 -4
- package/dist/tools/memory/searchMemoriesAdvanced.js +22 -22
- package/dist/tools/planning/generatePrd.js +46 -46
- package/dist/tools/prompt/enhancePromptGemini.js +160 -160
- package/dist/tools/reasoning/applyReasoningFramework.js +56 -56
- package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
- package/package.json +67 -67
- package/templates/constitution-template.md +184 -184
- package/templates/contract-backend-template.md +517 -517
- package/templates/contract-frontend-template.md +594 -594
- package/templates/feature-template.md +96 -96
- package/templates/hooks-template.json +103 -103
- package/templates/spec-template.md +199 -199
- package/dist/lib/vibe-mcp.d.ts.map +0 -1
- package/dist/lib/vibe-mcp.js.map +0 -1
|
@@ -1,291 +1,291 @@
|
|
|
1
|
-
# ๐๏ธ ์ฝ๋ ๊ตฌ์กฐ ์๋ํ ๊ท์น
|
|
2
|
-
|
|
3
|
-
## ์ปดํฌ๋ํธ ๊ตฌ์กฐ (์๊ฒฉํ ์์)
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
// 1. Import ๋ฌธ
|
|
7
|
-
import React, { useState, useEffect } from 'react';
|
|
8
|
-
|
|
9
|
-
// 2. ํ์
/์ธํฐํ์ด์ค ์ ์
|
|
10
|
-
interface Props {
|
|
11
|
-
userId: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 3. ์ปดํฌ๋ํธ ์ ์
|
|
15
|
-
function UserProfile({ userId }: Props) {
|
|
16
|
-
// 4. State & Refs
|
|
17
|
-
const [user, setUser] = useState<User | null>(null);
|
|
18
|
-
const inputRef = useRef<HTMLInputElement>(null);
|
|
19
|
-
|
|
20
|
-
// 5. Custom Hooks
|
|
21
|
-
const { isAuthenticated } = useAuth();
|
|
22
|
-
const { data, loading } = useUserData(userId);
|
|
23
|
-
|
|
24
|
-
// 6. Event Handlers
|
|
25
|
-
const handleSubmit = (e: FormEvent) => {
|
|
26
|
-
e.preventDefault();
|
|
27
|
-
// ...
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// 7. Effects
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
// ...
|
|
33
|
-
}, [userId]);
|
|
34
|
-
|
|
35
|
-
// 8. Early returns
|
|
36
|
-
if (loading) return <Spinner />;
|
|
37
|
-
if (!user) return <NotFound />;
|
|
38
|
-
|
|
39
|
-
// 9. Main return JSX
|
|
40
|
-
return (
|
|
41
|
-
<div>
|
|
42
|
-
{/* ... */}
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## ํจ์ ๋ถ๋ฆฌ ๊ธฐ์ค
|
|
49
|
-
|
|
50
|
-
### 1. ํจ์ ๊ธธ์ด ๊ธฐ์ค
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
// โ 20์ค ์ด๊ณผ - ๋ถ๋ฆฌ ํ์
|
|
54
|
-
function processUserData(user: User) {
|
|
55
|
-
// 30์ค์ ๋ณต์กํ ๋ก์ง
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// โ
๋จ์ผ ์ฑ
์์ผ๋ก ๋ถ๋ฆฌ
|
|
59
|
-
function processUserData(user: User) {
|
|
60
|
-
const validated = validateUser(user);
|
|
61
|
-
const transformed = transformUserData(validated);
|
|
62
|
-
return saveUserData(transformed);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function validateUser(user: User) { /* ... */ }
|
|
66
|
-
function transformUserData(user: User) { /* ... */ }
|
|
67
|
-
function saveUserData(user: User) { /* ... */ }
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. ์ปดํฌ๋ํธ JSX ๊ธธ์ด ๊ธฐ์ค
|
|
71
|
-
|
|
72
|
-
```typescript
|
|
73
|
-
// โ JSX 50์ค ์ด๊ณผ - ๋ถ๋ฆฌ ํ์
|
|
74
|
-
function Dashboard() {
|
|
75
|
-
return (
|
|
76
|
-
<div>
|
|
77
|
-
{/* 60์ค์ ๋ณต์กํ JSX */}
|
|
78
|
-
</div>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// โ
์๋ธ ์ปดํฌ๋ํธ ์ถ์ถ
|
|
83
|
-
function Dashboard() {
|
|
84
|
-
return (
|
|
85
|
-
<div>
|
|
86
|
-
<DashboardHeader />
|
|
87
|
-
<DashboardContent />
|
|
88
|
-
<DashboardFooter />
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function DashboardHeader() { /* ... */ }
|
|
94
|
-
function DashboardContent() { /* ... */ }
|
|
95
|
-
function DashboardFooter() { /* ... */ }
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### 3. ์ค์ฒฉ ๊น์ด ๊ธฐ์ค
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
// โ ์ค์ฒฉ 3๋จ๊ณ ์ด๊ณผ
|
|
102
|
-
function processData(data: Data) {
|
|
103
|
-
if (data) {
|
|
104
|
-
if (data.isValid) {
|
|
105
|
-
if (data.user) {
|
|
106
|
-
if (data.user.isActive) {
|
|
107
|
-
// ๋๋ฌด ๊น์ ์ค์ฒฉ
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// โ
Early return์ผ๋ก ํํํ
|
|
115
|
-
function processData(data: Data) {
|
|
116
|
-
if (!data) return null;
|
|
117
|
-
if (!data.isValid) return null;
|
|
118
|
-
if (!data.user) return null;
|
|
119
|
-
if (!data.user.isActive) return null;
|
|
120
|
-
|
|
121
|
-
// ๋ก์ง ์คํ
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### 4. Cyclomatic Complexity > 10
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
// โ ๋ณต์ก๋ ๋์ (15)
|
|
129
|
-
function calculatePrice(item: Item) {
|
|
130
|
-
let price = item.basePrice;
|
|
131
|
-
if (item.discount) price *= 0.9;
|
|
132
|
-
if (item.bulk) price *= 0.8;
|
|
133
|
-
if (item.seasonal) price *= 0.95;
|
|
134
|
-
if (item.member) price *= 0.85;
|
|
135
|
-
if (item.firstTime) price *= 0.9;
|
|
136
|
-
// ... ๋ ๋ง์ ์กฐ๊ฑด
|
|
137
|
-
return price;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// โ
๋ณต์ก๋ ๊ฐ์ (3)
|
|
141
|
-
function calculatePrice(item: Item) {
|
|
142
|
-
const basePrice = item.basePrice;
|
|
143
|
-
const discounts = getApplicableDiscounts(item);
|
|
144
|
-
return applyDiscounts(basePrice, discounts);
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### 5. Cognitive Complexity > 15
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
// โ ์ธ์ง ๋ณต์ก๋ ๋์
|
|
152
|
-
function processOrder(order: Order) {
|
|
153
|
-
if (order.isPremium) {
|
|
154
|
-
for (let item of order.items) {
|
|
155
|
-
if (item.category === 'electronics') {
|
|
156
|
-
if (item.price > 1000) {
|
|
157
|
-
// ์ค์ฒฉ๋ ๋ณต์กํ ๋ก์ง
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// โ
์ธ์ง ๋ณต์ก๋ ๊ฐ์
|
|
165
|
-
function processOrder(order: Order) {
|
|
166
|
-
if (!order.isPremium) return;
|
|
167
|
-
|
|
168
|
-
const electronics = filterElectronics(order.items);
|
|
169
|
-
const expensive = filterExpensive(electronics);
|
|
170
|
-
|
|
171
|
-
processItems(expensive);
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## ํ์ผ ๊ตฌ์กฐ ํ์ค
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
// ๐ user-profile.component.tsx
|
|
179
|
-
|
|
180
|
-
// 1. Imports
|
|
181
|
-
import { ... } from 'react';
|
|
182
|
-
import { ... } from '@/lib';
|
|
183
|
-
|
|
184
|
-
// 2. Types
|
|
185
|
-
interface UserProfileProps { }
|
|
186
|
-
type UserRole = 'admin' | 'user';
|
|
187
|
-
|
|
188
|
-
// 3. Constants
|
|
189
|
-
const MAX_BIO_LENGTH = 500;
|
|
190
|
-
const DEFAULT_AVATAR = '/avatar.png';
|
|
191
|
-
|
|
192
|
-
// 4. Helper Functions (๋ด๋ถ ์ ์ฉ)
|
|
193
|
-
function formatUserName(name: string) { }
|
|
194
|
-
|
|
195
|
-
// 5. Main Component
|
|
196
|
-
export function UserProfile() { }
|
|
197
|
-
|
|
198
|
-
// 6. Sub Components (exportํ์ง ์์)
|
|
199
|
-
function ProfileHeader() { }
|
|
200
|
-
function ProfileContent() { }
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## ๋ชจ๋ ๊ตฌ์ฑ ์์น
|
|
204
|
-
|
|
205
|
-
### 1. ์์ง๋ (Cohesion)
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
// โ
๋์ ์์ง๋ - ๊ด๋ จ ๊ธฐ๋ฅ๋ง ๋ชจ์
|
|
209
|
-
// ๐ user.service.ts
|
|
210
|
-
export class UserService {
|
|
211
|
-
getUser(id: string) { }
|
|
212
|
-
updateUser(id: string, data: User) { }
|
|
213
|
-
deleteUser(id: string) { }
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// โ ๋ฎ์ ์์ง๋ - ๊ด๋ จ ์๋ ๊ธฐ๋ฅ ํผ์ฌ
|
|
217
|
-
// ๐ utils.ts (์ํฐํจํด)
|
|
218
|
-
export class Utils {
|
|
219
|
-
validateEmail(email: string) { }
|
|
220
|
-
formatCurrency(amount: number) { }
|
|
221
|
-
uploadFile(file: File) { }
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### 2. ๊ฒฐํฉ๋ (Coupling)
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
// โ
๋์จํ ๊ฒฐํฉ - ์ธํฐํ์ด์ค ์์กด
|
|
229
|
-
interface Storage {
|
|
230
|
-
save(key: string, value: unknown): void;
|
|
231
|
-
load(key: string): unknown;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
class UserService {
|
|
235
|
-
constructor(private storage: Storage) { }
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// โ ๊ฐํ ๊ฒฐํฉ - ๊ตฌํ์ฒด ์ง์ ์์กด
|
|
239
|
-
class UserService {
|
|
240
|
-
private storage = new LocalStorage(); // ์ง์ ์์กด
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
## ํจ์ ๋งค๊ฐ๋ณ์ ์ ํ
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
// โ ๋งค๊ฐ๋ณ์ 5๊ฐ ์ด๊ณผ
|
|
248
|
-
function createUser(
|
|
249
|
-
name: string,
|
|
250
|
-
email: string,
|
|
251
|
-
age: number,
|
|
252
|
-
address: string,
|
|
253
|
-
phone: string,
|
|
254
|
-
role: string
|
|
255
|
-
) { }
|
|
256
|
-
|
|
257
|
-
// โ
๊ฐ์ฒด๋ก ๊ทธ๋ฃนํ
|
|
258
|
-
interface CreateUserParams {
|
|
259
|
-
name: string;
|
|
260
|
-
email: string;
|
|
261
|
-
age: number;
|
|
262
|
-
address: string;
|
|
263
|
-
phone: string;
|
|
264
|
-
role: string;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function createUser(params: CreateUserParams) { }
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## ์ํ ์์กด์ฑ ๋ฐฉ์ง
|
|
271
|
-
|
|
272
|
-
```typescript
|
|
273
|
-
// โ ์ํ ์์กด์ฑ
|
|
274
|
-
// fileA.ts
|
|
275
|
-
import { funcB } from './fileB';
|
|
276
|
-
export function funcA() { funcB(); }
|
|
277
|
-
|
|
278
|
-
// fileB.ts
|
|
279
|
-
import { funcA } from './fileA'; // ์ํ!
|
|
280
|
-
export function funcB() { funcA(); }
|
|
281
|
-
|
|
282
|
-
// โ
๊ณตํต ๋ชจ๋ ๋ถ๋ฆฌ
|
|
283
|
-
// shared.ts
|
|
284
|
-
export function sharedFunc() { }
|
|
285
|
-
|
|
286
|
-
// fileA.ts
|
|
287
|
-
import { sharedFunc } from './shared';
|
|
288
|
-
|
|
289
|
-
// fileB.ts
|
|
290
|
-
import { sharedFunc } from './shared';
|
|
291
|
-
```
|
|
1
|
+
# ๐๏ธ ์ฝ๋ ๊ตฌ์กฐ ์๋ํ ๊ท์น
|
|
2
|
+
|
|
3
|
+
## ์ปดํฌ๋ํธ ๊ตฌ์กฐ (์๊ฒฉํ ์์)
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// 1. Import ๋ฌธ
|
|
7
|
+
import React, { useState, useEffect } from 'react';
|
|
8
|
+
|
|
9
|
+
// 2. ํ์
/์ธํฐํ์ด์ค ์ ์
|
|
10
|
+
interface Props {
|
|
11
|
+
userId: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 3. ์ปดํฌ๋ํธ ์ ์
|
|
15
|
+
function UserProfile({ userId }: Props) {
|
|
16
|
+
// 4. State & Refs
|
|
17
|
+
const [user, setUser] = useState<User | null>(null);
|
|
18
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
19
|
+
|
|
20
|
+
// 5. Custom Hooks
|
|
21
|
+
const { isAuthenticated } = useAuth();
|
|
22
|
+
const { data, loading } = useUserData(userId);
|
|
23
|
+
|
|
24
|
+
// 6. Event Handlers
|
|
25
|
+
const handleSubmit = (e: FormEvent) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
// ...
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// 7. Effects
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
// ...
|
|
33
|
+
}, [userId]);
|
|
34
|
+
|
|
35
|
+
// 8. Early returns
|
|
36
|
+
if (loading) return <Spinner />;
|
|
37
|
+
if (!user) return <NotFound />;
|
|
38
|
+
|
|
39
|
+
// 9. Main return JSX
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
{/* ... */}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## ํจ์ ๋ถ๋ฆฌ ๊ธฐ์ค
|
|
49
|
+
|
|
50
|
+
### 1. ํจ์ ๊ธธ์ด ๊ธฐ์ค
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// โ 20์ค ์ด๊ณผ - ๋ถ๋ฆฌ ํ์
|
|
54
|
+
function processUserData(user: User) {
|
|
55
|
+
// 30์ค์ ๋ณต์กํ ๋ก์ง
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// โ
๋จ์ผ ์ฑ
์์ผ๋ก ๋ถ๋ฆฌ
|
|
59
|
+
function processUserData(user: User) {
|
|
60
|
+
const validated = validateUser(user);
|
|
61
|
+
const transformed = transformUserData(validated);
|
|
62
|
+
return saveUserData(transformed);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function validateUser(user: User) { /* ... */ }
|
|
66
|
+
function transformUserData(user: User) { /* ... */ }
|
|
67
|
+
function saveUserData(user: User) { /* ... */ }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2. ์ปดํฌ๋ํธ JSX ๊ธธ์ด ๊ธฐ์ค
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// โ JSX 50์ค ์ด๊ณผ - ๋ถ๋ฆฌ ํ์
|
|
74
|
+
function Dashboard() {
|
|
75
|
+
return (
|
|
76
|
+
<div>
|
|
77
|
+
{/* 60์ค์ ๋ณต์กํ JSX */}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// โ
์๋ธ ์ปดํฌ๋ํธ ์ถ์ถ
|
|
83
|
+
function Dashboard() {
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<DashboardHeader />
|
|
87
|
+
<DashboardContent />
|
|
88
|
+
<DashboardFooter />
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function DashboardHeader() { /* ... */ }
|
|
94
|
+
function DashboardContent() { /* ... */ }
|
|
95
|
+
function DashboardFooter() { /* ... */ }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3. ์ค์ฒฉ ๊น์ด ๊ธฐ์ค
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// โ ์ค์ฒฉ 3๋จ๊ณ ์ด๊ณผ
|
|
102
|
+
function processData(data: Data) {
|
|
103
|
+
if (data) {
|
|
104
|
+
if (data.isValid) {
|
|
105
|
+
if (data.user) {
|
|
106
|
+
if (data.user.isActive) {
|
|
107
|
+
// ๋๋ฌด ๊น์ ์ค์ฒฉ
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// โ
Early return์ผ๋ก ํํํ
|
|
115
|
+
function processData(data: Data) {
|
|
116
|
+
if (!data) return null;
|
|
117
|
+
if (!data.isValid) return null;
|
|
118
|
+
if (!data.user) return null;
|
|
119
|
+
if (!data.user.isActive) return null;
|
|
120
|
+
|
|
121
|
+
// ๋ก์ง ์คํ
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4. Cyclomatic Complexity > 10
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// โ ๋ณต์ก๋ ๋์ (15)
|
|
129
|
+
function calculatePrice(item: Item) {
|
|
130
|
+
let price = item.basePrice;
|
|
131
|
+
if (item.discount) price *= 0.9;
|
|
132
|
+
if (item.bulk) price *= 0.8;
|
|
133
|
+
if (item.seasonal) price *= 0.95;
|
|
134
|
+
if (item.member) price *= 0.85;
|
|
135
|
+
if (item.firstTime) price *= 0.9;
|
|
136
|
+
// ... ๋ ๋ง์ ์กฐ๊ฑด
|
|
137
|
+
return price;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// โ
๋ณต์ก๋ ๊ฐ์ (3)
|
|
141
|
+
function calculatePrice(item: Item) {
|
|
142
|
+
const basePrice = item.basePrice;
|
|
143
|
+
const discounts = getApplicableDiscounts(item);
|
|
144
|
+
return applyDiscounts(basePrice, discounts);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 5. Cognitive Complexity > 15
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// โ ์ธ์ง ๋ณต์ก๋ ๋์
|
|
152
|
+
function processOrder(order: Order) {
|
|
153
|
+
if (order.isPremium) {
|
|
154
|
+
for (let item of order.items) {
|
|
155
|
+
if (item.category === 'electronics') {
|
|
156
|
+
if (item.price > 1000) {
|
|
157
|
+
// ์ค์ฒฉ๋ ๋ณต์กํ ๋ก์ง
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// โ
์ธ์ง ๋ณต์ก๋ ๊ฐ์
|
|
165
|
+
function processOrder(order: Order) {
|
|
166
|
+
if (!order.isPremium) return;
|
|
167
|
+
|
|
168
|
+
const electronics = filterElectronics(order.items);
|
|
169
|
+
const expensive = filterExpensive(electronics);
|
|
170
|
+
|
|
171
|
+
processItems(expensive);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## ํ์ผ ๊ตฌ์กฐ ํ์ค
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// ๐ user-profile.component.tsx
|
|
179
|
+
|
|
180
|
+
// 1. Imports
|
|
181
|
+
import { ... } from 'react';
|
|
182
|
+
import { ... } from '@/lib';
|
|
183
|
+
|
|
184
|
+
// 2. Types
|
|
185
|
+
interface UserProfileProps { }
|
|
186
|
+
type UserRole = 'admin' | 'user';
|
|
187
|
+
|
|
188
|
+
// 3. Constants
|
|
189
|
+
const MAX_BIO_LENGTH = 500;
|
|
190
|
+
const DEFAULT_AVATAR = '/avatar.png';
|
|
191
|
+
|
|
192
|
+
// 4. Helper Functions (๋ด๋ถ ์ ์ฉ)
|
|
193
|
+
function formatUserName(name: string) { }
|
|
194
|
+
|
|
195
|
+
// 5. Main Component
|
|
196
|
+
export function UserProfile() { }
|
|
197
|
+
|
|
198
|
+
// 6. Sub Components (exportํ์ง ์์)
|
|
199
|
+
function ProfileHeader() { }
|
|
200
|
+
function ProfileContent() { }
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## ๋ชจ๋ ๊ตฌ์ฑ ์์น
|
|
204
|
+
|
|
205
|
+
### 1. ์์ง๋ (Cohesion)
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// โ
๋์ ์์ง๋ - ๊ด๋ จ ๊ธฐ๋ฅ๋ง ๋ชจ์
|
|
209
|
+
// ๐ user.service.ts
|
|
210
|
+
export class UserService {
|
|
211
|
+
getUser(id: string) { }
|
|
212
|
+
updateUser(id: string, data: User) { }
|
|
213
|
+
deleteUser(id: string) { }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// โ ๋ฎ์ ์์ง๋ - ๊ด๋ จ ์๋ ๊ธฐ๋ฅ ํผ์ฌ
|
|
217
|
+
// ๐ utils.ts (์ํฐํจํด)
|
|
218
|
+
export class Utils {
|
|
219
|
+
validateEmail(email: string) { }
|
|
220
|
+
formatCurrency(amount: number) { }
|
|
221
|
+
uploadFile(file: File) { }
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 2. ๊ฒฐํฉ๋ (Coupling)
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// โ
๋์จํ ๊ฒฐํฉ - ์ธํฐํ์ด์ค ์์กด
|
|
229
|
+
interface Storage {
|
|
230
|
+
save(key: string, value: unknown): void;
|
|
231
|
+
load(key: string): unknown;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
class UserService {
|
|
235
|
+
constructor(private storage: Storage) { }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// โ ๊ฐํ ๊ฒฐํฉ - ๊ตฌํ์ฒด ์ง์ ์์กด
|
|
239
|
+
class UserService {
|
|
240
|
+
private storage = new LocalStorage(); // ์ง์ ์์กด
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## ํจ์ ๋งค๊ฐ๋ณ์ ์ ํ
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
// โ ๋งค๊ฐ๋ณ์ 5๊ฐ ์ด๊ณผ
|
|
248
|
+
function createUser(
|
|
249
|
+
name: string,
|
|
250
|
+
email: string,
|
|
251
|
+
age: number,
|
|
252
|
+
address: string,
|
|
253
|
+
phone: string,
|
|
254
|
+
role: string
|
|
255
|
+
) { }
|
|
256
|
+
|
|
257
|
+
// โ
๊ฐ์ฒด๋ก ๊ทธ๋ฃนํ
|
|
258
|
+
interface CreateUserParams {
|
|
259
|
+
name: string;
|
|
260
|
+
email: string;
|
|
261
|
+
age: number;
|
|
262
|
+
address: string;
|
|
263
|
+
phone: string;
|
|
264
|
+
role: string;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function createUser(params: CreateUserParams) { }
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## ์ํ ์์กด์ฑ ๋ฐฉ์ง
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// โ ์ํ ์์กด์ฑ
|
|
274
|
+
// fileA.ts
|
|
275
|
+
import { funcB } from './fileB';
|
|
276
|
+
export function funcA() { funcB(); }
|
|
277
|
+
|
|
278
|
+
// fileB.ts
|
|
279
|
+
import { funcA } from './fileA'; // ์ํ!
|
|
280
|
+
export function funcB() { funcA(); }
|
|
281
|
+
|
|
282
|
+
// โ
๊ณตํต ๋ชจ๋ ๋ถ๋ฆฌ
|
|
283
|
+
// shared.ts
|
|
284
|
+
export function sharedFunc() { }
|
|
285
|
+
|
|
286
|
+
// fileA.ts
|
|
287
|
+
import { sharedFunc } from './shared';
|
|
288
|
+
|
|
289
|
+
// fileB.ts
|
|
290
|
+
import { sharedFunc } from './shared';
|
|
291
|
+
```
|