Skip to main content

🧱 DDD for python

モジュラモノリス + ドメイン駆動設計のカーネル。業務語彙をひとつも持たないことを設計制約にしている。

アーキテクチャ契約の検査は clean-architecture が担う。 このリポジトリは「import できるカーネル」だけを配る。

入っているもの

提供するもの
合成 AppModule / CompositeModule — モジュールの宣言点と合成ルート
集約 DomainEvent / DomainEventPublisher / DomainEventSubscriber / DomainRegistry
ユースケース UnitOfWork / ApplicationServiceLifeCycle / @transactional
outbox StoredEvent / EventStore / EventContextProvider
inbox ConsumedNotification / ConsumedNotificationStore / MessageSubscriber
発行 Notification / NotificationPublisher / PublishedNotificationTracker
アダプタ InMem*(テスト用) / SQLAlchemyUnitOfWork(extras: sqlalchemy
適合テスト ddd4py.testing.verify_* — 自分のアダプタ実装が契約を満たすか検証する

導入

uv add ddd4py
uv add "ddd4py[sqlalchemy]"   # SQLAlchemy アダプタも使う場合

トランザクションと配送の保証

@transactional の内側で publish されたドメインイベントは、集約の更新と同一トランザクションで outbox(StoredEvent)に追記される。ネストした境界は最外に join し、内側で失敗すれば最外まで巻き戻る (部分 commit を許さない)。

受信側は MessageSubscriber._dispatch が listener ごとにトランザクションを開始し、 consumed marker の INSERT(claim-before-process)と listener の副作用を単一トランザクションで commit する (Idempotent Consumer / transactional inbox)。at-least-once の重複は marker の unique 制約が先勝ち 1 つに絞る。

実行文脈というただ 1 つの拡張点

カーネルは「いま誰のリクエストを処理しているか」を知らない。知っているのは、outbox にそれを刻印する ことと、受信時にそれを確立することだけ。

from ddd4py import EventContext, EventContextProvider

class TenantContextProvider(EventContextProvider):
    def current(self) -> EventContext:
        tenant = CurrentTenant.get()
        return EventContext(partition_key=tenant.id, payload=tenant.to_dict())

    @contextmanager
    def bind(self, context: EventContext) -> Iterator[None]:
        with CurrentTenant.of(context.payload).bind():
            yield

単一テナントなら NullEventContextProvider のままでよい。

案件ごとの差し替え

CompositeModule は並べた順に DI を登録し、後ろに置いたモジュールが前の束縛を差し替える。 案件固有の実装は継承や上書きではなく、後ろにモジュールを足すことで注入する。

CompositeModule([Core(), Authority(), Tenant(), AcmeOverrides()])

適合テスト

自分のアダプタ実装が契約を満たすかを、利用側の CI で検証する。

from ddd4py.testing import verify_consumed_notification_store

def test_postgresql_consumed_notification_store(store):
    verify_consumed_notification_store(store)

開発

task init          # 依存インストール
task test          # テスト
task style:check   # ruff / mypy
task style:check:arch   # clean-architecture による自分自身への契約検査

リリース

PyPI への公開は GitHub Release をトリガーに、Trusted Publishing (OIDC) で自動実行される。 API トークンはリポジトリに置かない。

# 1. pyproject.toml の version を上げて main へマージする
# 2. その version と同じタグで Release を作る (v プレフィックス付き)
gh release create v0.1.0 --generate-notes

タグと pyproject.toml の version が食い違うとワークフローは公開前に落ちる。 __version__pyproject.toml から読むため、バージョンを書き換える箇所は pyproject.toml の 1 行だけ。

ライセンス

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ddd4py-0.1.0.tar.gz (59.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ddd4py-0.1.0-py3-none-any.whl (42.4 kB view details)

Uploaded Python 3

File details

Details for the file ddd4py-0.1.0.tar.gz.

File metadata

  • Download URL: ddd4py-0.1.0.tar.gz
  • Upload date:
  • Size: 59.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ddd4py-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c001dd1207aa68523f134de84221e0df309e8803356a58b6890c7e82bb3ed372
MD5 afb19facfd728349237587f805cb98e1
BLAKE2b-256 e51f72e79d99e3a7587859250e7be5163c914fbc9f7f8edcb7ccff56c9a91553

See more details on using hashes here.

Provenance

The following attestation bundles were made for ddd4py-0.1.0.tar.gz:

Publisher: publish.yml on theindiehacker/ddd4py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ddd4py-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ddd4py-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 42.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ddd4py-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 902063b677b01735c93da0e270b56384d0d37364e58e92bccb6c9938a9630543
MD5 69b15f5330c96d9504a5458ca2bad7e9
BLAKE2b-256 24d96f0ae3a9e9b4d665df05d7bd392955fd2a066f96eb50ae0045e40c72b588

See more details on using hashes here.

Provenance

The following attestation bundles were made for ddd4py-0.1.0-py3-none-any.whl:

Publisher: publish.yml on theindiehacker/ddd4py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.1

2 files

0.2.0

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page