Чистый микроблог. Обработчик
Итак, у нас есть данные нашего микроблога, мы уже разработали команду для публикации поста и событие, которым мы изменим мир. Настала пора написать обработчик, чем сейчас и займемся.
Для начала надо понять, что значит выполнить команду "Опубликуй пост". Мне кажется, обработчик должен сохранить пост где-то и сообщить миру о том, что "Пост опубликован". И все.
Полагаю, мы хотим хранить где-то посты пользователей - в каком-то абстрактном репозитории.
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)
Вот так вот получилось. В контексте репозитория мы создаем из команды пост, подготавливаем итоговое событие, сохраняем пост в репозитории, подтверждаем изменения и публикуем события.
Мне в этом коде непонятен только один момент: почему, когда я предлагаю писать вот так, никто не соглашается?