Чистый микроблог. Обработчик

Итак, у нас есть данные нашего микроблога, мы уже разработали команду для публикации поста и событие, которым мы изменим мир. Настала пора написать обработчик, чем сейчас и займемся.

Для начала надо понять, что значит выполнить команду "Опубликуй пост". Мне кажется, обработчик должен сохранить пост где-то и сообщить миру о том, что "Пост опубликован". И все.

Полагаю, мы хотим хранить где-то посты пользователей - в каком-то абстрактном репозитории.

from abc import ABC, abstractmethod

class AbstractRepository(ABC):

    @abstractmethod
    def save_post(self, post: Post) -> Post:
        "Creates post in repository"

     @abstractmethod
     def __enter__(self):
         "We need to initiate session with our repository"

      @abstractmethod
      def __exit__(self, *args):
          "We need to close our session and rollback uncommited changes"

      @abstractmethod
      def commit(self):
          "We want to commit changes into repository"

      @abstractmethod
      def rollback(self):
          "We want to rollback changes sometimes"

Сразу добавил методов из реального мира. Репозиторий обычно это какой-то движок базы данных, и нам надо открывать-закрывать соединение, запускать транзакции и т.д. Для обучающих целей достаточно было и первого метода, но чтобы никто не говорил "да это не будет работать" - сразу добавил и остальные. Будет.

Кроме того, нам нужна еще какая-то абстракция, которая будет публиковать сообщения. Для обработки нашей команды совершенно неважно где именно.

from abc import ABC, abstractmethod

class AbstractPublisher(ABC):

    @abstractmethod
    def publish(self, message: Message):
        "Publish message somewhere"

Ну и теперь наш обработчик. Он обрабатывает команду, знает о данных, о событии, но не зависит от реализации наших абстракций.

def publish_post_handler(command: PublishPost,
                         repo: AbstractRepository,
                         publisher: AbstractPublisher):
    with repo: 
        post = Post()
        post.id = command.id
        post.text = command.text
        post.customer_id = command.customer_id

        event = PostPublished(**vars(command))

        repo.create_post(post)
        repo.commit()
        publisher.publish(event)

Вот так вот получилось. В контексте репозитория мы создаем из команды пост, подготавливаем итоговое событие, сохраняем пост в репозитории, подтверждаем изменения и публикуем события.

Мне в этом коде непонятен только один момент: почему, когда я предлагаю писать вот так, никто не соглашается?

<2023-01-26 Thu>

Author: Nikita Mistiukov <me@nekifirus.com>

Created: 2023-01-26 Thu 23:54

Validate