- Data access object(DAO)っていうのは、データベースへのSQL操作をビジネスロジックから切り離して専用のクラスに閉じ込めるデザインパターンのことだよ。
- DBの種類が変わってもビジネスロジック側のコードを一切変えなくて済む疎結合な設計を実現するのがDAOの最大の存在価値で、テスタビリティの向上にも直結する。
- DAOパターンを導入すれば、MySQLからPostgreSQLへの移行やモックを使ったユニットテストが格段に楽になり、チームの開発速度が上がる。
【深掘り】これだけ知ってればOK!
Data Access Object(DAO)パターンは、アプリケーションのデータアクセス層(Persistence Layer)を独立したコンポーネントとして実装するソフトウェアデザインパターンだ。具体的には、UserDAOクラスがgetUserById()・createUser()・updateUser()・deleteUser()といったCRUDメソッドをカプセル化し、サービス層やコントローラはSQLを一切知らずにDAOインターフェースを通じてデータ操作を行う構造を作る。この分離によってビジネスロジックとDB実装の依存関係が切れるため、テスト時にはMockDAOに差し替えるだけでDBなしのユニットテストが実現でき、本番DBへの移行時にはDAOの実装クラスだけを差し替えれば上位層に影響が波及しない。
DAOパターンとRepository パターンはしばしば混同されるが、設計上の意図に違いがある。DAOはデータベーステーブルとの一対一対応に近い粒度でアクセス操作を定義することが多く、永続化のメカニズム(SQLの種類・接続ライブラリ)を隠蔽することが主目的だ。一方Repositoryパターンは集約(Aggregate)単位でドメインオブジェクトのコレクションを抽象化するDDDの概念に近く、複数テーブルをまたぐ操作を単一のリポジトリに集約する傾向がある。現代のWebフレームワークではSpring DataのJpaRepositoryやDjangoのORMが事実上のDAOとRepositoryを統合した形で提供しており、明示的にDAOクラスを作成しないケースも増えている。
マイクロサービス・クラウドネイティブ時代においてDAOパターンの役割は変化しつつある。RDBMSのDAOに加え、DynamoDB・Redis・S3などのNoSQLストレージへのアクセスを統一的なインターフェースで抽象化するアダプターとしてDAOの概念が拡張されているケースが増えている。複数のデータストアを使うサービスでは、ストレージの種類に依存しない汎用なDAOインターフェースを設計することがサービスの可搬性と保守性の鍵となる。
よくある誤解
ORMを使えばDAOは不要になるという誤解
ORMはSQL記述を省略できるが、DAOパターンが解決する「ビジネスロジックとデータアクセスの分離」という関心事は別の問題だ。ORMの呼び出しをコントローラやサービスに直書きすればDAOなしでもORMは動くが、テスタビリティと変更耐性が著しく低下する。DAOはORMの有無に関係なく適用できる設計原則だ。
DAOはJavaだけで使われるパターンなのか?
DAOはJavaのJ2EEパターンとして広まったが、パターン自体は言語非依存だ。Python・Go・TypeScript・PHPなどあらゆる言語でDAOの概念を適用した実装が存在する。「Javaの古い概念」と思って学習を飛ばしてしまうと、現代の設計議論で必要な語彙が欠けることになるのではないだろうか。
会話での使われ方

このサービスクラス、DBのSQL文が直書きされてるから、RDS移行のときに全部書き直しになりますよ。UserDAOを一枚挟んでください。
シニアエンジニアがコードレビューでDAOパターンの欠如を指摘している場面。




ユニットテストでDBに繋げないのはDAOのインターフェースがないからです。IOrderDAOを定義してMockOrderDAOを差し込める設計にすれば、DBなしでサービス層のテストができるようになります。
テスト駆動開発を推進するエンジニアがDAOとモックの関係をチームに説明している場面。




