Runner in the High

技術のことをかくこころみ

database/sqlとdatabase/sql/driverの関係性に学ぶインターフェイス設計

golangのdatabase/sqlには設計に関するドキュメントが用意されており、これが興味深い。

ドキュメント自体は非常に短い。以下のリンクでサクッと読める。

golang.org

中でも個人的に印象的なのは以下の説明で、ここからgolangにおけるdatabase/sqlの設計思想が見て取れる。

* Provide a generic database API for a variety of SQL or SQL-like
  databases.  There currently exist Go libraries for SQLite, MySQL,
  and Postgres, but all with a very different feel, and often
  a non-Go-like feel.

...

* Separate out the basic implementation of a database driver
  (implementing the sql/driver interfaces) vs the implementation
  of all the user-level types and convenience methods.
  In a nutshell:

  User Code ---> sql package (concrete types) ---> sql/driver (interfaces)
  Database Driver -> sql (to register) + sql/driver (implement interfaces)

ざっくり言うと、golangにおけるdatabase/sqlはユーザーアプリケーションに対して一般的なSQLの操作インターフェイスのみを提供するということを示している。

翻って、database/sqlを利用するアプリケーションはそのインターフェイスを介して操作する対象のSQLデータベースがなんであるかを意識しなくてもよい。アプリケーションはdatabase/sqlインターフェイスにのみ依存している状態であり、まさにクリーンアーキテクチャなどでいうところの抽象への依存(依存性逆転)そのものだ。

database/sql/driverの存在

ではdatabase/sqlSQLiteMySQLを利用するとき、実装がdatabase/sqlに依存しているかというとそんなことはない。実装(ドライバ)はdatabase/sqlとは別にdatabase/sql/driverというインターフェイスに依存している。上の抜粋でいうところの sql/driver (interfaces) がそれにあたる。

便宜的にこれをユーザ層、I/F、ドライバ層と分類してみると、以下のような依存関係になる。

f:id:IzumiSy:20210806113753p:plain
依存関係図

この依存関係図から、golangのdatabase/sqlパッケージは"アプリケーションでSQLを利用したいユーザー"に向けたインターフェイスを提供し、一方でsql/driverは"ドライバの実装者"に向けたインターフェイスを提供しているということが読み取れる。

利用者と実装者でI/Fを分離することのメリットは、インターフェイスを小さくかつ関心の対象を限定したものにできるというところにある。database/sqlにおいてはコネクションプーリングやセッション管理などの概念はインターフェイスに登場せず関心の対象外であり、一方でsql/driverにおいてはSessionResetterやConnectorの形で概念が登場し実装を用意することが要求される。このようにインターフェイスが分離されていることで、利用者は「database/sqlではコネクションプールやセッション管理はしなくてもいいんだな」とインターフェイスから理解でき、思考のコストが減る。

ジェネリックSQLインターフェイスのみを使う限りは依存のほとんどはdatabase/sqlのみに限定できる。もしRDBMS製品に固有な機能を使いたい場合には例外的にドライバから提供されているインターフェイスを直接呼び出せばいい。その場合にはドライバの実装に対する依存が生まれてしまうが、いずれにしても必要に応じて外部装置への依存性を利用者の側から選択できるようになっている点がdatabase/sqlの設計思想の優れたところなのかな、と思う。

参考情報

英語の記事だが、以下の記事も同じようなことを解説している。

eli.thegreenplace.net