[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -1,85 +1,235 @@
|
||||
---
|
||||
id: wiki-2026-0508-dry-principle
|
||||
title: Dry Principle
|
||||
title: DRY Principle (Don't Repeat Yourself)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AI-DRY]
|
||||
aliases: [DRY, Don't Repeat Yourself, single source of truth, WET, AHA]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.98
|
||||
tags: [SoftwareEngineering, Principles, DRY, CleanCode]
|
||||
verification_status: applied
|
||||
tags: [software-engineering, principles, dry, clean-code, abstraction, refactoring]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
language: Universal
|
||||
applicable_to: [Code, Schema, Config, Documentation]
|
||||
---
|
||||
|
||||
# [[Dry-Principle]] (Don't Repeat Yourself)
|
||||
# DRY Principle
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> "중복은 모든 악의 근원이다." 시스템 내부의 모든 지식은 단 한 번만, 단 하나의 명확한 형태로 존재해야 한다는 원칙이다.
|
||||
## 매 한 줄
|
||||
> **"매 every piece of knowledge 의 single, unambiguous, authoritative representation"**. Hunt & Thomas (Pragmatic Programmer). 매 duplication = 매 update bug. 매 modern caveat: 매 AHA (Avoid Hasty Abstraction) — 매 too-early DRY 의 wrong abstraction. 매 rule: 매 3rd repetition 의 abstract.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **Core [[goal]]**: 유지보수성 향상. 기능을 수정할 때 여러 곳을 고쳐야 한다면 반드시 실수하게 되어 있다.
|
||||
- **Beyond Code**: 단순히 '복사-붙여넣기' 코드를 줄이는 것뿐만 아니라, DB 스키마, 테스트 케이스, 문서화 등 프로젝트 전반의 정보 중복을 제거하는 것을 포함한다.
|
||||
- **Mechanisms**: 함수화, 클래스화, 모듈화, 상수 관리 등을 통해 구현한다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- DRY를 맹신하면 '성급한 추상화(Premature Abstraction)'에 빠지게 된다. 모양만 같고 '의미(Semantics)'가 다른 두 코드를 억지로 합치면, 나중에 각자의 비즈니스 로직이 달라질 때 코드가 꼬여버린다. 이럴 때는 차라리 중복을 허용하는 'WET(Write Everything Twice)'가 나을 수도 있다.
|
||||
### 매 origin
|
||||
- Hunt & Thomas, Pragmatic Programmer (1999).
|
||||
- 매 "knowledge" 의 emphasize — 매 code line 의 X.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- Related: Clean-Code , [[Modular-Programming]]
|
||||
- Contrast: YAGNI-Principle
|
||||
### 매 vs WET / AHA
|
||||
- **WET**: Write Everything Twice / We Enjoy Typing.
|
||||
- **AHA**: Avoid Hasty Abstraction (Sandi Metz).
|
||||
- **Rule of 3**: 매 3 repetition 의 abstract.
|
||||
- **Quote**: "Duplication is far cheaper than the wrong abstraction." — Sandi Metz.
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 매 type of duplication
|
||||
- **Imposed**: 매 environment 의 force.
|
||||
- **Inadvertent**: 매 unaware.
|
||||
- **Impatient**: 매 deadline.
|
||||
- **Interdeveloper**: 매 communication 의 X.
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
### 매 응용
|
||||
1. **Constants**: 매 magic number 의 named.
|
||||
2. **Functions**: 매 logic 의 extract.
|
||||
3. **Templates / generics**: 매 type 의 abstract.
|
||||
4. **Schema**: 매 single source.
|
||||
5. **Config**: 매 env-specific override.
|
||||
6. **Doc**: 매 generate from code.
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
### 매 modern context
|
||||
- **Microservices**: 매 service 의 own data → 매 controlled duplication.
|
||||
- **CQRS**: 매 read / write model 의 separate.
|
||||
- **Type-driven**: 매 schema 의 source.
|
||||
- **Codegen**: 매 OpenAPI → client / server.
|
||||
- **LLM era**: 매 context-aware 의 inline 의 fine (token cost).
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
## 💻 패턴
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
### Extract function
|
||||
```python
|
||||
# 매 ❌ duplicated
|
||||
def order_total(items):
|
||||
total = 0
|
||||
for i in items: total += i.price * i.qty
|
||||
tax = total * 0.08
|
||||
return total + tax
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
def cart_total(cart):
|
||||
total = 0
|
||||
for i in cart: total += i.price * i.qty
|
||||
tax = total * 0.08
|
||||
return total + tax
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
# 매 ✅ DRY
|
||||
def calculate_total(items, tax_rate=0.08):
|
||||
subtotal = sum(i.price * i.qty for i in items)
|
||||
return subtotal * (1 + tax_rate)
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Single source of truth (schema)
|
||||
```typescript
|
||||
// 매 Zod schema → 매 type + 매 validation
|
||||
import { z } from 'zod';
|
||||
const UserSchema = z.object({ id: z.string(), email: z.string().email() });
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
// 매 runtime validation + compile-time type
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Config (env override)
|
||||
```typescript
|
||||
const config = {
|
||||
apiUrl: process.env.API_URL ?? 'http://localhost:3000',
|
||||
timeout: Number(process.env.TIMEOUT ?? 5000),
|
||||
};
|
||||
// 매 single config object, env-specific override
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### OpenAPI codegen
|
||||
```yaml
|
||||
# openapi.yaml — single source
|
||||
paths:
|
||||
/users/{id}: { get: { responses: { 200: { schema: { $ref: '#/User' } } } } }
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
# 매 → openapi-typescript / openapi-generator → client + server stubs + docs
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Database migration as code
|
||||
```typescript
|
||||
// 매 schema 의 ORM model 의 single source
|
||||
@Entity()
|
||||
class User {
|
||||
@PrimaryColumn() id: string;
|
||||
@Column({ unique: true }) email: string;
|
||||
}
|
||||
// 매 migration 의 generate from model
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Template (Mustache / Liquid)
|
||||
```handlebars
|
||||
{{!-- email-template.hbs --}}
|
||||
Hi {{user.name}}, your order #{{order.id}} ships {{order.shipDate}}.
|
||||
```
|
||||
|
||||
### Inheritance / mixin (cautious)
|
||||
```python
|
||||
class TimestampMixin:
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class User(Base, TimestampMixin): pass
|
||||
class Post(Base, TimestampMixin): pass
|
||||
```
|
||||
|
||||
### Decorator (cross-cutting)
|
||||
```python
|
||||
def retry(times=3):
|
||||
def decorator(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
for attempt in range(times):
|
||||
try: return func(*args, **kwargs)
|
||||
except: if attempt == times - 1: raise
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
@retry(times=3)
|
||||
def fetch_data(url): ...
|
||||
```
|
||||
|
||||
### AHA — when NOT to abstract
|
||||
```python
|
||||
# 매 ❌ premature abstraction
|
||||
class GenericResourceHandler:
|
||||
def __init__(self, kind, ...18 params...): ...
|
||||
|
||||
# 매 ✅ duplicate first, abstract later
|
||||
def handle_user(req): ...
|
||||
def handle_post(req): ...
|
||||
# 매 → 매 3rd similar handler 의 의 emerge 의 pattern 의 see → 매 then abstract
|
||||
```
|
||||
|
||||
### Detect duplication (PMD / jscpd)
|
||||
```bash
|
||||
# 매 jscpd
|
||||
npx jscpd --threshold 5 --reporters html src/
|
||||
# 매 reports clones >= 5 lines
|
||||
```
|
||||
|
||||
### Refactor — Pull Up Method
|
||||
```python
|
||||
# 매 before
|
||||
class Dog:
|
||||
def name(self): return self._name
|
||||
class Cat:
|
||||
def name(self): return self._name
|
||||
|
||||
# 매 after
|
||||
class Animal:
|
||||
def name(self): return self._name
|
||||
class Dog(Animal): pass
|
||||
class Cat(Animal): pass
|
||||
```
|
||||
|
||||
### Pragmatic limit (microservices)
|
||||
```python
|
||||
# 매 service A
|
||||
class UserDTO_A: id: str; email: str
|
||||
|
||||
# 매 service B (separate codebase)
|
||||
class UserDTO_B: id: str; email: str
|
||||
|
||||
# 매 ✅ controlled duplication — 매 services 의 independent deploy
|
||||
# 매 ❌ shared library 의 coupling 의 anti-pattern
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | DRY Rule |
|
||||
|---|---|
|
||||
| 2nd occurrence | Wait |
|
||||
| 3rd occurrence | Extract |
|
||||
| Cross-service | Controlled duplicate |
|
||||
| Schema | Single source + codegen |
|
||||
| Config | Env-override |
|
||||
| Wrong abstraction | Inline first |
|
||||
|
||||
**기본값**: 매 rule of 3 + 매 AHA (avoid hasty abstraction) + 매 wrong abstraction > duplication.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Software-Engineering-Principles]] · [[Clean-Code]]
|
||||
- 변형: [[AHA]] · [[Rule-of-Three]] · [[Single-Source-of-Truth]]
|
||||
- 응용: [[Refactoring]] · [[Codegen]] · [[Schema-Driven]]
|
||||
- Adjacent: [[SOLID]] · [[YAGNI]] · [[KISS]] · [[Conventional-Commits]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 refactor. 매 abstraction decision. 매 code review.
|
||||
**언제 X**: 매 < 3 occurrence. 매 cross-domain.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Premature DRY**: 매 wrong abstraction → 매 update 의 cascade.
|
||||
- **Inheritance abuse**: 매 IS-A 의 X 의 force.
|
||||
- **Cross-service shared lib**: 매 deploy coupling.
|
||||
- **DRY at all cost**: 매 readability < deduplication.
|
||||
- **Magic abstraction**: 매 reader 의 confuse.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Pragmatic Programmer, Sandi Metz).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-04-20 | Auto-reinforced |
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — DRY + AHA + 매 extract / Zod / OpenAPI / detect / refactor code |
|
||||
|
||||
Reference in New Issue
Block a user