DynamoDBのアクセスロジックをLambda関数に直書きしてたら、後でElastiCacheに切り替えるとき全部書き直しになった。最初からIProductRepositoryで抽象化しておくべきだった。
AWSのサーバーレス開発経験者が設計上の反省を後輩に語っている場面。
【まとめ】3つのポイント
- DAOはビジネスロジックとDB操作を切り離す設計パターン:CRUDメソッドをDAOクラスにカプセル化することで、DBの種類変更・テスト時のモック差し替えが容易になり、システム全体の変更耐性が高まる。
- インターフェースの定義がDAOパターンの肝:具象クラスではなくインターフェースに依存する設計にすることで依存性注入と組み合わせたモック差し替えが可能となり、DBなしのユニットテスト環境が実現できる。
- 現代ではNoSQLストレージへの抽象化にも応用される:DynamoDB・Redis・S3など複数のデータストアを扱うサービスでDAOインターフェースを統一することが、サービスの可搬性と保守コスト削減の鍵となっている。
よくある質問
-
QDAOパターンをPythonで実装する場合のサンプルはありますか?
-
A
IUserDAOという抽象基底クラス(ABCを継承)にget_by_id・create・update・deleteメソッドを定義し、MySQLUserDAOクラスがそれを実装する形が標準的です。DIフレームワーク(injector等)と組み合わせることでテスト時のMock差し替えがより容易になります。
-
QDAOとRepositoryパターンの使い分けはどうすれば良いですか?
-
A
テーブル単位のデータアクセス抽象化が目的ならDAO、ドメイン集約単位のオブジェクト管理が目的ならRepositoryが適しています。DDDを採用しているプロジェクトではRepository、シンプルなCRUDアプリではDAOの方が設計が明快になる傾向があります。
-
QSpring Bootを使う場合DAOは必要ですか?
-
A
Spring DataのJpaRepositoryがDAOとRepositoryの機能を統合して提供するため、多くの場合は明示的なDAOクラスを作る必要はありません。ただし複雑なカスタムクエリや複数データソースを扱う場合は独自のDAOインターフェースを定義する方が保守性が高まることがあります。
-
QData access objectとActive Recordパターンの違いは何ですか?
-
A
Active Recordはデータモデル(エンティティ)自身がDBアクセスメソッドを持つパターンで、RubyのActiveRecordが代表例です。DAOはアクセスロジックをエンティティとは別のクラスに分離します。Active Recordはシンプルさが利点、DAOは関心の分離と疎結合が利点で、複雑なドメインロジックにはDAOが適している傾向があります。
この用語と一緒に知っておきたい用語
| 用語 | この記事との関連 |
|---|---|
| インターフェース | 本記事のテーマと実務上セットで使われることが多い用語です。インターフェースの主要な特徴と用途を理解することで、関連する技術・制度・概念を正確に把握できるようになる |
| データ | 本記事のテーマと実務上セットで使われることが多い用語です。コンピュータが処理する数値や文字、画像といった事実や資料そのもの、それがデータだ |
| テスト | テストとの関係を知ると全体像がつかみやすくなります。テストというのは、作ったソフトウェアが意図した通りに正しく動くかどうかを確かめる検証作業のことなんだ。 |
| DynamoDB | DynamoDBを押さえると本記事の理解がさらに深まります。AWSが提供するフルマネージドのキーバリュー型NoSQL DB。サーバー管理不要で自動スケールし、どんな規模でも一桁ミリ秒以下のレイテンシを保証する |
| データベース | データベースは関連分野でよく登場する重要キーワードです。データを効率よく蓄積・検索・更新・削除できるよう構造化して管理する仕組みの総称。専用エンジンを持ち大量データを高速操作できる |
【出典】参考URL
https://www.oracle.com/java/technologies/dataaccessobject.html:Oracle公式 Core J2EE DAOパターン解説
https://martinfowler.com/eaaCatalog/dataAccessObject.html:Martin Fowler EAA CatalogのDAOパターン解説


コメント