객체 지향 특성, 의존성 응집도 결합도 with 코드

jjin·2024년 3월 21일
0

책임과 협력

책임

한 객체가 수행해야 하는 범위. 책임에 맞게 설계.

ex) 사람은 운전의 책임이 있다. 차량은 감속/가속의 책임이 있다.

협력

필요에 따라 의존하는 것. 객체 호출 등

class Car:
	def __init__(self):
		self.speed = 0
        
	def accelerate(self):
    	self.speed += 10
    
    def decelerate(self):
    	self.speed -= 10

class User:
	def __init__(self) -> None:
    	self.car = MorningCar()

	def drive(self) -> None:
    	self.car.accelerate()

추상화

추상화 없을 때

class PorscheCar:
    def __init__(self):
        self.speed = 0 
        self._fuel = 0
						
    def accelerate(self):
        self.speed += 3

    def decelerate(self):
        self.speed -= 3
		

class User: # 다른 차 추가마다 elif 문 추가
    def __init__(self, car_name: str) -> None:
        if car_name == "morning":
            self.car = MorningCar()
        elif car_name == "porsche":
            self.car = PorscheCar()

    def drive(self):
        self.car.accelerate()

추상화 있을 때 (인터페이스 유무)

from abc import ABC

class Car(ABC):						
    @abstractmethod                    
    def accelerate(self) -> None:
        spass
        
	@abstractmethod
    def decelerate(self) -> None:
        pass
class PorscheCar(Car):
	    def __init__(self) -> None:
        self.speed = 0 
        self._fuel = 0
						               
    def accelerate(self) -> None:
        self.speed += 3
        
    def decelerate(self) -> None:
        self.speed -= 3
        
class MorningCar(Car):
	    def __init__(self) -> None:
        self.speed = 0 
        self._fuel = 0
						               
    def accelerate(self) -> None:
        self.speed += 1
        
    def decelerate(self) -> None:
        self.speed -= 1
class User:
	def __init__(self, car: Car) -> None:
    	self.car = car
        
    def drive(self):
    	self.car.accelerate()

다형성: 객체 지향의 꽃

user = User(MorningCar())
user.drive()

user = User(PorscheCar())
user.drive()

User는 생성자에서 추상 클래스인 Car를 의존하고 있음.

의존성 주입

Car의 자식 클래스 객체를 파라미터로 넘겨 주고 있음.
OCP 준수

캡슐화

은닉 않고 직접 접근하는 것: SRP 위반, 검증되지 않은 값 들어가기 쉬움

!== Getter/Setter
캡슐화를 돕는 방법 중 하나일 뿐.

의존성 응집도 결합도

의존성

정적 의존성 =컴파일 의존성

객체 내에서 다른 객체에 접근하는 경우.
User 객체가 Engineer 객체의 정보(속성, 메서드)를 아는 경우.

동적 의존성

코드 레벨에서 드러나지는 않지만, 두 객체(인터페이스) 간 의존 관계
보통 추상클래스/인터페이스를 파라미터 타입으로 두고 의존성 주입으로 구체 클래스 객체를 인자로 넘겨주는 방식.

의존성 설계

정적 의존성 대상을 고수준(인터페이스) 코드로,
동적 의존성 대상을 저수준(인스턴스) 코드로 하자.

응집도

SRP. 한 객체에 책임에 따른 기능이 충분히 모여있도록.

결합도

객체의 정적 의존성 정도.
한 객체가 다른 객체의 정보를 알수록 좋지 않음.

리팩토링 해보기

class GrabStore:
    def __init__(self):
        self.money = 0
        self.name = "그랩마켓"
        self.products = {
            1: {"name": "키보드", "price": 30000},
            2: {"name": "모니터", "price": 50000},
        }

    def set_money(self, money):
        self.money = money

    def set_products(self, products):
        self.products = products

    def get_money(self):
        return self.money

    def get_products(self):
        return self.products
        
        
class User:
    def __init__(self):
        self.money = 0
        self.store = GrabStore()
        self.belongs = []

    def set_money(self, money):
        self.money = money

    def set_belongs(self, belongs):
        self.belongs = belongs

    def get_money(self):
        return self.money

    def get_belongs(self):
        return self.belongs

    def get_store(self):
        return self.store

    def see_product(self, product_id):
        products = self.store.get_products()
        return products[product_id]

    def purchase_product(self, product_id):
        product = self.see_product(product_id)
        if self.money >= product["price"]:
            self.store.products.pop(product_id)  # 상점에서 상품 꺼내기
            self.money -= product["price"]  # 사용자가 돈 내기
            self.store.money += product["price"]  # 상점에서 돈 받기
            self.belongs.append(product)
            return product
        else:
            raise Exception("잔돈이 부족합니다")
if __name__ == "__main__":
    user = User()
    user.set_money(100000)
    user.purchase_product(product_id=1)
profile
진짜

0개의 댓글

관련 채용 정보