背景
オニオンアーキテクチャを理解したかったので、FastAPIをオニオンアーキテクチャで作ることにした!
とは言ったものの、オニオンアーキテクチャを調べると難しかったので、自分が理解できるレベルに噛み砕いてみた
前提知識
オニオンアーキテクチャ
よく見つやつ↓
勉強スタート
ディレクトリ構成
以下のディレクトリ構成を作る
interface/ # アプリケーションが外部システムと通信するためのAPI
application/ # DB操作、トランザクション管理、外部サービスなどを組み合わせる
domain/ # モデル、モデルを作ったり、計算するサービス
infrastructure/ # 外部サービスとの連携, DB との連携
オニオンアーキテクチャの絵を書き直す
基本的なデータの流れ
赤の矢印に沿ってプログラムが進んでいく。
逆向きに進んではNG!
NG例: DomainServiceからApplicationServiceを呼び出してはいけない
DBが操作できない?
この絵の通りプログラムを書いていくと、壁にぶち当たった
ApplicationServiceでDBを更新したりするのだが、DBを更新するプログラムはinfrastructure/
にある
矢印の向き的に、ApplicationServiceからinfrastructure/
を呼び出せない。
これを解消するために、domain/
にInterfaceを作る。
DomainInterfaceはただの箱。実体は、infrastructure/
にある。
interface/api
を実行する時に、箱の中身も渡してあげるイメージ
コードだとこんな感じ
# domain/interface/repositories/message_repository.py
class IMessageRepository(ABC):
@abstractmethod
def find_by_id(self, message_id: int) -> Message:
pass
@abstractmethod
def save(self, message: Message) -> Message:
pass
# infrastructure/repositories/message_repository.py
class MessageRepository(IMessageRepository):
def __init__(self, session: SQLAlchemySession) -> None:
self.session = session
def find_by_id(self, message_id: int) -> Message:
try:
p_message = (
self.session.query(MessagePersistence).filter_by(id=message_id).one()
)
return self._create_message_from_persistence(p_message)
except Exception:
raise
def save(self, message: Message) -> Message:
p_message = MessagePersistence.create(message)
try:
self.session.add(p_message)
if self.session.in_transaction():
self.session.flush()
else:
self.session.commit()
return self._create_message_from_persistence(p_message)
except Exception:
raise
最終的に出来上がったもの
interface/
|- api/ # API
application/
|- services/ # DB操作、トランザクション管理、外部サービスなどを組み合わせる
domain/
|- services/ # DomainModel作成、計算処理
|- models/ # プログラム全体で利用するモデル
|- interfaces/
|- repositories/ # infrastructure/respositoriesを呼び出すための箱
|- externals/ # infrastructure/externalsを呼び出すための箱
infrastructure/
|- repotitories/ # DBの処理
|- externals/ # 外部サービスの呼び出し
感想
オニオンアーキテクチャの基本的な流れが理解できた。
まだ、書いてないがテストがやりやすそう。
ただ、コード書く量が多いなーとは正直思った。