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