Perl Hackers Hub

第47回 Anikiで学ぶ実践的なO/Rマッパの作り方(3)

この記事を読むのに必要な時間:およそ 4.5 分

(1)こちら⁠2)こちらから。

Aniki─⁠─これまでになかった抽象度を実現したO/Rマッパ

これまでのO/Rマッパが持つ問題を解消するために筆者が新しく開発したO/RマッパがAnikiです。⁠3)ではAnikiの設計と実装について,特徴的な部分とその考え方を説明します。

既存のO/Rマッパとの違い

AnikiはこれまでのO/Rマッパと比べて,抽象度の低いデータベース操作ができるO/Rマッパとして設計されています。すべてのデータベース操作を行うメソッドは,抽象的な操作の名前ではなくデータベースにどのようなSQLを発行するかというより低レベルな操作で命名されています。たとえば,Anikiのデータベース操作を行うメソッドの名前はselectinsert_and_fetch_rowなどにしています。これにより,O/Rマッパに明るくない人でも,どこでどのようなSQLが発行されるのかが比較的容易にわかります。

反面として,O/Rマッパを使う以上は高い抽象度でデータを扱いたいケースが多いはずです。Anikiでは行オブジェクトを不変オブジェクトImmutable Objectとして扱うことで,既存のO/Rマッパに近い触り心地を実現しつつも,SQLの発行は明示的に行うインタフェースを使うことを強制できるようにしています。行オブジェクトが状態を持たないことによってデータが変更された可能性を考慮する必要がなくなりデバッグが容易になるなど,行オブジェクトを不変オブジェクトとして扱うメリットはたくさんあります。

また,⁠2)で紹介したようなCPANモジュールに積極的に機能を委譲しており,さらにMouseのメタクラスを利用することで,本質的でないコードをなくして読みやすく,拡張しやすくしています。この点についてはのちほど実装を踏まえて詳しく説明します。

本当に作る必要があるのか

表1に挙げたような既存のO/Rマッパが抱える問題は,根本的な機能設計レベルで起きているものです。既存のO/Rマッパで問題を解決するためには非常に大きな変更を行う必要があります。変更によりインタフェースにも非互換が発生するため,すでに広く使われているO/Rマッパを変更することは難しいでしょう。

もちろん,O/Rマッパを使わないという選択もあります。しかし,筆者が以前行っていたソーシャルゲームのゲームサーバ開発のように,巨大な構造を持ったデータベースを利用するアプリケーションの開発においては,テーブルの数が100を超えることも珍しくありません。それくらいの規模になるとテーブルどうしの関係性の管理を補助しコードの抽象度を高めてくれるO/Rマッパを使わない開発は考えられません。

また,⁠2)のとおり今日では先人たちの不断の努力の結果としてデータベースプログラミングに必要な各機能が別々のCPANモジュールとして提供されています。これらを使って新しいO/Rマッパを構築することは以前と比べると極めて容易になったと言えるでしょう。そこで,これらの問題を解決することを目指して,自分の考える最高のO/Rマッパを新たに構築しようと作り始めたものがAnikiです。

セットアップ

Anikiについて詳しく知るために,どのように使えるのかを見ていきましょう。

まずはcpanmAnikiをインストールします。

$ cpanm Aniki

インストールに成功すると,install-anikiコマンドが利用可能になります。Anikiを利用するネームスペースとモジュールの生成先ディレクトリを指定して実行すればセットアップが完了します。

MyApp::DBネームスペースにセットアップする場合

$ install-aniki --lib=./lib MyApp::DB

セットアップされるモジュールは表2のとおりです。

表2 install-anikiがセットアップするモジュール

名前機能
MyApp::DBデータベースを表現する
MyApp::DB::Schemaスキーマ定義を定義する
MyApp::DB::Filterinflate/deflateなどのフィルタを表現する
MyApp::DB::ResultSQLの実行結果を表現する
MyApp::DB::Rowデータベースの行を表現する
スキーマ定義

install-anikiで生成したMyApp::DB::Schemaでは,DBIx::Schema::DSLを利用してスキーマを定義します。

サンプルとして,DBIx::Schema::DSLを利用して簡単な地理とその間のフライトを管理するスキーマを用意しました図1)⁠

図1 サンプルのER図

図1 サンプルのER図

create_table country => columns {
    integer 'id', primary_key;
    varchar 'name', size => 32;
    varchar 'region', size => 32;
};

create_table city => columns {
    integer 'id', primary_key;
    varchar 'name', size => 32;
    integer 'country_id';

    belongs_to 'country';
};

create_table flight => columns {
    integer 'id', primary_key;
    varchar 'name', size => 32;
    integer 'departure_city_id';
    integer 'arrival_city_id';

    fk 'departure_city_id' => 'city', 'id';
    fk 'arrival_city_id' => 'city', 'id';
};

次項以降では,これらのモジュールとスキーマをベースにAnikiの各機能を見ていきましょう。

著者プロフィール

佐藤健太(さとうけんた)

1990年,千葉県生まれ。2011年に株式会社モバイルファクトリーに新卒入社し2016年9月より現職であるDeNAのオープンプラットフォーム事業部に勤務。Japan Perl Associationの理事も務める。

2014年5月にGotanda.pmを発足。YAPC::AsiaやYAPC::Japan,YAPC::EUなどでもスピーカーをするなど,Perl関連のコミュニティを中心に活動している。

好きな言語はPerlとGo。日本酒と寿司とロックンロールが好物。バンド活動も行っている。

URL:https://karupas.org/

コメント

コメントの記入