python: Domain-Driven-Design

 

 

domain/
  aggregates/
  entities/
  value objects/
  events
application/
  services
  commands
  queries
infrastructure/
  repositories
  messaging/
tests

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:实体(Entity)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:12
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : Entities.py
# explain   : 学习

from uuid import UUID

class Customer:
    """
    实体(Entity)
    """
    def __init__(self, id: UUID, name: str, email: str):
        """

        :param id:
        :param name:
        :param email:
        """
        self.id = id
        self.name = name
        self.email = email

class Product:
    """
    实体(Entity)
    """
    def __init__(self, id: UUID, name: str, price: float):
        """

        :param id:
        :param name:
        :param price:
        """
        self.id = id
        self.name = name
        self.price = price

  

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:值对象(Value Object)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:14
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : ValueObjects.py
# explain   : 学习

from dataclasses import dataclass
from Entities import Product


@dataclass(frozen=True)
class Address:
    """
    值对象(Value Object)
    """
    street: str
    city: str
    state: str
    zip_code: str

@dataclass(frozen=True)
class OrderItem:
    """
    值对象(Value Object)
    """
    product: Product
    quantity: int

  

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:聚合(Aggregate) 一组相关联的对象,作为一个整体进行操作和事务处理。
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:15
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : Aggregates.py
# explain   : 学习
from uuid import UUID
from Entities import Product
from Entities import Customer
from typing import Optional, List
from ValueObjects import OrderItem
from ValueObjects import Address


class Order:
    """
    聚合(Aggregate)
    """
    def __init__(self, id: UUID, customer: Customer, items: List[OrderItem], shipping_address: Address, discount_rate: float = 0.0):
        """

        :param id:
        :param customer:
        :param items:
        :param shipping_address:
        :param discount_rate:
        """
        self.id = id
        self.customer = customer
        self.items = items
        self.shipping_address = shipping_address
        self.discount_rate = discount_rate

    def apply_discount(self, discount_rate: float):
        """

        :param discount_rate:
        :return:
        """
        self.discount_rate = discount_rate

    def total_price(self) -> float:
        """

        :return:
        """
        total = sum(item.product.price * item.quantity for item in self.items)
        return total * (1 - self.discount_rate)

  

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:33
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : Event.py
# explain   : 学习
from uuid import UUID
from typing import Optional, List
from domain.Entities import Customer
from domain.Entities import Product



class OrderCreated:
    """

    """

    def __init__(self, order_id: UUID, customer: Customer):
        """

        :param order_id:
        :param customer:
        """
        self.order_id = order_id
        self.customer = customer

  

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:34
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : EventHandler.py
# explain   : 学习

from Event import OrderCreated


class SendOrderConfirmationEmail:
    """

    """

    def __init__(self, email_service):
        """

        :param email_service:
        """
        self._email_service = email_service

    def handle(self, event: OrderCreated) -> None:
        """

        :param event:
        :return:
        """
        self._email_service.send(
            to=event.customer.email,
            subject="Order Confirmation",
            body=f"Your order {event.order_id} has been created."
        )

  

 

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:24
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : RepositoryInterfaces.py
# explain   : 学习
from abc import ABC, abstractmethod
from typing import Optional, List
from uuid import UUID
from domain.Entities import Customer
from domain.Entities import Product

from domain.Aggregates import Order


class CustomerRepository(ABC):
    """

    """
    @abstractmethod
    def save(self, customer: Customer) -> None:
        """

        :param customer:
        :return:
        """
        pass

    @abstractmethod
    def find_by_id(self, customer_id: UUID) -> Optional[Customer]:
        """

        :param customer_id:
        :return:
        """
        pass

class ProductRepository(ABC):
    """

    """
    @abstractmethod
    def save(self, product: Product) -> None:
        """

        :param product:
        :return:
        """
        pass

    @abstractmethod
    def find_by_id(self, product_id: UUID) -> Optional[Product]:
        """

        :param product_id:
        :return:
        """

        pass

    @abstractmethod
    def find_all(self) -> List[Product]:
        """

        :return:
        """
        pass

class OrderRepository(ABC):
    """

    """
    @abstractmethod
    def save(self, order: Order) -> None:
        """

        :param order:
        :return:
        """
        pass

    @abstractmethod
    def find_by_id(self, order_id: UUID) -> Optional[Order]:
        """

        :param order_id:
        :return:
        """
        pass

  

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:27
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : RepositoryClasses.py
# explain   : 学习

