Skip to content

Actor

Principles

Story could define an actor

Complicated business process is always a composition of smaller business processes. Sometimes these smaller processes would be executed by different persons in real life. Or by people with different roles. To make it easier for the reader of your code to understand who is I in current story you could define an actor as part of the story class.

Our general advice would be always define story actors even if you system only has single role at the moment. This small change would give right context for the reader. And please do not call it User. It is always a user.

>>> from dataclasses import dataclass
>>> from typing import Callable
>>> from stories import Story, I, State, Actor
>>> from app.repositories import load_order, load_customer, create_payment

>>> class Customer(Actor):
...     ...

>>> @dataclass
... class Purchase(Story, Customer):
...     I.find_order
...     I.find_customer
...     I.check_balance
...     I.persist_payment
...
...     def find_order(self, state):
...         state.order = self.load_order(state.order_id)
...
...     def find_customer(self, state):
...         state.customer = self.load_customer(state.customer_id)
...
...     def check_balance(self, state):
...         if not state.order.affordable_for(state.customer):
...             raise Exception
...
...     def persist_payment(self, state):
...         state.payment = self.create_payment(
...             order_id=state.order_id, customer_id=state.customer_id
...         )
...
...     load_order: Callable
...     load_customer: Callable
...     create_payment: Callable

>>> purchase = Purchase(
...     load_order=load_order,
...     load_customer=load_customer,
...     create_payment=create_payment,
... )

>>> state = State(order_id=1, customer_id=1)

>>> purchase(state)
>>> import asyncio
>>> from dataclasses import dataclass
>>> from typing import Coroutine
>>> from stories import Story, I, State, Actor
>>> from aioapp.repositories import load_order, load_customer, create_payment

>>> class Customer(Actor):
...     ...

>>> @dataclass
... class Purchase(Story, Customer):
...     I.find_order
...     I.find_customer
...     I.check_balance
...     I.persist_payment
...
...     async def find_order(self, state):
...         state.order = await self.load_order(state.order_id)
...
...     async def find_customer(self, state):
...         state.customer = await self.load_customer(state.customer_id)
...
...     async def check_balance(self, state):
...         if not state.order.affordable_for(state.customer):
...             raise Exception
...
...     async def persist_payment(self, state):
...         state.payment = await self.create_payment(
...             order_id=state.order_id, customer_id=state.customer_id
...         )
...
...     load_order: Coroutine
...     load_customer: Coroutine
...     create_payment: Coroutine

>>> purchase = Purchase(
...     load_order=load_order,
...     load_customer=load_customer,
...     create_payment=create_payment,
... )

>>> state = State(order_id=1, customer_id=1)

>>> asyncio.run(purchase(state))

— ⭐ —