<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>境界設計  |  Python-memo｜自動化・AI・Web開発の実験室</title>
	<atom:link href="https://python.cbagames.jp/tag/%E5%A2%83%E7%95%8C%E8%A8%AD%E8%A8%88/feed/" rel="self" type="application/rss+xml" />
	<link>https://python.cbagames.jp</link>
	<description>Pythonで、できるをふやそう。</description>
	<lastBuildDate>Fri, 26 Dec 2025 08:26:26 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://python.cbagames.jp/wp-content/uploads/2025/06/cropped-497d491d54402de785c9e043bfa0620a-32x32.png</url>
	<title>境界設計  |  Python-memo｜自動化・AI・Web開発の実験室</title>
	<link>https://python.cbagames.jp</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Pythonの境界設計とは？I/Oとロジック分離で“変更に強い”コードにする方法</title>
		<link>https://python.cbagames.jp/2025/12/26/python-boundary-design-io-logic-separation/</link>
					<comments>https://python.cbagames.jp/2025/12/26/python-boundary-design-io-logic-separation/#respond</comments>
		
		<dc:creator><![CDATA[asukapy]]></dc:creator>
		<pubDate>Fri, 26 Dec 2025 08:26:24 +0000</pubDate>
				<category><![CDATA[クラス設計・OOP入門]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Python設計]]></category>
		<category><![CDATA[typing.Protocol]]></category>
		<category><![CDATA[クリーンアーキテクチャ]]></category>
		<category><![CDATA[テスト設計]]></category>
		<category><![CDATA[依存性逆転]]></category>
		<category><![CDATA[境界設計]]></category>
		<guid isPermaLink="false">https://python.cbagames.jp/?p=719</guid>

					<description><![CDATA[目次 はじめになぜPythonでも「境界設計」が必要なのか変更が連鎖するコードの典型例フレームワーク依存が強すぎる問題テストが書けない＝設計が苦しいサイン境界設計の思想的な原点（考え方を先に押さえる）関心の分離（SoC） [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2"><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">なぜPythonでも「境界設計」が必要なのか</a><ol><li><a href="#toc3" tabindex="0">変更が連鎖するコードの典型例</a></li><li><a href="#toc4" tabindex="0">フレームワーク依存が強すぎる問題</a></li><li><a href="#toc5" tabindex="0">テストが書けない＝設計が苦しいサイン</a></li></ol></li><li><a href="#toc6" tabindex="0">境界設計の思想的な原点（考え方を先に押さえる）</a><ol><li><a href="#toc7" tabindex="0">関心の分離（SoC）というシンプルだけど強力な考え方</a></li><li><a href="#toc8" tabindex="0">依存関係の向きがコードの寿命を決める</a></li><li><a href="#toc9" tabindex="0">「フレームワーク中心」から「ユースケース中心」へ</a></li></ol></li><li><a href="#toc10" tabindex="0">Python的に理解する「境界」の正体</a><ol><li><a href="#toc11" tabindex="0">よく語られる4つのレイヤー</a></li><li><a href="#toc12" tabindex="0">Pythonでは「厳密に分けすぎない」が正解</a></li><li><a href="#toc13" tabindex="0">境界が曖昧なコードのサイン</a></li></ol></li><li><a href="#toc14" tabindex="0">実装で効く：I/Oとロジックを分離するディレクトリ設計</a><ol><li><a href="#toc15" tabindex="0">よくあるBefore：すべてが混ざった構成</a></li><li><a href="#toc16" tabindex="0">After：境界を意識したシンプルな分割</a></li><li><a href="#toc17" tabindex="0">ディレクトリごとの役割を整理する</a></li><li><a href="#toc18" tabindex="0">「最初から完璧」を目指さなくていい</a></li></ol></li><li><a href="#toc19" tabindex="0">抽象化の要：Protocol / ABCで境界を作る</a><ol><li><a href="#toc20" tabindex="0">なぜ抽象がないと境界が壊れるのか</a></li><li><a href="#toc21" tabindex="0">ABCで作る明示的な契約</a></li><li><a href="#toc22" tabindex="0">Protocolで作るPythonらしい境界</a></li><li><a href="#toc23" tabindex="0">ABCとProtocol、どちらを使うべき？</a></li></ol></li><li><a href="#toc24" tabindex="0">依存性注入（DI）で境界を“動かす”</a><ol><li><a href="#toc25" tabindex="0">newしないだけで設計は一段よくなる</a></li><li><a href="#toc26" tabindex="0">コンストラクタDIの基本形</a></li><li><a href="#toc27" tabindex="0">エントリーポイントで依存を組み立てる</a></li><li><a href="#toc28" tabindex="0">手動DIで十分なケースは多い</a></li><li><a href="#toc29" tabindex="0">それでも辛くなったらDIコンテナ</a></li></ol></li><li><a href="#toc30" tabindex="0">境界設計 × テスト：なぜテストが一気に楽になるのか</a><ol><li><a href="#toc31" tabindex="0">境界がないとテストが重くなる</a></li><li><a href="#toc32" tabindex="0">境界があるとテスト対象が一気に小さくなる</a></li><li><a href="#toc33" tabindex="0">モックが最小限で済む理由</a></li><li><a href="#toc34" tabindex="0">「テストしづらさ」は設計の警告灯</a></li></ol></li><li><a href="#toc35" tabindex="0">境界設計とドメイン思考の相性</a><ol><li><a href="#toc36" tabindex="0">Entityを「データ入れ物」で終わらせない</a></li><li><a href="#toc37" tabindex="0">ユースケースは「業務の流れ」を語る場所</a></li><li><a href="#toc38" tabindex="0">CRUD地獄から抜け出すヒント</a></li></ol></li><li><a href="#toc39" tabindex="0">まとめ</a><ol><li><a href="#toc40" tabindex="0">この記事で伝えたかったポイント</a></li><li><a href="#toc41" tabindex="0">私の実務での実感</a></li><li><a href="#toc42" tabindex="0">次にやるならこの一歩</a></li><li><a href="#toc43" tabindex="0">あわせて読みたい</a></li><li><a href="#toc44" tabindex="0">参考文献</a></li></ol></li><li><a href="#toc45" tabindex="0">よくある質問（Q&amp;A）</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">はじめに</span></h2>



<p>Pythonで開発していると、最初はスッキリ書けていたはずのコードが、機能追加を重ねるうちにどんどん触りづらくなっていく……そんな経験はありませんか？</p>



<p>ちょっとした仕様変更のつもりが、API、DB、画面表示まで一緒に修正することになったり、テストを書こうとしたらデータベースや外部APIの準備が必要になったり。「なんでこんなに大変なんだろう？」と感じたことがある人は少なくないと思います。</p>



<p>その原因の多くは、<strong>I/O処理（DB・API・UIなど）とビジネスロジックが密結合している</strong>ことにあります。 ロジックの中に外部とのやり取りが混ざっていると、コードは一気に壊れやすく、変更に弱い構造になってしまうんです。</p>



<p>そこで登場するのが<strong>「境界設計」</strong>という考え方です。 境界設計は、I/Oとロジックを明確に分け、依存関係の向きを整理することで、コードを「変更しやすく」「テストしやすく」する設計アプローチです。</p>



<p>この記事では、Clean Architectureなどで語られる境界の考え方をベースにしつつ、<strong>Pythonの実務で無理なく使える形</strong>に落とし込んで解説していきます。 難しい理論を振りかざすのではなく、「なぜ必要なのか」「どこから手を付ければいいのか」が自然と理解できる構成にしています。</p>



<p>設計に自信がない人も、すでにコードが複雑になって悩んでいる人も、読み終わる頃には<strong>「まずここを分ければいいんだ」</strong>という一歩が見えるはずです🙂 それでは、Pythonの境界設計の世界を一緒に見ていきましょう。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc2">なぜPythonでも「境界設計」が必要なのか</span></h2>



<p>境界設計というと、「大規模システム向け」「意識高い設計」というイメージを持たれがちですが、 実はPythonのような軽量な言語ほど、その恩恵を受けやすいと私は感じています。</p>



<p>理由はシンプルで、Pythonは<strong>書こうと思えば何でもすぐ書けてしまう</strong>からです。 DBアクセスもAPI呼び出しも、ビジネスロジックも、同じ関数・同じファイルに自然と集まっていきます。</p>



<h3 class="wp-block-heading"><span id="toc3">変更が連鎖するコードの典型例</span></h3>



<p>たとえば、次のような流れで開発が進むことはよくあります。</p>



<ul class="wp-block-list">
<li>最初は1画面・1APIだけのシンプルな処理</li>



<li>仕様追加で条件分岐が増える</li>



<li>DB構造変更に合わせてロジックも修正</li>



<li>画面表示の都合でロジックにif文が増殖</li>
</ul>



<p>この状態では、「価格計算を少し変えたい」だけなのに、 API、DB、画面、テストコードまで同時に触る必要が出てきます。<br>変更の影響範囲が読めず、修正が怖くなっていくんですよね。</p>



<h3 class="wp-block-heading"><span id="toc4">フレームワーク依存が強すぎる問題</span></h3>



<p>DjangoやFastAPIはとても便利ですが、便利すぎるがゆえに、 ビジネスロジックがフレームワークの中に溶け込んでしまいがちです。</p>



<p>その結果、</p>



<ul class="wp-block-list">
<li>別のフレームワークへ移行しづらい</li>



<li>CLIやバッチ処理で再利用できない</li>



<li>フレームワーク込みでないとテストできない</li>
</ul>



<p>といった「身動きの取れないコード」になってしまいます。</p>



<h3 class="wp-block-heading"><span id="toc5">テストが書けない＝設計が苦しいサイン</span></h3>



<p>「テストを書くのが面倒」というより、 <strong>テストを書くための準備が重すぎる</strong>状態になっていませんか？</p>



<p>ロジックの中にI/O処理が混ざっていると、 テストのたびにDB接続、外部API、設定ファイルの準備が必要になります。 これでは、テストを書く気力が削られてしまいます。</p>



<p>境界設計は、この問題を<strong>構造そのものから解決する</strong>考え方です。 ロジックをI/Oから切り離すことで、変更にもテストにも強いコードへと変えていけます。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、その境界設計がどんな思想をベースにしているのか、 「考え方」の部分から整理していきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc6">境界設計の思想的な原点（考え方を先に押さえる）</span></h2>



<p>境界設計をうまく使いこなすために大切なのは、 いきなりディレクトリ構成やコード例を見ることではありません。<br>まずは<strong>「なぜその分け方をするのか」</strong>という思想を押さえておくことが重要です。</p>



<p>この考え方の土台になっているのが、Clean Architecture や SOLID 原則で語られる設計思想です。 Python特有の話に入る前に、共通するエッセンスだけを整理しておきましょう。</p>



<h3 class="wp-block-heading"><span id="toc7">関心の分離（SoC）というシンプルだけど強力な考え方</span></h3>



<p>境界設計の出発点は、とてもシンプルです。</p>



<p><strong>「同じ理由で変更されるものはまとめ、違う理由で変更されるものは分ける」</strong></p>



<p>価格計算のルールと、DBへの保存方法は、変更される理由がまったく違います。 にもかかわらず同じ場所に書いてしまうと、 本来関係ないはずの修正が連鎖していきます。</p>



<h3 class="wp-block-heading"><span id="toc8">依存関係の向きがコードの寿命を決める</span></h3>



<p>境界設計でもっとも重要なのが、<strong>依存関係の向き</strong>です。</p>



<p>原則はひとつだけ。</p>



<p><strong>依存は常に「外側」から「内側」へ向ける</strong></p>



<p>ここでいう内側とは、ビジネスルールやユースケースなど、 アプリケーションの「本質」にあたる部分です。<br>逆に、フレームワーク、DB、外部API、UIといったものは外側の存在になります。</p>



<p>内側のコードが外側を知らなければ、 DBをPostgreSQLからSQLiteに変えても、 Web APIをCLIツールに置き換えても、 ビジネスロジックはそのまま生き残れます。</p>



<h3 class="wp-block-heading"><span id="toc9">「フレームワーク中心」から「ユースケース中心」へ</span></h3>



<p>多くのプロジェクトでは、 「Djangoアプリ」「FastAPIプロジェクト」という意識から設計が始まります。</p>



<p>でも境界設計が目指すのは、 <strong>「何をするシステムなのか」が構造から伝わる状態</strong>です。</p>



<p>たとえば、</p>



<ul class="wp-block-list">
<li>注文を確定する</li>



<li>ユーザーを登録する</li>



<li>支払いを検証する</li>
</ul>



<p>こうしたユースケースが主役で、 フレームワークはあくまで「実行するための道具」に過ぎません。</p>



<p>この考え方を体系的にまとめたのが、次の一冊です。</p>



<p><strong>Clean Architecture 達人に学ぶソフトウェアの構造と設計</strong><br>✅ <a rel="noopener" target="_blank" href="https://amzn.to/4seW53K">Amazonでチェックする</a>｜ ✅ <a rel="noopener" target="_blank" href="https://a.r10.to/hkOqm7">楽天でチェックする</a></p>



<p>正直、すべてをそのままPythonに当てはめる必要はありません。 ただ、「なぜ境界が必要なのか」「なぜ依存の向きを守るのか」を理解するうえで、 これ以上に分かりやすい原典はないと私は思います。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、これらの思想を踏まえたうえで、<br><strong>Python的に境界をどう捉え、どう分けるか</strong>を具体的に見てい</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc10">Python的に理解する「境界」の正体</span></h2>



<p>ここまでで、境界設計の思想的な背景は押さえられたと思います。 ただ、このままだと「で、Pythonでは結局どう分ければいいの？」という疑問が残りますよね。</p>



<p>この章では、Clean Architectureで語られる層構造をベースにしつつ、 <strong>Pythonの現場で無理なく使える形</strong>に翻訳していきます。</p>



<h3 class="wp-block-heading"><span id="toc11">よく語られる4つのレイヤー</span></h3>



<p>境界設計では、システムを同心円状のレイヤーとして捉えます。 名前だけ見ると難しそうですが、役割はとてもシンプルです。</p>



<ul class="wp-block-list">
<li><strong>Entities（エンティティ）</strong><br>ビジネスのルールそのもの。 価格計算や状態遷移など、「会社として変えにくいルール」を持つ。</li>



<li><strong>Use Cases（ユースケース）</strong><br>アプリケーションとして何をするか。 エンティティをどう使うかを定義する“司令塔”。</li>



<li><strong>Interface Adapters（境界・アダプター）</strong><br>Web、DB、外部APIとの橋渡し役。 データ形式の変換や呼び出しの仲介を担当。</li>



<li><strong>Frameworks &amp; Drivers（外側の世界）</strong><br>Django、FastAPI、ORM、DB、UIなど、変化しやすい技術要素。</li>
</ul>



<p>重要なのは、<strong>この分類を厳密に守ることではありません</strong>。 大切なのは「どこが変わりやすく、どこが守るべき中核なのか」を意識することです。</p>



<h3 class="wp-block-heading"><span id="toc12">Pythonでは「厳密に分けすぎない」が正解</span></h3>



<p>PythonでClean Architectureをそのまま再現しようとすると、 ファイルやクラスが増えすぎて逆に分かりづらくなることがあります。</p>



<p>そこでおすすめなのが、次のような割り切りです。</p>



<ul class="wp-block-list">
<li>エンティティとユースケースは「ロジック層」としてまとめてもOK</li>



<li>重要なのは「I/Oを含まない純粋なコード」が存在すること</li>



<li>フレームワークのコードがロジックを支配しない構造にする</li>
</ul>



<p>つまり、<strong>完全な層構造よりも、依存の向きが守られているか</strong>が判断基準になります。</p>



<h3 class="wp-block-heading"><span id="toc13">境界が曖昧なコードのサイン</span></h3>



<p>自分のコードに境界があるかどうかは、次の質問でチェックできます。</p>



<ul class="wp-block-list">
<li>この処理、DBやAPIなしでテストできる？</li>



<li>Web以外（CLI・バッチ）から再利用できる？</li>



<li>フレームワークを外したら何も残らない？</li>
</ul>



<p>もし「全部つらい…」と感じたら、 それは境界がまだ曖昧なサインです。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、こうした考え方を踏まえて、 <strong>実際にどうディレクトリを分け、構造として境界を作るのか</strong>を 具体例と一緒に見ていきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc14">実装で効く：I/Oとロジックを分離するディレクトリ設計</span></h2>



<p>境界設計は思想だけ分かっていても、実装に落とせなければ意味がありません。 この章では、<strong>Pythonで現実的に運用しやすいディレクトリ構成</strong>を例に、 I/Oとロジックをどう分けるかを見ていきます。</p>



<h3 class="wp-block-heading"><span id="toc15">よくあるBefore：すべてが混ざった構成</span></h3>



<p>境界を意識せずに成長したプロジェクトでは、 次のような構成になっていることが多いです。</p>



<pre class="wp-block-code"><code>app/
├─ main.py
├─ api.py
├─ models.py
├─ services.py
└─ db.py
</code></pre>



<p>一見すると分かれているように見えますが、 実際には <code>services.py</code> の中でDBアクセスやAPIレスポンスの加工、 ビジネスルールが混在しているケースがほとんどです。</p>



<h3 class="wp-block-heading"><span id="toc16">After：境界を意識したシンプルな分割</span></h3>



<p>まず目指したいのは、次のような最低限の分離です。</p>



<pre class="wp-block-code"><code>src/
├─ domain/
│  ├─ entities.py
│  └─ services.py
├─ usecases/
│  └─ order_usecase.py
├─ interfaces/
│  ├─ repository.py
│  └─ notifier.py
├─ infrastructure/
│  ├─ db_repository.py
│  └─ email_notifier.py
└─ entrypoints/
   └─ api.py
</code></pre>



<p>ポイントは、<strong>domain / usecases が I/O を一切知らない</strong>ことです。 DBや外部APIの詳細は、すべて <code>infrastructure</code> 側に閉じ込めます。</p>



<h3 class="wp-block-heading"><span id="toc17">ディレクトリごとの役割を整理する</span></h3>



<ul class="wp-block-list">
<li><strong>domain</strong><br>エンティティや純粋なビジネスルール。フレームワーク非依存。</li>



<li><strong>usecases</strong><br>アプリケーションの振る舞いを定義。domainをどう使うかを書く。</li>



<li><strong>interfaces</strong><br>RepositoryやNotifierなどの「契約（抽象）」を定義。</li>



<li><strong>infrastructure</strong><br>DB、外部API、メール送信などの具体実装。</li>



<li><strong>entrypoints</strong><br>FastAPI / CLI / バッチなど、外部からの入口。</li>
</ul>



<p>この構成なら、Web APIをやめてCLIに切り替えても、 触るのは <code>entrypoints</code> だけで済みます。 ロジック層はそのまま再利用できます。</p>



<h3 class="wp-block-heading"><span id="toc18">「最初から完璧」を目指さなくていい</span></h3>



<p>いきなりこの構成をすべて作る必要はありません。</p>



<ul class="wp-block-list">
<li>まずは「DBアクセスを別ファイルに出す」</li>



<li>次に「ロジックをフレームワークから切り離す」</li>



<li>必要になったらインターフェースを切る</li>
</ul>



<p>境界設計は、<strong>一度で完成させる設計ではなく、育てていく設計</strong>です。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、この構造を支える重要な要素、 <strong>Protocol / ABC を使った「境界の作り方」</strong>を解説します。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc19">抽象化の要：Protocol / ABCで境界を作る</span></h2>



<p>ディレクトリを分けただけでは、まだ境界設計は完成していません。 本当に重要なのは、<strong>「内側が外側を知らない状態」をコードで保証する</strong>ことです。</p>



<p>そのために登場するのが、<strong>抽象化（インターフェース）</strong>です。 Pythonでは主に <code>ABC</code>（抽象基底クラス）と <code>Protocol</code> の2つが使われます。</p>



<h3 class="wp-block-heading"><span id="toc20">なぜ抽象がないと境界が壊れるのか</span></h3>



<p>たとえばユースケースの中で、次のようなコードを書いてしまうとどうなるでしょうか。</p>



<pre class="wp-block-code"><code>def create_user():
    conn = PostgresConnection()
    conn.save(...)
</code></pre>



<p>この時点で、ユースケースは<strong>特定のDB実装に強く依存</strong>しています。 DBを差し替えたい、テストではメモリ実装を使いたい、 そう思った瞬間に修正が必要になります。</p>



<p>境界設計では、ユースケースは 「保存できる何か」があることだけを知っていれば十分です。</p>



<h3 class="wp-block-heading"><span id="toc21">ABCで作る明示的な契約</span></h3>



<p><code>abc.ABC</code> を使うと、 「このメソッドを必ず実装してください」という契約を明示できます。</p>



<pre class="wp-block-code"><code>from abc import ABC, abstractmethod

class UserRepository(ABC):
    @abstractmethod
    def save(self, user) -&gt; None:
        pass
</code></pre>



<p>この形はJavaやC#に慣れている人には分かりやすく、 設計意図を強く伝えたい場面に向いています。</p>



<h3 class="wp-block-heading"><span id="toc22">Protocolで作るPythonらしい境界</span></h3>



<p>一方で <code>typing.Protocol</code> は、 Pythonのダックタイピングを活かした抽象化です。</p>



<pre class="wp-block-code"><code>from typing import Protocol

class UserRepository(Protocol):
    def save(self, user) -&gt; None:
        ...
</code></pre>



<p>この場合、継承は不要で、 <code>save()</code> メソッドを持っていれば Repositoryとして扱えます。</p>



<p>静的型チェック（mypyなど）と組み合わせることで、 <strong>柔らかいのに壊れにくい境界</strong>を作れるのが強みです。</p>



<h3 class="wp-block-heading"><span id="toc23">ABCとProtocol、どちらを使うべき？</span></h3>



<ul class="wp-block-list">
<li>設計を強く固定したい → ABC</li>



<li>柔軟性・Pythonらしさを重視 → Protocol</li>



<li>テストダブルを簡単に差し替えたい → Protocol</li>
</ul>



<p>正解は1つではありません。 大切なのは、<strong>ユースケースが具体実装をnewしない</strong>ことです。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、この抽象をどうやって実装に結び付けるのか、 <strong>依存性注入（DI）</strong>という考え方を解説していきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc24">依存性注入（DI）で境界を“動かす”</span></h2>



<p>Protocol や ABC で境界を定義できても、 それを実際に使えなければ意味がありません。 そこで必要になるのが <strong>依存性注入（Dependency Injection / DI）</strong> です。</p>



<p>DIという言葉だけ聞くと難しそうですが、 やっていることはとてもシンプルです。</p>



<p><strong>「必要なものは自分で作らず、外から渡してもらう」</strong></p>



<h3 class="wp-block-heading"><span id="toc25">newしないだけで設計は一段よくなる</span></h3>



<p>境界が壊れているコードでは、 ユースケースの中で具体クラスを直接生成してしまいがちです。</p>



<pre class="wp-block-code"><code>class UserService:
    def create(self, user):
        repo = SqlUserRepository()
        repo.save(user)
</code></pre>



<p>この書き方だと、UserServiceは <code>SqlUserRepository</code> 以外を受け付けません。 テストや差し替えが一気に難しくなります。</p>



<h3 class="wp-block-heading"><span id="toc26">コンストラクタDIの基本形</span></h3>



<p>これをDIで書き直すと、次のようになります。</p>



<pre class="wp-block-code"><code>class UserService:
    def __init__(self, repo: UserRepository):
        self.repo = repo

    def create(self, user):
        self.repo.save(user)
</code></pre>



<p>UserServiceは 「保存できる何か」があることしか知りません。 具体的なDB実装は、外側の世界の責任になります。</p>



<h3 class="wp-block-heading"><span id="toc27">エントリーポイントで依存を組み立てる</span></h3>



<p>依存関係を組み立てるのは、 APIやCLIなどのエントリーポイントです。</p>



<pre class="wp-block-code"><code>repo = SqlUserRepository()
service = UserService(repo)
</code></pre>



<p>この構造のおかげで、 テストでは簡単にスタブやフェイクに差し替えられます。</p>



<h3 class="wp-block-heading"><span id="toc28">手動DIで十分なケースは多い</span></h3>



<p>小〜中規模のプロジェクトでは、 この手動DIだけで十分なことがほとんどです。</p>



<ul class="wp-block-list">
<li>依存関係が追いやすい</li>



<li>魔法が少なくデバッグしやすい</li>



<li>学習コストが低い</li>
</ul>



<h3 class="wp-block-heading"><span id="toc29">それでも辛くなったらDIコンテナ</span></h3>



<p>クラスが増え、 依存関係の組み立てが煩雑になってきたら、 DIコンテナの導入を検討してもOKです。</p>



<p>ここで大事なのは、 <strong>「DIコンテナを使うこと」ではなく 「DIできる設計になっていること」</strong>です。</p>



<p>既存コードを段階的に良くしていく流れについては、 次の一冊がとても参考になります。</p>



<p><strong>リファクタリング（第2版）</strong><br>✅ <a rel="noopener" target="_blank" href="https://amzn.to/4bdhzaW">Amazonでチェックする</a>｜ ✅ <a rel="noopener" target="_blank" href="https://a.r10.to/hg6PpP">楽天でチェックする</a></p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、境界設計がもたらす最大の恩恵のひとつ、 <strong>「テストが楽になる理由」</strong>を具体的に見ていきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc30">境界設計 × テスト：なぜテストが一気に楽になるのか</span></h2>



<p>境界設計の効果をいちばん実感しやすいのが、テストです。 「設計を変えただけで、こんなに書きやすくなるの？」と驚く人も多いと思います。</p>



<p>その理由はシンプルで、 <strong>テストしたいロジックが、I/Oから完全に切り離される</strong>からです。</p>



<h3 class="wp-block-heading"><span id="toc31">境界がないとテストが重くなる</span></h3>



<p>境界が曖昧なコードでは、 1つのテストを書くために次のような準備が必要になります。</p>



<ul class="wp-block-list">
<li>テスト用DBの起動</li>



<li>接続設定やマイグレーション</li>



<li>外部APIのモック設定</li>
</ul>



<p>本来確認したいのは 「価格計算が正しいか」「状態遷移が正しいか」なのに、 周辺準備ばかりに時間を取られてしまいます。</p>



<h3 class="wp-block-heading"><span id="toc32">境界があるとテスト対象が一気に小さくなる</span></h3>



<p>境界設計をすると、テストの主役は <strong>ユースケースやドメインロジック</strong>になります。</p>



<pre class="wp-block-code"><code>def test_create_user():
    repo = InMemoryUserRepository()
    service = UserService(repo)

    service.create(user)

    assert repo.saved_user == user
</code></pre>



<p>DBもAPIも不要で、 処理の流れと結果だけを素直に確認できます。</p>



<h3 class="wp-block-heading"><span id="toc33">モックが最小限で済む理由</span></h3>



<p>境界がはっきりしていると、 「どこを差し替えればいいか」が明確になります。</p>



<ul class="wp-block-list">
<li>Repositoryはフェイク実装に差し替え</li>



<li>Notifierはダミー実装に差し替え</li>



<li>フレームワークはテスト対象外</li>
</ul>



<p>無理にモックライブラリを多用しなくても、 素直なクラスでテストダブルを作れるのは大きなメリットです。</p>



<h3 class="wp-block-heading"><span id="toc34">「テストしづらさ」は設計の警告灯</span></h3>



<p>テストが書きづらいとき、 それはテスト技術の問題ではなく、 <strong>設計が苦しがっているサイン</strong>であることが多いです。</p>



<p>境界設計は、 テストのためだけのテクニックではありません。<br>テストしやすい＝理解しやすく、変更しやすいコードだということです。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、もう一段踏み込んで、 <strong>境界設計とドメイン思考の関係</strong>について解説していきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc35">境界設計とドメイン思考の相性</span></h2>



<p>境界設計を進めていくと、 あるところでこんな違和感を覚えることがあります。</p>



<p>「構造はきれいになったけど、ロジックが薄い気がする」 「結局、if文が増えているだけでは？」</p>



<p>これは失敗ではなく、<strong>次のステップへ進むサイン</strong>です。 そこで重要になるのが、<strong>ドメイン思考</strong>です。</p>



<h3 class="wp-block-heading"><span id="toc36">Entityを「データ入れ物」で終わらせない</span></h3>



<p>境界設計を始めたばかりの頃は、 Entityがただのデータクラスになりがちです。</p>



<pre class="wp-block-code"><code>class Order:
    def __init__(self, price, status):
        self.price = price
        self.status = status
</code></pre>



<p>これでも構造的には分離できていますが、 ビジネスルールが外に漏れ出しやすくなります。</p>



<p>ドメイン思考では、 <strong>「ルールはデータの近くに置く」</strong>ことを重視します。</p>



<pre class="wp-block-code"><code>class Order:
    def confirm(self):
        if self.status != "draft":
            raise ValueError("確定できない状態です")
        self.status = "confirmed"
</code></pre>



<p>こうすることで、 不正な状態遷移を自然に防げるようになります。</p>



<h3 class="wp-block-heading"><span id="toc37">ユースケースは「業務の流れ」を語る場所</span></h3>



<p>ユースケースの役割は、 細かい計算を詰め込むことではありません。</p>



<p><strong>業務として何が起きるのか</strong>を、 上から読んで分かる形で表現することです。</p>



<ul class="wp-block-list">
<li>注文を受け付ける</li>



<li>在庫を確認する</li>



<li>価格を確定する</li>



<li>通知を送る</li>
</ul>



<p>このレベルで処理が読めると、 コード自体が仕様書の代わりになります。</p>



<h3 class="wp-block-heading"><span id="toc38">CRUD地獄から抜け出すヒント</span></h3>



<p>ドメイン思考を取り入れると、 「Create / Update / Delete」中心の設計から、 「意味のある操作」中心の設計に変わります。</p>



<p>境界設計は構造を守り、 ドメイン思考は中身を豊かにする。<br>この2つは、とても相性がいい組み合わせです。</p>



<p>ドメインの考え方をやさしく理解するなら、 次の一冊がとても参考になります。</p>



<p><strong>ドメイン駆動設計入門</strong><br>✅ <a rel="noopener" target="_blank" href="https://amzn.to/4jowgdt">Amazonでチェックする</a>｜ ✅ <a rel="noopener" target="_blank" href="https://a.r10.to/hgH8up">楽天でチェックする</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc39">まとめ</span></h2>



<p>ここまで、Pythonにおける境界設計について、 考え方から実装、テスト、ドメイン思考まで順番に見てきました。</p>



<p>境界設計という言葉は少し大げさに聞こえるかもしれませんが、 本質はとてもシンプルです。</p>



<p><strong>「I/Oとビジネスロジックを分ける」</strong><br>まずは、これだけで十分です。</p>



<h3 class="wp-block-heading"><span id="toc40">この記事で伝えたかったポイント</span></h3>



<ul class="wp-block-list">
<li>変更に弱いコードの多くは、依存関係の向きが壊れている</li>



<li>境界設計はPythonでも現実的に使える</li>



<li>完璧なClean Architectureを再現する必要はない</li>



<li>Protocol / ABC + DI で「守れる境界」が作れる</li>



<li>テストしやすさは、設計の健全さを映す鏡</li>
</ul>



<h3 class="wp-block-heading"><span id="toc41">私の実務での実感</span></h3>



<p>私自身、最初から境界設計を意識していたわけではありません。 「テストが書きづらい」「修正が怖い」という違和感から、 少しずつI/Oとロジックを分けるようになりました。</p>



<p>すると、設計を変えただけなのに、 コードの見通しがよくなり、 「どこを直せばいいか」で悩む時間が一気に減りました。</p>



<p>境界設計は、 コードを“賢くする魔法”ではありません。 でも、<strong>コードを長く健康に保つための習慣</strong>にはなります。</p>



<h3 class="wp-block-heading"><span id="toc42">次にやるならこの一歩</span></h3>



<p>もし今のコードが少しでも触りづらいと感じているなら、 次のどれか1つだけ試してみてください。</p>



<ul class="wp-block-list">
<li>DBアクセスをロジックから切り離す</li>



<li>newしているクラスを外から渡す</li>



<li>Protocolで「できること」を定義する</li>
</ul>



<p>小さな一歩でも、 境界は確実に育っていきます。</p>



<p>境界設計はゴールではなく、 よりよい設計へ進むための土台です。 ぜひ、自分のプロジェクトに合った形で取り入れてみてください 🙂</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><span id="toc43">あわせて読みたい</span></h3>



<p>境界設計の考え方を実務でさらに活かすために、 関連するテーマの記事もあわせて読んでみてください。<br>今回の内容とつながりが強く、理解が一段深まります。</p>



<ul class="wp-block-list">
<li><a target="_blank" href="https://python.cbagames.jp/2025/12/19/python-project-structure-src-layout/">Pythonプロジェクトのディレクトリ構成入門｜srcレイアウトで迷わない設計例</a><br><small>境界設計を支える土台として、プロジェクト全体の構造をどう整理するかを解説しています。</small></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/12/20/python-type-hints-guide/">Python型ヒント実践入門｜Type Hintsでコード品質を上げる方法</a><br><small>Protocolや境界の契約をより強固にするための型ヒント活用法を紹介しています。</small></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/12/21/python-strategy-pattern/">Pythonで学ぶStrategyパターン｜if文地獄から抜け出す設計思考</a><br><small>境界設計と相性の良い設計パターンを、具体例ベースで解説しています。</small></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/09/19/clean-code-rules/">【実務で評価される】読みやすく変更しやすい「綺麗なコード」の書き方</a><br><small>境界設計を導入したあとに意識したい、コードの読みやすさ・保守性の話です。</small></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><span id="toc44">参考文献</span></h3>



<ul class="wp-block-list">
<li><a rel="noopener" target="_blank" href="https://deepengineering.substack.com/p/clean-architecture-essentials-transforming">Clean Architecture Essentials: Transforming Complex Systems</a></li>



<li><a rel="noopener" target="_blank" href="https://www.geeksforgeeks.org/system-design/complete-guide-to-clean-architecture/">Complete Guide to Clean Architecture</a></li>



<li><a rel="noopener" target="_blank" href="https://python.plainenglish.io/is-clean-architecture-still-clean-in-2025-a27bf239fa7c" class="broken_link">Is Clean Architecture Still Clean in 2025?</a></li>



<li><a rel="noopener" target="_blank" href="https://github.com/valignatev/ddd-dynamic">ddd-dynamic（GitHub）</a></li>



<li><a rel="noopener" target="_blank" href="https://dev.to/markparker5/python-architecture-essentials-building-scalable-and-clean-application-for-juniors-2o14">Python Architecture Essentials: Building Scalable and Clean Applications</a></li>



<li><a rel="noopener" target="_blank" href="https://en.wikipedia.org/wiki/Entity%E2%80%93control%E2%80%93boundary">Entity–Control–Boundary（Wikipedia）</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><span id="toc45">よくある質問（Q&amp;A）</span></h2>



<div class="wp-block-cocoon-blocks-faq faq-wrap blank-box block-box not-nested-style cocoon-block-faq"><dl class="faq"><dt class="faq-question faq-item"><div class="faq-question-label faq-item-label">Q</div><div class="faq-question-content faq-item-content">境界設計は小規模なPythonプロジェクトでも必要ですか？</div></dt><dd class="faq-answer faq-item"><div class="faq-answer-label faq-item-label">A</div><div class="faq-answer-content faq-item-content">
<p>必ずしも最初からフルセットで導入する必要はありません。 ただし、小規模でも<strong>I/Oとロジックを分ける</strong>だけで、 後から機能追加や修正がかなり楽になります。</p>



<p>特に「将来もう少し大きくなりそう」「あとから人が増えそう」な場合は、 最低限の境界を早めに作っておく価値は高いです。</p>
</div></dd></dl></div>



<div class="wp-block-cocoon-blocks-faq faq-wrap blank-box block-box not-nested-style cocoon-block-faq"><dl class="faq"><dt class="faq-question faq-item"><div class="faq-question-label faq-item-label">Q</div><div class="faq-question-content faq-item-content">Djangoの models.py は Entity と考えていいのでしょうか？</div></dt><dd class="faq-answer faq-item"><div class="faq-answer-label faq-item-label">A</div><div class="faq-answer-content faq-item-content">
<p>厳密には<strong>そのままでは Entity とは言えません</strong>。 DjangoのモデルはORMやDBの都合を強く含んでいるため、 Clean Architectureでいう純粋なEntityとは役割が異なります。</p>



<p>実務では、</p>



<ul class="wp-block-list">
<li>models.py は「永続化用のデータ構造」</li>



<li>domain側に「業務ルールを持つクラス」を別で置く</li>
</ul>



<p>という分け方をすると、境界がかなり分かりやすくなります。</p>
</div></dd></dl></div>



<div class="wp-block-cocoon-blocks-faq faq-wrap blank-box block-box not-nested-style cocoon-block-faq"><dl class="faq"><dt class="faq-question faq-item"><div class="faq-question-label faq-item-label">Q</div><div class="faq-question-content faq-item-content">Protocol と ABC、結局どちらを使うのが正解ですか？</div></dt><dd class="faq-answer faq-item"><div class="faq-answer-label faq-item-label">A</div><div class="faq-answer-content faq-item-content">
<p>正解はありませんが、Pythonでは<strong>Protocolの方が相性がいいケースが多い</strong>です。</p>



<ul class="wp-block-list">
<li>テストダブルを簡単に作りたい → Protocol</li>



<li>設計を厳密に固定したい → ABC</li>



<li>柔軟性と読みやすさを重視 → Protocol</li>
</ul>



<p>大切なのは選択そのものより、 <strong>ユースケースが具体クラスに依存していないこと</strong>です。</p>
</div></dd></dl></div>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.cbagames.jp/2025/12/26/python-boundary-design-io-logic-separation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