from RepositoryInterfaces import CustomerRepository
from RepositoryInterfaces import ProductRepository
from RepositoryInterfaces import OrderRepository
from uuid import UUID
from typing import Optional, List

from domain.Entities import Customer
from domain.Entities import Product
from domain.Aggregates import Order


class InMemoryCustomerRepository(CustomerRepository):
    """

    """
    def __init__(self):
        self._store = {}

    def save(self, customer: Customer) -> None:
        """

        :param customer:
        :return:
        """
        self._store[customer.id] = customer

    def find_by_id(self, customer_id: UUID) -> Optional[Customer]:
        """

        :param customer_id:
        :return:
        """
        return self._store.get(customer_id)

class InMemoryProductRepository(ProductRepository):
    """

    """
    def __init__(self):
        self._store = {}

    def save(self, product: Product) -> None:
        """

        :param product:
        :return:
        """

        self._store[product.id] = product

    def find_by_id(self, product_id: UUID) -> Optional[Product]:
        """

        :param product_id:
        :return:
        """

        return self._store

    def find_by_id(self, product_id: UUID) -> Optional[Product]:
        """

        :param product_id:
        :return:
        """
        return self._store.get(product_id)

    def find_all(self) -> List[Product]:
        """

        :return:
        """
        return list(self._store.values())

class InMemoryOrderRepository(OrderRepository):
    """

    """
    def __init__(self):
        self._store = {}

    def save(self, order: Order) -> None:
        """

        :param order:
        :return:
        """
        self._store[order.id] = order

    def find_by_id(self, order_id: UUID) -> Optional[Order]:
        """

        :param order_id:
        :return:
        """
        return self._store.get(order_id)

  

# encoding: utf-8
# 版权所有 2024 涂聚文有限公司
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:领域服务(Domain Service)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, poostgreSQL 17.0
# Datetime  : 2024/12/17 20:30
# User      : geovindu
# Product   : PyCharm
# Project   : Pydddsimple
# File      : Services.py
# explain   : 学习


from uuid import UUID
from typing import Optional, List

from domain.Entities import Customer
from domain.Entities import Product
from domain.Aggregates import Order
from domain.ValueObjects import Address
from domain.ValueObjects import OrderItem
from infrastructure.RepositoryClasses import CustomerRepository
from infrastructure.RepositoryClasses import ProductRepository
from infrastructure.RepositoryClasses import OrderRepository

from domain.Event import OrderCreated
from domain.EventHandler import SendOrderConfirmationEmail



class ECommerceService:
    """

    """
    def __init__(self, customer_repository: CustomerRepository, product_repository: ProductRepository, order_repository: OrderRepository):
        """

        :param customer_repository:
        :param product_repository:
        :param order_repository:
        """

        self._customer_repository = customer_repository
        self._product_repository = product_repository
        self._order_repository = order_repository

    def create_customer(self, name: str, email: str) -> Customer:
        """

        :param name:
        :param email:
        :return:
        """
        customer = Customer(id=UUID(), name=name, email=email)
        self._customer_repository.save(customer)
        return customer

    def create_product(self, name: str, price: float) -> Product:
        """

        :param name:
        :param price:
        :return:
        """
        product = Product(id=UUID(), name=name, price=price)
        self._product_repository.save(product)
        return product

    def create_order(self, customer_id: UUID, items: List[OrderItem], shipping_address: Address) -> Order:
        """

        :param customer_id:
        :param items:
        :param shipping_address:
        :return:
        """
        customer = self._customer_repository.find_by_id(customer_id)
        if not customer:
            raise ValueError("Customer not found")

        order = Order(id=UUID(), customer=customer, items=items, shipping_address=shipping_address)
        self._order_repository.save(order)

        # Apply discount based on total order value
        if order.total_price() > 100:
            order.apply_discount(0.1)

        # Send email notification (handled by domain event)
        event = OrderCreated(order_id=order.id, customer=customer)
        SendOrderConfirmationEmail().handle(event)

        return order

    def get_order_by_id(self, order_id: UUID) -> Optional[Order]:
        """

        :param order_id:
        :return:
        """

        return self._order_repository.find_by_id(order_id)

  

from:

https://www.w3computing.com/articles/implementing-domain-driven-design-in-python-projects/

https://github.com/heynickc/awesome-ddd
https://github.com/qu3vipon/python-ddd
https://github.com/software-architecture-2030/Domain-Driven-Design-DDD
https://www.geeksforgeeks.org/domain-driven-design-ddd/

 

posted @ 2024-12-17 20:55  ®Geovin Du Dream Park™  阅读(24)  评论(0)    收藏  举报