도메인 주도 설계(DDD)란 무엇인가?

돈과젤리·2024년 6월 6일
0
  1. 도메인 주도 설계(DDD, Domain-Driven Design)는 복잡한 소프트웨어 시스템을 설계하는 방법론 중 하나입니다.
    아래 내용에서 DDD의 설명과 예시 코드를 보여드리겠습니다.

2. DDD의 주요 원칙

2.1 엔티티(Entity)

엔티티는 고유한 식별자를 가지고 있으며, 도메인 내에서 중요한 객체를 나타냅니다. 예를 들어, 상품 관리 시스템에서 상품은 엔티티가 될 수 있습니다.

2.2 값 객체(Value Object)

값 객체는 고유한 식별자가 없으며, 특정 엔티티의 속성을 구성합니다. 값 객체는 불변성을 가지며, 동일한 값이면 같은 객체로 간주됩니다.

2.3 리포지토리(Repository)

리포지토리는 엔티티 객체들의 저장소 역할을 합니다. 데이터베이스와 같은 영구 저장소와의 상호작용을 담당합니다.

2.4 서비스(Service)

서비스는 비즈니스 로직을 포함하는 객체로, 엔티티와 리포지토리를 조작하여 비즈니스 로직을 구현합니다.


3. DDD 예제: 상품 관리 시스템

다음은 DDD 원칙을 적용한 상품 관리 시스템의 예제입니다.
이 예제에서는 상품 리스트를 관리하고 출력하는 애플리케이션을 작성합니다.

3.1 엔티티 클래스 작성

먼저, Product 엔티티 클래스를 작성합니다.
product\productlist\entity\product.py

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def getName(self):
        return self.name

    def getPrice(self):
        return self.price

3.2 값 객체 작성

다음으로, ProductList 값을 Enum으로 정의합니다.
product\productlist\entity\productList.py

from enum import Enum


class ProductList(Enum):
    PRODUCT1 = ("반팔티", 10000)
    PRODUCT2 = ("반바지", 10000)
    PRODUCT3 = ("모자", 5000)

3.3 리포지토리 인터페이스 작성

리포지토리 인터페이스를 정의합니다.
product\productlist\repository\product_list_repository.py

from abc import ABC, abstractmethod

class ProductListRepository(ABC):
    @abstractmethod
    def getProductList(self):
        pass

3.4 리포지토리 구현

리포지토리 구현체를 작성합니다.
product\productlist\repository\product_list_repository_impl.py

from productlist.entity.product import Product
from productlist.repository.product_list_repository import ProductListRepository
from productlist.entity.productList import ProductList

class ProductListRepositoryImpl(ProductListRepository):
    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
            cls.__instance.__productList = []

            # Initialize product list from ProductList enum
            for product in ProductList:
                name, price = product.value
                cls.__instance.__productList.append(Product(name, price))

        return cls.__instance

    @classmethod
    def getInstance(cls):
        if cls.__instance is None:
            cls.__instance = cls()

        return cls.__instance

    def getProductList(self):
        return self.__productList

3.5 서비스 인터페이스 작성

서비스 인터페이스를 정의합니다.
product\productlist\service\product_list_service.py

from abc import ABC, abstractmethod


class ProductListService(ABC):
    @abstractmethod
    def getProductList(self):
        pass

3.6 서비스 구현

서비스 구현체를 작성합니다.
product\productlist\service\product_list_service_impl.py

from productlist.repository.product_list_repository_impl import (
    ProductListRepositoryImpl,
)
from productlist.service.product_list_service import ProductListService


class ProductListServiceImpl(ProductListService):
    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
            cls.__instance.__productlistRepository = (
                ProductListRepositoryImpl().getInstance()
            )

        return cls.__instance

    @classmethod
    def getInstance(cls):
        if cls.__instance is None:
            cls.__instance = cls()

        return cls.__instance

    def getProductList(self):
        return self.__productlistRepository.getProductList()

3.8 애플리케이션 계층 작성

애플리케이션의 진입점을 작성합니다.
product\main.py

from productlist.service.product_list_service_impl import ProductListServiceImpl
from initializer.domain_initializer import DomainInitializer

if __name__ == "__main__":
    DomainInitializer.initEachDomain()

    productService = ProductListServiceImpl.getInstance()
    productList = productService.getProductList()

    for product in productList:
        print(f"상품명: {product.getName()}, 가격: {product.getPrice()}")

0개의 댓글

관련 채용 정보