コードを眺めてて、これってInterfaceである必要ある?Classでよくない?みたいなことがあったので少しばかり考えてみた。
前章
昔プログラミング(PHP)を習い始めたころ、入門書をいくつか見てみると Interface の項目には必ずと言っていいほど、以下のようなことが書かれている。
複数の異なるクラスに共通の機能を実装するために、その実体を定義することなく指定する仕組みだよー。
↓こんな感じ。
interface Database
{
function listOrders();
function addOrder();
function removeOrder();
...
}
当時の俺「定義しないなら必要ねーじゃねーかよw」
さらにこんな感じの記述も必ずある。
継承した側のクラスで実装しないとエラーになるよー。
↓こんな感じ。
// removeOrder がないよー
// ってことでこれエラーね
class MySqlDatabase implements Database
{
function listOrders()
{
// 実装
}
function addOrders()
{
// 実装
}
}
当時の俺「なんでだよ。おせっかいだよw」
Interfaceの本質
Interface というのは何も Class の抽象化のために用意されているものではない。
そんなことしたいだけなら素直に抽象 Class 使用すればいいだけ。
で、ここから説明ね。
まずさっきも使ったこれ。つまりデータベースにアクセスするインターフェースを用意。
interface Database
{
function listOrders();
function addOrder();
function removeOrder();
...
}
で、実際のデータベースは MySQL かな。じゃあ Databaseインターフェースを継承するクラスを作成しよー。
class MySqlDatabase implements Database
{
function listOrders()
{
// 実装
}
function addOrders()
{
// 実装
}
function removeOrders()
{
// 実装
}
よし、これを Controller で使用してみよー。
$db = new MySqlDatabase();
foreach ($db->listOrders() as $order) {
// 作業
}
三ヵ月後。
やっぱデータベースは Oracle にしよーっと。
ってことでこれ作成↓
class OracleDatabase implements Database
{
function listOrders()
{
// 実装
}
function addOrders()
{
// 実装
}
function removeOrders()
{
// 実装
}
Controller も変更しなくちゃ!
// 変更はこれだけ -> (MySqlDatabase => OracleDatabase)
$db = new OracleDatabase();
foreach ($db->listOrders() as $order) {
// 作業
}
つまり Interface というのは、この場合で言うと、データベースにアクセスする必要はあるけど、それをどのように実行(implement は実行するっていう意味)するかは Controller からは別に知る必要はないじゃんってこと。
Interface はプログラマの好きなように実行してくれてかまわん。しかもコードの修正は超簡単みたいな。
妄想
ちなみに interface って日本語で言うと「接点、仲立ち、連絡役」みたいな意味。
プログラムのこの機能に Interface って名づけた人もおそらく英語圏の出身者だと思うけど、おそらく Controller から見て 仲立ちである Interface に(このケースで言うと)「データベースのアクセスは頼むよ。だけど実際のアクセス方法とビジネスロジック(データベースから取得したデータをゴニョゴニョすること)はこっちで知る必要もないし、知りたくも無いからw」っていう思想で interface っていう名前を付けたのだろうと勝手に妄想した。
ちなみに、
こっちで知る必要もないし、知りたくも無いからw
ってのがいわゆる疎結合ってやつね。
疎結合だとそれぞれのコンポーネントの結びつきが弱いから、例えば上の例で言うと、 「Model である MySqlDatabase を修正しても、Controller である Controller.php には抜本的な修正は必要ないよね」って感じ。
だからどうした
登場人物:
生徒(プログラミングは習い始めて3ヶ月)
先生(現場経験あり)
生徒「いや、けどどのみち上の例で言っても、俺が作成しようと思ってるちょっとした Webアプリってデータベースは MySQL以外使う気ねーし、Interface って使い道が無いんだけど」
先生「そのとおり。どのみち実装者が君だけのそのゴミアプリには必要ない」
生徒「じゃあいったいどんなときに役に立つの?」
先生「大勢の人に使ってもらうために公開するフレームワークとかライブラリなんかを記述するときかな。だって大勢の人が使用するんだから、人によっては Oracle や Postgresも使われるだろうから汎用性は大切だよね」
生徒「そうなんだ」
先生「だいたいデータベースの種類によって別の独立したメソッド作ってたんじゃあ、ひとつひとつ説明するのも面倒だよw それなら Interface を使用して呼び出し方は一緒にしてたほうが楽じゃね?それに関連して"継承クラスでは実装を強制する"ってもの、例えば『このデータベースではこのメソッドは無いからなっ』て言われたら、使用している側からしたらカオスじゃん。そこんところは統一しろよみたいな」
生徒「なるほどな」
終章
ってことで妄想終わり。
参考:http://php.net/manual/ja/language.oop5.interfaces.php#107364