TechCraft – エンジニアのためのスキルアップメモ

エンジニアのスキルアップを少しでも加速する技術ブログ

ヘキサゴナルアーキテクチャで学ぶ設計の本質:Pythonで実践する疎結合アプリ構築

ヘキサゴナルアーキテクチャで学ぶ設計の本質:Pythonで実践する疎結合アプリ構築


1. 導入:なぜ今「ヘキサゴナルアーキテクチャ」なのか?

ソフトウェアの寿命は年々長くなり、保守性と柔軟性がますます求められるようになっています。アプリケーションの要件が変化しても、核となるビジネスロジックを傷つけずに拡張・修正できる構造が求められます。

こうしたニーズに応える設計思想の一つが「ヘキサゴナルアーキテクチャ(Hexagonal Architecture)」、別名「ポートとアダプタアーキテクチャ」です。本記事ではこのアーキテクチャの基本を学び、Pythonで簡単なアプリケーションを構築することで、疎結合設計の本質を実感していただきます。


2. ヘキサゴナルアーキテクチャとは?

ヘキサゴナルアーキテクチャは、以下の特徴を持つアーキテクチャスタイルです:

この構成により、コアと外部の依存を逆転させ、テストしやすく拡張性の高い構造が実現します。

図解イメージ(リンク)

以下のサイトでは、構造のイメージをわかりやすく図解しています:


3. Pythonで簡単なヘキサゴナルアプリを作ってみよう

3.1 全体構成

myapp/
├── domain/           # ビジネスルール
│   └── model.py
├── usecase/          # アプリケーションロジック
│   └── interactor.py
├── interface/        # アダプタ(入出力)
│   ├── repository.py
│   └── cli.py
└── main.py           # エントリーポイント

3.2 ドメイン層(ビジネスルール)

# domain/model.py
class User:
    def __init__(self, user_id: int, name: str):
        self.user_id = user_id
        self.name = name

3.3 ポート(インタフェースの抽象)

# usecase/interactor.py
from abc import ABC, abstractmethod
from domain.model import User

class UserRepository(ABC):
    @abstractmethod
    def save(self, user: User):
        pass

class UserInteractor:
    def __init__(self, repository: UserRepository):
        self.repository = repository

    def create_user(self, user_id: int, name: str):
        user = User(user_id, name)
        self.repository.save(user)
        return user

3.4 アダプタ層(インフラ実装)

# interface/repository.py
from usecase.interactor import UserRepository
from domain.model import User

class InMemoryUserRepository(UserRepository):
    def __init__(self):
        self.users = {}

    def save(self, user: User):
        self.users[user.user_id] = user
        print(f"Saved user: {user.name}")
# interface/cli.py
from usecase.interactor import UserInteractor
from interface.repository import InMemoryUserRepository

def run():
    repo = InMemoryUserRepository()
    interactor = UserInteractor(repo)
    interactor.create_user(1, "Alice")

3.5 エントリーポイント

# main.py
from interface.cli import run

if __name__ == "__main__":
    run()

4. 疎結合のメリットを実感しよう

ヘキサゴナルアーキテクチャを使うことで、以下のようなメリットを享受できます:

  • テストの容易さビジネスロジックが外部依存から隔離されており、Mockでテスト可能。
  • 保守性の高さ:UIやDBの変更がコアに影響を与えない。
  • 拡張性:新しいインターフェース(REST APICLI、バッチ)を容易に追加可能。

たとえば、CLIをWeb APIに置き換えたくなった場合でも、UserInteractor には一切変更が必要ありません。


5. トラブルシューティングと注意点

問題 原因 対策
TypeError: Can't instantiate abstract class ポートの抽象クラスを直接インスタンス化しようとした 実装クラス(アダプタ)を使うこと
コードが複雑に感じる 層の分離による初期コスト 小さく始めてスケールさせる設計を意識
循環インポートエラー ドメイン層とインターフェースが直接参照し合っている 依存の方向性を守る(コア→外部のみ)

6. まとめ

ヘキサゴナルアーキテクチャは、複雑なアプリケーションを「コアと外部の明確な分離」という設計哲学で整理する強力な方法論です。Pythonのような動的言語でも、抽象クラスやディレクトリ構成を通じて、この設計手法を実践できます。

今回の例はごく基本的なものですが、実際の業務アプリケーションにも応用可能です。次のステップとしては以下の内容をおすすめします:


参考リンク・書籍