Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Python
- 노개북
- 프로그래머스 입문
- 월부닷컴
- 월급쟁이부자들
- 프로그래머스 기초
- 개발자북클럽
- 프로그래머스 코딩테스트 기초
- 문자열이 몇 번 등장하는지 세기
- 풀스택gpt
- 노마드코더
- 0 떼기
- 파이썬
- 주사위 게임1
- 부동산강의
- 코딩테스트
- 배열 만들기3
- 특정 문자열로 끝나는 가장 긴 문자열 찾기
- 월부
- 첫번째로 나오는 음수
- 세 개의 구분자
- 프로그래머스
- 클린코드
- 배열 만들기6
- 열기반
- 기초
- l로 만들기
- 열반스쿨기초반
- 무작위로 k개의 수 뽑기
- 특별한 이차원 배열 1
Archives
- Today
- Total
해쟈스토리
결합도 본문
728x90
반응형
def process_order(order):
# 재고 확인
if check_inventory(order.items) == False:
print("재고 부족")
return False
# 결제 처리
if process_payment(order.total, order.payment_info) == False:
print("결제 실패")
return False
# 배송 처리
shipping_label = create_shipping_label(order.address)
if shipping_label == None:
print("배송 라벨 생성 실패")
return False
# 이메일 발송
send_confirmation_email(order.email, order.items)
print("주문 처리 완료")
return True
def check_inventory(items):
# 재고 확인 로직
pass
def process_payment(total, payment_info):
# 결제 처리 로직
pass
def create_shipping_label(address):
# 배송 라벨 생성 로직
pass
def send_confirmation_email(email, items):
# 주문 확인 이메일 발송 로직
pass
위와 같은 코드가 있다. 이 코드는 낮은 수준의 추상화 레벨을 가지고 있다(높은 결합도)
그래서 이런 코드를 개선해야한다.
class OrderProcessor:
def __init__(self):
self.inventory_manager = InventoryManager()
self.payment_gateway = PaymentGateway()
self.shipping_manager = ShippingManager()
self.email_service = EmailService()
def process_order(self, order):
try:
self.check_inventory(order)
self.process_payment(order)
self.create_shipping_label(order)
self.send_confirmation(order)
print("주문 처리 완료")
return True
except OrderProcessingError as e:
print(f"주문 처리 실패: {str(e)}")
return False
def check_inventory(self, order):
if not self.inventory_manager.check_availability(order.items):
raise OrderProcessingError("재고 부족")
def process_payment(self, order):
if not self.payment_gateway.charge(order.total, order.payment_info):
raise OrderProcessingError("결제 실패")
def create_shipping_label(self, order):
label = self.shipping_manager.create_label(order.address)
if not label:
raise OrderProcessingError("배송 라벨 생성 실패")
def send_confirmation(self, order):
self.email_service.send_order_confirmation(order.email, order.items)
class OrderProcessingError(Exception):
pass
class InventoryManager:
def check_availability(self, items):
# 재고 확인 로직
pass
class PaymentGateway:
def charge(self, total, payment_info):
# 결제 처리 로직
pass
class ShippingManager:
def create_label(self, address):
# 배송 라벨 생성 로직
pass
class EmailService:
def send_order_confirmation(self, email, items):
# 주문 확인 이메일 발송 로직
pass
근데 솔직히 와닿지 않는다... 뭔소리람? 왜 두번째 코드처럼 바뀌여야 하는지 잘 이해가 안된다...
개선된 코드의 장점에 대해 claude에게 물어봤다.
- OrderProcessor 클래스는 전체 주문 처리 흐름만 관리하며, 세부 작업은 각 전문 클래스에 위임합니다.
- 각 기능(재고 관리, 결제, 배송, 이메일)이 별도의 클래스로 분리되어 있어, 독립적으로 수정하거나 확장할 수 있습니다.
- 에러 처리가 통일되어 있어 코드의 일관성이 향상되었습니다.
- 새로운 기능(예: 주문 추적)을 추가하려면 새 클래스를 만들고 OrderProcessor에 연결하면 됩니다.
각 부분에 대해 내가 궁금한 점을 계속해서 물어봤다.
OrderProcessor 클래스는 전체 주문 처리 흐름만 관리하며, 세부 작업은 각 전문 클래스에 위임합니다.
전체 주문 처리 흐름만 관리한다고 하는데, 기존 코드에서도 각 주문 step별로 함수로 나누어져 있었다. 뭔 차이 인가????
이 함수는 확실히 각 단계별로 함수를 호출하고 있어서, 어느 정도 관심사의 분리가 이루어져 있습니다. 그러나 여전히 몇 가지 문제점이 있습니다:
오류 처리: 각 단계의 오류 처리 로직이 process_order 함수 내에 하드코딩되어 있습니다.
이는 오류 처리 방식을 변경하려면 이 함수를 수정해야 한다는 것을 의미합니다.
흐름 제어: 전체 프로세스의 흐름 제어(각 단계의 순서, 조건부 실행 등)가 이 함수에 직접 포함되어 있습니다.
의존성: 이 함수는 여러 다른 함수(check_inventory, process_payment 등)에 직접적으로 의존하고 있습니다.
이들 함수의 시그니처가 변경되면 process_order 함수도 수정해야 합니다.
확장성: 새로운 단계를 추가하거나 기존 단계의 순서를 변경하려면 이 함수를 직접 수정해야 합니다.
오류 처리 방식을 변경하는 것은 이미 계약에 의해서 bool값으로 return하기로 되어 있는데 오류처리 방식을 바꾸면 안되는거아냐? 처음부터 잘못 설계한거야?
흐름제어도 OderProcessor에서 process_order에서 흐름제어 하잖아.
의존성은 무슨 말인지 모르겠어. 함수의 시그니처가 뭐야?
새로운 단계를 추가하거나 기존 단계 순서를 변경하면 OrderProcessor에서도 process_order가 변경되야 하는거 아냐?
오류 처리: 맞습니다. 만약 계약에 의해 boolean 값을 반환하기로 되어 있다면, 그 인터페이스를 유지해야 합니다. 이 경우, 처음부터 이런 방식으로 설계한 것이 최선의 선택이 아니었을 수 있습니다. 더 나은 설계라면 오류의 상세 정보를 제공할 수 있는 방식(예: 예외 처리나 상세한 결과 객체 반환)을 고려했을 것입니다.
흐름 제어: 네, 맞습니다. OrderProcessor의 process_order 메서드도 여전히 흐름을 제어합니다. 주요 차이점은 각 단계가 메서드로 추출되어 있어 테스트와 수정이 더 용이하다는 점입니다. 하지만 근본적인 흐름 제어 로직은 여전히 존재합니다.
함수의 시그니처: 함수의 시그니처란 함수의 이름, 매개변수 목록, 반환 타입을 포함한 함수의 정의 부분을 말합니다.
새로운 단계 추가 또는 순서 변경: 네, 맞습니다. OrderProcessor의 process_order 메서드도 새로운 단계 추가나 순서 변경 시 수정이 필요합니다. 이 점에서는 두 접근 방식이 크게 다르지 않습니다.
--------------------------------------------------------------------------------------------------------------------------------------------------
제가 앞서 설명한 내용 중 일부가 과장되거나 부정확했던 것 같습니다. 실제로 두 접근 방식의 차이는 생각보다 미묘할 수 있습니다. 주요 차이점을 다시 정리하면:
객체 지향적 접근: OrderProcessor는 객체 지향 프로그래밍의 원칙을 따르며, 상태(각 매니저 객체)와 행동(메서드)을 하나의 클래스에 캡슐화합니다.
테스트 용이성: 클래스 기반 접근은 각 단계를 개별 메서드로 분리하여 단위 테스트가 더 쉬울 수 있습니다.
의존성 관리: OrderProcessor는 생성자를 통해 의존성을 주입받을 수 있어, 필요시 다른 구현으로 쉽게 교체할 수 있습니다.
그러나 근본적인 로직 구조와 흐름 제어 측면에서는 두 접근 방식이 매우 유사합니다. 결국 어떤 방식을 선택할지는 프로젝트의 요구사항, 팀의 선호도, 그리고 전체 시스템의 아키텍처에 따라 달라질 수 있습니다.
메서드로 추출되어 있어서 테스트와 수정이 더 용이하다고 했는데... 함수로 되어 있으니까 함수도 테스트할 수 있잖아 무슨 차이가 있는거야?
함수 시그니처도 그래... 매개변수가 바뀌면 OrderProcessor에서도 바꿔야되잖아...
의존성 관리는 무슨 뜻인지 모르겠어
테스트와 수정의 용이성: 사실 함수와 메서드 모두 테스트할 수 있습니다. 이 점에서 큰 차이는 없습니다. 제가 말씀드린 "더 용이하다"는 표현은 정확하지 않았습니다. 오히려 차이점은 다음과 같습니다:
클래스 기반 접근에서는 각 단계가 클래스의 멤버 메서드로 구현되어 있어, 상태를 공유할 수 있습니다. 이는 장점이 될 수도 있고 단점이 될 수도 있습니다. 함수 기반 접근은 더 순수한 함수형 프로그래밍 스타일에 가깝습니다. 이는 테스트할 때 상태 관리에 대해 덜 신경 쓸 수 있다는 장점이 있습니다.
함수 시그니처 변경: 맞습니다. 함수의 시그니처가 변경되면 OrderProcessor에서도 변경해야 합니다. 이 점에서 두 접근 방식의 차이는 없습니다. 제가 이 부분을 과대평가했습니다.
의존성 관리: 의존성 관리란 한 모듈이 다른 모듈에 의존하는 방식을 관리하는 것을 말합니다.
class OrderProcessor:
def __init__(self, inventory_manager, payment_gateway, shipping_manager, email_service):
self.inventory_manager = inventory_manager
self.payment_gateway = payment_gateway
self.shipping_manager = shipping_manager
self.email_service = email_service
이렇게 구성하면, 각 구성요소(inventory_manager, payment_gateway 등)를 외부에서 주입받을 수 있습니다. 이를 "의존성 주입"이라고 합니다.
함수 기반 접근에서도 비슷한 효과를 낼 수 있습니다:
def process_order(order, inventory_checker, payment_processor, shipping_label_creator, email_sender):
if not inventory_checker(order.items):
return False
# ... 나머지 로직
두 방식 모두 의존성을 외부에서 주입받을 수 있으므로, 이 점에서도 큰 차이가 없습니다.
결론적으로, 제가 처음에 설명드린 두 접근 방식의 차이점들은 실제로는 그렇게 크지 않습니다. 주요 차이점은 다음과 같이 정리할 수 있습니다:
객체 지향 vs 함수형: OrderProcessor 클래스는 객체 지향적 접근을, 함수 기반은 더 함수형 프로그래밍에 가까운 접근을 취합니다.
상태 관리: 클래스 기반 접근은 상태를 내부적으로 관리할 수 있지만, 함수 기반 접근은 보통 상태를 외부에서 관리합니다.
코드 구조: 클래스 기반 접근은 관련 기능을 하나의 클래스 안에 모아둘 수 있어, 코드 구조화에 도움이 될 수 있습니다.
그러나 성능, 테스트 용이성, 유지보수성 등의 측면에서 두 접근 방식은 크게 다르지 않을 수 있습니다. 선택은 주로 프로젝트의 전반적인 스타일, 팀의 선호도, 그리고 특정 요구사항에 따라 달라질 것입니다.
음... 마지막 답변에는 의문점이 없었지만 언제 클래스 형식으로 추상화해야하는지. 이런 부분은 해소되지 못했다.
메소드가 하나라면 함수로 해도 될것같다.
728x90
반응형
'파이썬 > 클린코드' 카테고리의 다른 글
| 클린 코드 책읽기 day2 - 1장 깨끗한 코드 (0) | 2024.08.27 |
|---|---|
| 클린코드 책 읽기 day1 (0) | 2024.08.24 |
| 방어적 프로그래밍 (0) | 2024.08.19 |
| dataclasses 모듈 (1) | 2024.06.17 |
| Property (0) | 2024.06.14 |