|
⇤ ← Revision 1 as of 2025-12-29 20:28:27
Size: 29548
Comment:
|
Size: 29042
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 855: | Line 855: |
| === Core Foundation === '''LanguageBuilding''' - 이름은 언어의 단어다. 좋은 이름이 모여 좋은 언어를 만든다. ''필수 관계'' '''MetaphorThinking''' - 은유와 비유가 직관적인 이름을 만든다. 이름을 통해 은유를 표현한다. ''인지적 도구'' '''TwoWorlds''' - 문제 공간과 해결 공간을 모두 잘 표현하는 이름. 도메인 언어 vs 기술 언어. ''두 종류의 이름'' '''DataAsFoundation''' - 데이터 구조의 이름이 전체 설계의 기반. 좋은 데이터 이름이 좋은 설계를 만든다. ''기반'' === Design Process === '''WorkingFirst''' - 완벽한 이름부터 찾지 마라. 작동하는 코드를 먼저 만들고 이름은 점진적으로 개선. ''과정'' '''OrganicGrowth''' - 이름도 유기적으로 진화한다. 이해가 깊어지면 이름도 개선된다. ''진화'' '''LivingVocabulary''' - 어휘는 살아있고 성장한다. 이름도 프로젝트와 함께 발전한다. ''지속적 개선'' === Code Quality === '''ComplexityTaming''' - 좋은 이름이 복잡성을 줄인다. 명확한 이름이 이해를 돕는다. ''단순화 도구'' '''ArtisanMind''' - 이름 짓기는 예술이다. 직관과 감각이 필요하다. ''장인 정신'' '''DirectPath''' - 좋은 이름이 코드의 흐름을 명확하게 만든다. ''명확성'' === Team Collaboration === '''SharedMind''' - 공유된 어휘가 팀 협업을 만든다. 같은 이름으로 같은 개념을 이야기한다. ''공통 언어'' '''TechnicalCommunity''' - 일관된 네이밍 컨벤션이 커뮤니티를 만든다. ''규약'' |
'''[[LanguageBuilding]]''' - 이름은 언어의 단어다. 좋은 이름이 모여 좋은 언어를 만든다. ''필수 관계'' '''[[MetaphorThinking]]''' - 은유와 비유가 직관적인 이름을 만든다. 이름을 통해 은유를 표현한다. ''인지적 도구'' '''[[TwoWorlds]]''' - 문제 공간과 해결 공간을 모두 잘 표현하는 이름. 도메인 언어 vs 기술 언어. ''두 종류의 이름'' '''[[DataAsFoundation]]''' - 데이터 구조의 이름이 전체 설계의 기반. 좋은 데이터 이름이 좋은 설계를 만든다. ''기반'' '''[[WorkingFirst]]''' - 완벽한 이름부터 찾지 마라. 작동하는 코드를 먼저 만들고 이름은 점진적으로 다듬어라. ''순서'' '''[[LivingVocabulary]]''' - 이름은 고정된 것이 아니라 이해가 깊어짐에 따라 진화한다. ''성장'' '''[[ArtisanMind]]''' - 이름을 짓는 것은 대표적인 '감각적' 활동이다. 논리보다 뉘앙스가 중요하다. ''기예'' '''[[PatternHunting]]''' - 반복되는 구조를 발견하면 그에 걸맞은 이름을 붙여 패턴으로 박제하라. ''도구'' |
NamesAsDesign
주니어 개발자들을 위한 패턴 언어 - 네이밍을 설계 활동으로 다루어 개념을 명확히 하는 방법
Contents
The Story: The Search for the Right Name
주니어 개발자 수진은 주문 처리 시스템을 작성하고 있었다. 그녀는 변수 이름을 짓다가 막혔다.
def process(data):
x = data['items']
y = 0
for i in x:
y += i['price'] * i['qty']
return y"이건 너무 못생겼어..." 수진은 생각했다. 30분 동안 고민한 끝에:
def calculate_order_total_amount_including_all_items(order_data):
list_of_order_items = order_data['items']
total_amount_to_be_paid = 0
for individual_item in list_of_order_items:
total_amount_to_be_paid += individual_item['price'] * individual_item['qty']
return total_amount_to_be_paid"더 명확해졌어!" 하지만 코드 리뷰에서:
시니어 개발자 민호가 말했다. "수진, 이건 오히려 더 읽기 어려워. 이름이 너무 길고, 중복이 많아."
"하지만 명확하게 하려고..."
"명확함은 길이가 아니라 문맥에서 나와. 봐봐:"
def total(order):
return sum(item.price * item.quantity for item in order.items)"짧네요! 하지만 무엇의 total인지 어떻게 알아요?"
민호가 더 큰 코드를 보여주었다:
class Order:
def total(self):
return sum(item.subtotal() for item in self.items)
class Item:
def subtotal(self):
return self.price * self.quantity
# 사용할 때
order = Order(...)
payment.charge(order.total())"봐, order.total()이라고 쓰면 Order의 total이라는 게 명확해. 문맥이 이름을 완성하는 거야. 그리고 Item.subtotal()은 Item의 소계라는 게 바로 보이지?"
수진의 눈이 커졌다. "아... 이름은 혼자 존재하는 게 아니라 관계 속에서 의미를 갖는 거군요!"
"정확해. 이름 짓기는 단순히 라벨을 붙이는 게 아니야. 그것은 설계 활동이야. 좋은 이름은 좋은 설계를 반영해."
Context
당신은 코드를 작성하면서 변수, 함수, 클래스, 모듈에 이름을 붙여야 한다. 이름은 코드의 모든 곳에 있고, 코드를 읽는 사람(미래의 자신을 포함해서)이 가장 먼저 보는 것이다.
당신은 LanguageBuilding을 통해 도메인 언어를 만드는 것의 중요성을 알고, MetaphorThinking을 통해 은유가 이해를 돕는다는 것을 안다. 이제 그 언어를 구성하는 단어 하나하나를 만드는 단계다.
일상적인 상황:
변수 이름을 data, temp, x 같은 일반적 이름으로 짓는다
함수 이름을 너무 길게 만든다 (calculateOrderTotalAmountIncludingTax)
같은 개념을 여러 이름으로 부른다 (user / customer / account)
- 이름을 짓는 데 과도한 시간을 쓰거나, 거의 생각 없이 짓는다
Problem
초보 프로그래머는 네이밍을 단순한 라벨링으로 취급한다. 어떤 이는 너무 빨리 못생긴 이름을 붙이고, 어떤 이는 오래 고민하지만 결과는 여전히 좋지 않다.
The Naming Dichotomy
주니어는 두 극단 사이를 오간다:
너무 빠른 네이밍
def f(x):
y = x['a']
z = 0
for i in y:
z += i['b'] * i['c']
return z- 빠르지만 의미 없음
- 1주일 후 자신도 이해 못 함
- "코드가 스스로 말한다"는 원칙 위반
너무 긴 네이밍
def calculate_total_amount_of_order_including_all_line_items_with_quantities():
list_of_all_items_in_current_order = ...- 명확하려 했지만 장황함
- 읽기 어려움
- 중복 정보 (order의 total이면 당연히 items 포함)
The Fundamental Misunderstanding
Phil Karlton이 말했다: "There are only two hard things in Computer Science: cache invalidation and naming things."
왜 네이밍이 어려운가? 많은 프로그래머가 착각한다:
잘못된 믿음:
- "좋은 이름은 그 자체로 명확해야 한다"
- "이름만 보고 모든 것을 알 수 있어야 한다"
- "길고 자세할수록 좋다"
진실:
이름 자체로는 좋고 나쁨을 판단할 수 없다
문맥에 embedding되었을 때 평가할 수 있다
관계 속에서 의미가 만들어진다
The Isolation Problem
주니어는 이름을 고립되어 생각한다:
# 이 이름이 좋은가? calculate_total() # 판단 불가능! 문맥이 없다.
하지만 이름은 관계망 속에 존재한다:
# 같은 이름, 다른 평가
class Order:
def calculate_total(self): # ❌ 너무 장황
...
# vs
class Order:
def total(self): # ✅ 문맥상 명확
...
# 사용할 때:
order.total() # "Order의 total" - 명확!이름의 품질은:
부모와의 관계 (Order.total - Order가 문맥 제공)
형제와의 관계 (total, subtotal, tax - 일관된 어휘)
자식과의 관계 (함수 내부가 이름과 일치하는지)
The Surface of Design
더 깊은 문제: 이름은 설계의 표면이다.
나쁜 이름은 종종 나쁜 설계를 반영한다:
# 이름 짓기 어렵다면...
def process_user_data_and_send_email_and_update_database(user):
# 이 함수는 너무 많은 일을 한다!
# 이름의 문제가 아니라 설계의 문제
...좋은 이름을 찾기 어렵다는 것은:
- 개념이 불명확하다는 신호
- 책임이 잘못 분배되었다는 신호
- 추상화가 잘못되었다는 신호
네이밍 문제 = 설계 문제
Name as Concept
이름은 단순한 라벨이 아니다. 이름은 개념 그 자체다.
# 같은 것, 다른 개념화 items = [...] # 단순 리스트 shopping_cart = [...] # 쇼핑 맥락 pending_orders = [...] # 주문 맥락
이름을 바꾸면 생각이 바뀐다:
data → user : 추상적 데이터에서 구체적 사용자로
process() → authenticate() : 무엇을 하는지 명확해짐
flag → is_valid : boolean의 의미가 명확해짐
좋은 이름을 짓는다 = 잘 개념화한다
Names vs Documentation
좋은 이름은 주석보다 가치있다:
# ❌ 나쁜 이름 + 좋은 주석
# 사용자의 나이가 18세 이상인지 확인
def check(u):
return u['age'] >= 18
# ✅ 좋은 이름, 주석 불필요
def is_adult(user):
return user.age >= LEGAL_AGEWard Cunningham이 말했다: "Clean code is when each function does pretty much what you expected."
예상을 만드는 것이 바로 이름이다.
Solution
네이밍을 사고를 명확하게 하고 추상화를 드러내는 설계 활동으로 다뤄라. 좋은 이름은 문맥 속에서 평가되고, 관계 속에서 의미를 갖는다. 이름은 개념이고, 좋은 이름은 좋은 설계를 반영한다.
Principle 1: Names in Context (Embedding)
이름은 고립되어 평가할 수 없다. 문맥에 embedding하여 평가하라.
Small Context (함수 내부)
# ❌ 문맥 무시
def calculate_total(list_of_order_items):
total_amount = 0
for individual_order_item in list_of_order_items:
total_amount += individual_order_item['price']
return total_amount
# ✅ 문맥 활용
def calculate_total(items):
total = 0
for item in items:
total += item.price
return total
# ✅✅ 더 나은 문맥
def calculate_total(items):
return sum(item.price for item in items)짧은 스코프에서는 짧은 이름이 명확하다. 문맥이 이미 충분한 정보를 제공하기 때문이다.
Large Context (클래스, 모듈)
# 클래스 문맥
class Order:
def total(self): # "Order의 total"
...
def subtotal(self): # "Order의 subtotal"
...
def tax(self): # "Order의 tax"
...
# 사용할 때 문맥이 의미를 만든다
order.total() # 무엇의 total인지 명확
order.subtotal() # Order의 subtotal
order.tax() # Order의 tax클래스/모듈 이름이 문맥을 제공한다. 메서드 이름은 그 문맥에서 평가된다.
Principle 2: Relational Quality (Playing Along)
좋은 이름은 "잘 어울린다" - 형제, 부모, 자식과 조화롭게.
Siblings (형제 관계)
같은 레벨의 이름들은 일관된 패턴을 따라야 한다:
# ❌ 형제들이 안 어울림
class User:
def get_name(self): # get_
...
def fetchAge(self): # fetch (카멜케이스)
...
def email(self): # 그냥 명사
...
# ✅ 형제들이 잘 어울림
class User:
def name(self):
...
def age(self):
...
def email(self):
...일관성이 예측 가능성을 만든다.
Parent-Child (부모-자식 관계)
부모(클래스)와 자식(메서드)이 조화로워야 한다:
# ❌ 중복
class OrderCalculator:
def calculate_order_total(self): # Order가 두 번
...
# ✅ 조화
class Order:
def total(self): # Order + total = "주문의 합계"
...
class Calculator:
def calculate(self): # Calculator + calculate = 자연스러움
...
Principle 3: Two Spaces - Problem and Solution
TwoWorlds를 기억하라. 좋은 이름은 문제 공간과 해결 공간을 모두 잘 표현한다.
Problem Space Names (도메인 언어)
# 비즈니스 도메인의 이름
class Order:
def place(self): # 도메인 용어
...
def ship(self):
...
def cancel(self):
...
class Customer:
def purchase(self):
...도메인 전문가와 대화할 때 사용하는 단어들이 코드에 그대로 있어야 한다. Ubiquitous Language (Eric Evans, DDD).
Solution Space Names (기술 언어)
# 기술적 구현의 이름
class OrderRepository:
def save(self):
...
def find_by_id(self):
...
class EventBus:
def publish(self):
...
def subscribe(self):
...기술적 패턴과 메커니즘은 기술 용어로.
Principle 4: Name as Concept (Conceptualization)
이름 짓기는 개념화하기다. 명확한 이름 = 명확한 개념.
Discovery Through Naming
이름을 찾는 과정은 개념을 발견하는 과정이다:
# 진화 과정 data # 너무 일반적 - 개념 불명확 user_data # 조금 나아짐 - 사용자와 관련 profile # 더 구체적 - 프로필이라는 개념 발견 user_profile # 명확 - 사용자의 프로필
이름이 명확해지는 과정 = 개념이 명확해지는 과정.
Boolean Names
Boolean은 질문으로 이름 지어라:
# ❌ 애매함 flag = True status = False # ✅ 명확한 질문 is_valid = True has_permission = False can_edit = True should_retry = False
is_, has_, can_, should_ 접두사가 의도를 명확히 한다.
Principle 5: Names > Documentation
좋은 이름은 주석을 불필요하게 만든다.
# ❌ 주석 의존
# 사용자가 성인인지 확인
def check(u):
return u['a'] >= 18
# ✅ 자체 문서화
def is_adult(user):
return user.age >= LEGAL_ADULT_AGERobert C. Martin이 말했다: "The proper use of comments is to compensate for our failure to express ourselves in code."
이름으로 표현하지 못해서 주석을 쓴다. 좋은 이름은 주석을 불필요하게 만든다.
Principle 6: Metaphor and Analogy
MetaphorThinking - 좋은 은유는 좋은 이름을 만든다.
# 은유 활용
class Stack: # "쌓다" - 물리적 은유
def push(item): # 밀어넣다
def pop(): # 꺼내다
class Queue: # "줄" - 물리적 은유
def enqueue(item): # 줄에 서다
def dequeue(): # 줄에서 나가다
class Stream: # "흐름" - 물리적 은유
def read():
def write():
def flush(): # 흘려보내다은유가 직관적 이해를 만든다.
Principle 7: Semantic Network
LanguageBuilding - 이름들은 의미 네트워크를 형성한다.
# 의미적으로 연결된 이름들
class Order:
def total(self): # 전체
return self.subtotal() + self.tax()
def subtotal(self): # 부분 합계
return sum(item.subtotal() for item in self.items)
def tax(self): # 세금
return self.subtotal() * self.tax_rate
class Item:
def subtotal(self): # 항목의 소계
return self.price * self.quantitytotal, subtotal, tax - 이 단어들은 서로 관계를 형성한다. 하나를 보면 다른 것을 예상할 수 있다.
Real Examples
Example 1: From Generic to Specific
진화 과정:
# V1: 일반적
def process(data):
result = []
for item in data:
result.append(item * 2)
return result
# V2: 조금 나아짐
def process_numbers(numbers):
doubled = []
for num in numbers:
doubled.append(num * 2)
return doubled
# V3: 명확한 의도
def double_prices(prices):
return [price * 2 for price in prices]
# V4: 도메인 언어
def apply_inflation(prices, rate=2.0):
return [price * rate for price in prices]각 단계마다 개념이 명확해진다.
Example 2: Context Makes Meaning
같은 이름, 다른 문맥:
# 문맥 1: 파일 시스템
class File:
def size(self): # 파일 크기
return self.bytes
# 문맥 2: 의류
class Shirt:
def size(self): # 옷 사이즈
return self.size_label # "M", "L"
# 문맥 3: 컬렉션
class List:
def size(self): # 원소 개수
return len(self.items)size() 자체로는 애매하지만, 문맥이 의미를 만든다.
Example 3: Siblings Harmony
일관성 있는 형제들:
# ✅ CRUD 패턴
class UserRepository:
def create(user):
...
def read(user_id):
...
def update(user):
...
def delete(user_id):
...
# ✅ Validation 패턴
class Validator:
def is_valid_email(email):
...
def is_valid_password(password):
...
def is_valid_username(username):
...
Example 4: Real Naming Session
실제 리팩토링 과정:
# 원본 코드
def func(x, y):
z = []
for i in x:
if i > y:
z.append(i)
return z
# 1차: 의미 추가
def filter_data(data, threshold):
result = []
for item in data:
if item > threshold:
result.append(item)
return result
# 2차: 도메인 언어
def filter_scores(scores, passing_grade):
passing_scores = []
for score in scores:
if score >= passing_grade:
passing_scores.append(score)
return passing_scores
# 3차: 개념 명확화
def find_passing_students(scores, passing_grade=60):
return [score for score in scores if score >= passing_grade]
# 최종: 더 나은 추상화
class GradeBook:
def passing_students(self, cutoff=60):
return [s for s in self.scores if s.grade >= cutoff]이름이 진화하면서 설계도 진화했다.
Example 5: Metaphor Power
은유가 만드는 직관:
# Factory 패턴 - "공장"
class UserFactory:
def create(): # 공장에서 만든다
...
# Builder 패턴 - "건축가"
class QueryBuilder:
def select(): # 선택
...
def where(): # 조건
...
def build(): # 건축 - 최종 완성
...
# Observer 패턴 - "관찰자"
class Subject:
def attach(observer): # 관찰자를 붙인다
...
def detach(observer): # 관찰자를 떼어낸다
...
def notify(): # 관찰자에게 알린다
...은유가 패턴을 이해 가능하게 만든다.
Example 6: Names Reveal Design Issues
이름이 설계 문제를 드러낸다:
# ❌ 이름 짓기 어렵다 = 설계 문제
class UserManagerControllerHandlerService:
def process_user_data_and_send_email_and_log():
# 이 클래스는 무엇을 하는가?
# 이 함수는 너무 많은 일을 한다!
...
# ✅ 이름이 쉬워지면 = 설계 개선됨
class UserRegistration:
def register(self, user):
self._validate(user)
self._save(user)
self._send_welcome_email(user)
class EmailService:
def send_welcome(user):
...
class UserRepository:
def save(user):
...좋은 이름을 짓기 어렵다면, 설계를 다시 보라.
The Naming Process
Process 1: Start Concrete, Then Abstract
일반적인 것부터 시작하지 마라. 구체적인 것부터 시작하라.
# ❌ 너무 추상적부터 data → processed_data → result # ✅ 구체적부터 시작 prices → doubled_prices → inflated_prices
Process 2: Let Context Emerge
이름을 먼저 짓지 말고, 사용하면서 이름을 발견하라.
# WorkingFirst와 연결
# 1. 일단 작동하게 (임시 이름)
def calc(x):
return x * 1.1
# 2. 사용해보기
result = calc(price) # "price를 calc?" - 어색함
# 3. 더 나은 이름 발견
result = apply_tax(price) # 자연스러움!사용 문맥이 좋은 이름을 제안한다.
Process 3: Refactor Names
이름도 리팩토링 대상이다:
# 이해가 깊어지면 이름도 변한다 data # 초기: 뭔지 모름 user_data # 사용자 데이터라는 것 발견 preferences # 실제로는 선호도 settings # 더 정확하게는 설정
LivingVocabulary - 어휘는 진화한다.
Process 4: Read Aloud Test
이름을 소리내어 읽어보라:
# 읽어보기 order.calculate_total_amount() # "Order야, calculate total amount 해줘" # 어색함! order.total() # "Order의 total" # 자연스러움!
Process 5: Consistency Check
비슷한 개념은 비슷한 패턴으로:
# ✅ 일관된 패턴 user.is_active() user.is_admin() user.is_verified() # ❌ 비일관적 user.is_active() user.check_if_admin() user.verified()
Common Pitfalls
Pitfall 1: Premature Long Names
명확하려다 장황해진다:
# ❌ 지나침
def calculateTotalAmountOfOrderIncludingTaxAndShipping():
...
# ✅ 문맥 활용
class Order:
def total_with_tax_and_shipping(self):
...
# 또는 더 간단히
def total(self):
return self.subtotal() + self.tax() + self.shipping()
Pitfall 2: Abbreviations
약어는 이해를 방해한다:
# ❌ 약어 남용
def proc_usr_ord(u, o):
...
# ✅ 명확한 이름
def process_user_order(user, order):
...
# 예외: 보편적 약어는 OK
http_request # HTTP는 보편적
html_parser # HTML도 OK
id, url, api # 이들도 충분히 명확
Pitfall 3: Inconsistent Vocabulary
같은 개념을 다른 이름으로:
# ❌ 혼란
class User:
...
class CustomerManager:
...
class ClientService:
...
# User? Customer? Client? 같은 건가 다른 건가?
# ✅ 일관성
class User:
...
class UserManager:
...
class UserService:
...Ubiquitous Language - 하나의 개념은 하나의 이름으로.
Pitfall 4: Type in Name
타입 정보를 이름에 넣는다:
# ❌ Hungarian notation strUserName = "John" intUserAge = 30 arrUserOrders = [] # ✅ 의미에 집중 name = "John" age = 30 orders = []
타입은 타입 시스템이 말하게 하라. 이름은 의미에 집중.
Pitfall 5: Noise Words
의미 없는 단어들:
# ❌ 소음 class UserManager: # Manager가 뭘 하는지 불명확 class DataProcessor: # Processor가 뭘 하는지 불명확 class InfoHolder: # Holder가 무슨 의미? # ✅ 구체적 class UserAuthenticator: class OrderValidator: class ConfigurationStore:
Manager, Processor, Handler, Data, Info - 이들은 종종 의미가 없다.
Pitfall 6: Naming in Isolation
문맥 없이 이름을 평가한다:
# "get()이 좋은 이름인가?" # → 판단 불가능! # 문맥 제공: user.get() # ❌ 무엇을 get? user.email() # ✅ 명확 request.get() # ✅ HTTP GET (문맥상 명확)
항상 문맥에서 평가하라.
Connection to Other Patterns
LanguageBuilding - 이름은 언어의 단어다. 좋은 이름이 모여 좋은 언어를 만든다. 필수 관계
MetaphorThinking - 은유와 비유가 직관적인 이름을 만든다. 이름을 통해 은유를 표현한다. 인지적 도구
TwoWorlds - 문제 공간과 해결 공간을 모두 잘 표현하는 이름. 도메인 언어 vs 기술 언어. 두 종류의 이름
DataAsFoundation - 데이터 구조의 이름이 전체 설계의 기반. 좋은 데이터 이름이 좋은 설계를 만든다. 기반
WorkingFirst - 완벽한 이름부터 찾지 마라. 작동하는 코드를 먼저 만들고 이름은 점진적으로 다듬어라. 순서
LivingVocabulary - 이름은 고정된 것이 아니라 이해가 깊어짐에 따라 진화한다. 성장
ArtisanMind - 이름을 짓는 것은 대표적인 '감각적' 활동이다. 논리보다 뉘앙스가 중요하다. 기예
PatternHunting - 반복되는 구조를 발견하면 그에 걸맞은 이름을 붙여 패턴으로 박제하라. 도구
Signs of Success
NamesAsDesign을 효과적으로 사용하고 있다는 신호:
주석이 줄어든다 - 코드가 스스로 말한다. 이름만으로 의도가 명확하다.
새로운 팀원의 빠른 적응 - 이름이 명확해서 코드베이스를 빠르게 이해한다.
코드 리뷰에서 이름 논의 - "이 이름이 의도를 잘 표현하나요?" 같은 질문이 나온다.
일관된 어휘 - 같은 개념을 항상 같은 이름으로 부른다. 혼란이 없다.
자연스러운 읽기 - 코드를 읽으면 문장처럼 흘러간다.
쉬운 리팩토링 - 이름을 바꾸면 설계 의도가 더 명확해진다.
도메인 대화 - 도메인 전문가와 대화할 때 코드의 이름을 그대로 사용할 수 있다.
For Teachers and Mentors
주니어의 네이밍을 개선하려면:
문맥을 보여줘라
"이 이름 좋아?"가 아니라 "이 이름이 여기서 어떻게 사용되는지 봐봐."
# 고립된 평가 X def calc(x): ... # 문맥에서 평가 ✓ order.calc() # 어색함 order.total() # 자연스러움
소리내어 읽게 하라
"이 코드를 영어 문장으로 읽어봐."
order.calculate_total_amount() # → "Order, calculate total amount" # 어색하지 않니? order.total() # → "Order's total" # 자연스럽지?
대안을 탐색하게 하라
"한 가지 이름만 생각하지 말고, 3-4개 대안을 만들어봐."
Option 1: process_user_data() Option 2: handle_user() Option 3: authenticate_user() Option 4: verify_credentials() # 어느 것이 의도를 가장 잘 표현하나?
리팩토링을 시연하라
# "이름을 개선하면서 설계도 개선되는 것 봐봐"
# V1
def f(x):
return x * 2
# V2
def process(data):
return data * 2
# V3
def double(value):
return value * 2
# V4
def apply_markup(price, rate=2.0):
return price * rate
패턴을 가르쳐라
일관된 패턴:
Boolean: is_*, has_*, can_*
Collection: 복수형 users, orders
Factory: create_*, build_*, make_*
Query: find_*, get_*, fetch_*
The Ultimate Insight
Phil Karlton이 말했다: "There are only two hard things in Computer Science: cache invalidation and naming things."
Martin Fowler가 말했다: "Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
Ward Cunningham이 말했다: "Clean code reads like well-written prose."
Robert C. Martin이 말했다: "The ratio of time spent reading versus writing is well over 10 to 1... making it easy to read makes it easier to write."
이 모든 지혜는 같은 진리를 가리킨다:
이름은 코드의 가장 중요한 문서다. 이름은 설계의 표면이다. 이름은 개념 그 자체다.
Names as the Surface of Thought
코드를 작성할 때, 우리는 생각을 코드로 변환한다:
생각: "주문의 총액을 계산해야 해" ↓ 이름: calculate_order_total() ↓ 코드: def calculate_order_total(order): ...
이름은 생각의 표면이다. 생각이 명확하면 이름도 명확하다. 이름이 불명확하면 생각도 불명확하다.
Names as Design Decisions
모든 이름은 설계 결정이다:
User vs Customer - 도메인 모델 결정
calculate() vs compute() - 의도의 차이
Manager vs Service - 아키텍처 패턴
data vs profile - 추상화 레벨
이름을 바꾸는 것은 단순한 리네이밍이 아니다. 설계를 바꾸는 것이다.
Names as Conversation
Eric Evans (DDD)의 Ubiquitous Language:
"비즈니스 전문가가 사용하는 단어를 코드에서도 사용하라. 그러면 코드가 비즈니스를 말한다."
좋은 이름은:
도메인 전문가와의 대화를 코드로 가져온다
팀원들 사이의 공통 언어를 만든다
미래의 개발자와 대화한다
The Paradox of Simplicity
역설: 간단한 이름이 더 어렵다.
# 쉬움: 모든 것을 이름에 calculateTotalAmountOfOrderIncludingAllItemsAndTax() # 어려움: 문맥과 조화 order.total()
간단한 이름을 짓는 것은 문맥을 이해하고 설계가 명확해야 가능하다.
좋은 이름은 쉬워 보이지만, 그 뒤에는 깊은 사고가 있다.
Summary
NamesAsDesign는 이름을 설계 활동으로 보는 철학이다:
핵심 원칙:
이름은 문맥에서 평가 - 고립된 이름은 판단 불가능
관계 속의 의미 - 형제, 부모, 자식과 조화
이름 = 개념 - 좋은 이름 = 좋은 개념화
이름 > 문서 - 자체 문서화 코드
은유의 힘 - 직관적 이해
의미 네트워크 - 언어로서의 이름들
왜 작동하는가:
- 이름은 생각의 표면
- 이름은 설계 결정
- 이름은 대화의 도구
- 간단한 이름은 깊은 이해의 결과
주니어 vs 시니어:
- 주니어: 이름을 라벨로 본다 → 너무 빠르거나 너무 장황함
- 시니어: 이름을 설계로 본다 → 문맥에 맞고 관계 속에서 조화로운 이름
궁극의 통찰:
좋은 이름은 그 자체로 좋지 않다. 좋은 이름은 문맥 속에서 "잘 어울린다." 형제, 부모, 자식과 조화롭게. 문제 공간과 해결 공간을 모두 표현하면서. 이름 짓기가 어렵다면, 그것은 신호다: 개념이 불명확하거나, 설계가 잘못되었거나. 좋은 이름을 찾는 과정은 좋은 설계를 찾는 과정이다.
"Code is read much more often than it is written."
이름을 설계하라. 개념을 명확히 하라. 그러면 코드가 스스로 말할 것이다.
CategoryPatternLanguage CategoryProgramming CategoryDesign CategoryNaming CategoryCleanCode
