単体テスト自動化と静的解析を阻害する「DBアクセス直書き」の問題点とは?
本記事では、プログラマーやSEの方へ向けて、単体テストの自動化や静的解析を進める際に必ずと言っていいほど問題になる
「DBアクセスを直接コードに書いてしまうことの問題点」について解説します。
私はこれまで業務系Webシステム、社内ツール、バッチ処理など、さまざまな現場で開発とテストを担当してきました。
その中で何度も痛い目を見てきたのが、「とりあえず動けばOK」という発想で書かれたDBアクセス直書きコードです。
この記事では、単なる理論ではなく、実際の現場で何が起きたのか、なぜテストができなくなるのか、
そしてどう改善すればよいのかまでを、できるだけわかりやすい言葉でお伝えします。
DBアクセスを直接書くとはどういうことか?
まずは「DBアクセスを直接書く」とは何かを整理します。
ここでいうDBアクセス直書きとは、次のような状態を指します。
- 業務ロジックの中にSQL文が直接書かれている
- newでDB接続クラスを生成して、その場でクエリを発行している
- テスト用・本番用の切り替えを考慮していない
たとえば、以下のようなイメージです。
public int getUserCount() {
Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM users");
...
}
一見するとシンプルでわかりやすく、「余計なクラスもなくて楽だ」と感じる方も多いと思います。
実際、私自身も新人時代はこのような書き方をよくしていました。
しかし、この「楽さ」が後になって大きな問題を引き起こします。
DBアクセス直書きが単体テスト自動化を妨げる理由
単体テストとは何かを改めて確認する
単体テストとは、1つのクラスやメソッドが正しく動くかを自動で検証するテストです。
ポイントは「自動」で「高速」に「何度でも」実行できることです。
ところが、DBアクセスを直接書いているコードは、この前提条件をことごとく壊してきます。
DBがないとテストできない問題
DBアクセス直書きの最大の問題は、DBが存在しないとテストが実行できない点です。
私が以前関わったプロジェクトでは、単体テストを実行するために、
- ローカルにDBを立てる
- テスト用データを事前に投入する
- テスト後にデータを掃除する
という手順が必要でした。
その結果どうなったかというと、「テストを実行するまでが面倒すぎて誰もやらない」という状態になりました。
テストが遅くなる問題
DBにアクセスするテストは、とにかく遅いです。
数百件の単体テストを実行するたびにDB接続が発生すると、テスト完了まで数分かかることも珍しくありません。
私は一度、「テスト実行に10分以上かかる」プロジェクトに遭遇しました。
結果として、開発者はテストを流さずに修正を進め、バグが量産されるという悪循環に陥りました。
静的解析の観点から見たDBアクセス直書きの問題点
静的解析とは何か
静的解析とは、プログラムを実行せずにコードを解析し、問題点を指摘する仕組みです。
SonarQubeやCheckstyle、PMDなどが代表的なツールです。
責務が肥大化して警告だらけになる
DBアクセス直書きは、1つのクラスに次の責務を押し込みます。
- 業務ロジック
- SQLの組み立て
- DB接続管理
- 例外処理
その結果、クラスは肥大化し、静的解析ツールから
- メソッドが長すぎる
- 複雑度が高い
- 依存関係が強すぎる
といった警告を大量に受けるようになります。
私の経験では、警告が増えすぎると「どうせ全部直せないから無視しよう」という雰囲気が生まれます。
これでは静的解析を導入した意味がありません。
DBアクセス直書きをやめることで得られるメリット
単体テストが爆発的に書きやすくなる
DBアクセスを分離し、インターフェース経由で扱うようにすると、
DBを使わないモックを使ったテストが可能になります。
これにより、
- テストが高速になる
- 環境構築が不要になる
- CIで安定して回せる
というメリットを得られます。
仕様変更に強くなる
DB構造が変わった場合でも、影響範囲を限定できます。
私が経験した現場では、テーブル設計変更のたびに数十クラスを修正していましたが、
DAOを分離したことで修正箇所が数クラスに収まるようになりました。
筆者の体験談:DB直書き地獄からの脱出
あるプロジェクトで、私は「テストを書こう」と提案しました。
しかし返ってきた言葉は、「DBが絡んでるから無理だよ」でした。
実際にコードを見ると、業務ロジックのあらゆる場所にSQLが埋め込まれていました。
そこで私は、まずDAOクラスを作り、インターフェースを定義しました。
最初は「クラスが増えて面倒だ」と言われましたが、
テストが書けるようになった途端、チームの空気が変わりました。
バグ修正時に即座にテストで確認できるようになり、リリース前の不安が激減したのです。
応用編:さらに便利になる設計とテスト手法
DI(依存性注入)を活用する
DIコンテナを使えば、テスト時に簡単にモックへ差し替えできます。
Springを使った現場では、テストコードが劇的にシンプルになりました。
インメモリDBの併用
完全なモックでは不安な場合、H2などのインメモリDBを使う方法も有効です。
本番DBに近い構造で高速なテストが可能になります。
まとめ:DBアクセス直書きをやめることは未来への投資
DBアクセスを直接書くことは、一時的には楽に見えます。
しかし、単体テスト自動化や静的解析を進めようとした瞬間に、大きな足かせになります。
私自身、何度も遠回りをしましたが、今ではDBアクセス分離は必須だと断言できます。
ぜひ本記事をきっかけに、ご自身のコードを見直し、テストしやすい設計へ一歩踏み出してみてください。

コメント