Blog

concrete5に「おっぱい問題」は存在するか?

Posted by admin at 8:34 日時 2013/10/03

WordPressの専門家で犬の散歩が日課のミスタージャ○ネットこと @miya0001 さんが『WordPressプラグインのおっぱい問題』なるブログ記事をアップされていました。

要約すると、WordPressではプラグインを入れて行くたびにプションがいっぱいになっていきデータベースから取得するデータが肥大化し、それがパフォーマンスに影響を与える問題がある、という記事です。いやあ、なんと分かりやすい略し方なんだ!

さらに藤本さんが『Movable Typeに「おっぱい問題」はある?』という記事をアップされていて、CMS界隈でおっぱい問題が話題になっているようです。両方の記事のタイトルはともかくとして、面白い話でしたのでconcrete5ではどうなのか書いてみたいと思います。

concrete5での設定データの保存方法

concrete5では、設定(コンフィグ)系のデータの取得・保存には一括して Config クラスを用います。

// Configクラスのインスタンスを作成  $cfg = new Config();    // Configデータの取得  $value = $cfg->get('CONFIG_KEY');    // Configデータを取得して定数に設定(こちらの方が利用頻度が高い)  $cfg->getAndDefine('CONFIG_KEY', $value);  echo CONFIG_KEY;    // Configデータの保存  $cfg->save('CONFIG_KEY', $value);

また、マーケットプレイスから入手できるアドオンやテーマからは、Package クラスを通して設定ファイルの取得・保存を行ないます。Package クラスも内部的には Config クラスを使用しています。

// ハンドルを指定してPackageクラスのインスタンスを取得  $pkg = Package::getByHandle('your_package_handle');    // パッケージの設定データを取得  $value = $pkg->config('CONFIG_KEY');    // パッケージの設定データを保存  $pkg->saveConfig('CONFIG_KEY', $value);

concrete5のConfigデータはいつデータベースから取得されるか

Config クラスのインスタンスは、ConfigStore クラスのインスタンスを静的なプロパティとして保持します。したがって、Config クラスのインスタンスをいくつ作成しても、内部的にはひとつの ConfigStore クラスのインスタンスを共有します。ConfigStore クラスは、インスタンスの作成時にデータベースの Config テーブルから全てのデータを一括で取得し、インスタンス内に連想配列としてデータを保持します。これにより、設定データへのデータベースアクセスを1回に抑え、Config クラスからの問い合わせによりいちいちデータベースにアクセスしないことで高速化を図っています。

要するに、ここまではWordPressとほとんど同じ仕組みってことですね。設計がオブジェクト指向なのが違うくらいです。

concrete5もアドオンをどんどん入れていくと重くなるのか?

WordPressでは、プラグインがアンインストール時の処理を書くことを怠って、オプションデータを掃除しないことが多いのが問題、という指摘がありました。concrete5ではどうでしょうか?

concrete5の拡張パッケージ(アドオンやテーマ)は、全て Package クラスを継承しています。アドオンで独自の処理を追加していない限りは、アドオンのアンインストール時には Package クラスの uninstall() メソッドが呼ばれ、パッケージのデータを自動でお掃除してくれます

concrete5では、ブロックタイプ、テーマ、属性、ジョブ、その他あらゆるオブジェクトがパッケージIDをデータとして持っており、アンインストール時にはパッケージがインストールしたそれらのオブジェクトに関するデータを全て自動で削除します。Config データも例外ではなく、Package クラスを経由して保存した Config データはパッケージのアンインストール時に自動で消去されます。また、concrete5にないオブジェクトを自前で作成している場合も、uninstall メソッドを作っておけばそれが自動で呼ばれるという徹底ぶりです。

したがって、パッケージの作者がアンインストール時の処理をな〜んにも書かなくても、自動でよろしく削除してくれると言うことですね。concrete5はこれだけでなく、開発者がパッケージの機能自体の開発に集中できるよう、めんどくさいところはコアの設計でカバーしてくれるという設計思想になっていますので、追加機能の開発が非常に楽です。

WordPressだと、アンインストールだけでなく、他のプラグインとのコンフリクトの回避方法や、そもそもプラグインの設計まで、全て開発者によって作り方がばらばらで統一されていません(間口が広いとも言えますが)。concrete5の拡張パッケージは必ず Package クラスを継承する必要があるため、ルールに則る必要はありますが、設計が統一されコードが理解しやすいメリットがあります。フレームワークのメリットと同じですね。

WordPressの他の問題

とはいえ、WordPressがプラグインを増やすと重くなるのはそれだけが原因ではないと思いますので、ここでは2点指摘したいと思います。

少ないテーブルを色んな用途に使い過ぎでは?

wp_options テーブルが肥大化する原因は、単にプラグインがオプションデータをアンインストール時に残していくというだけでなく、Transient API が wp_options テーブルを共用するのも問題じゃないかと思います。Transient APIとは、WordPressが内部的に使用しているキャッシュの仕組みです。キャッシュデータがどんどん wp_options テーブルにたまっていくので、プラグインを入れないように気を配ったところで、ほとんど意味はないと思うんですよね。

他にも、同じテーブルを色んな用途に使い回すことが非常に多いと思います。WordPressは11のテーブルをやりくりしていますが、concrete5は200近いテーブルを使用します。concrete5だと拡張パッケージも基本的には既存のテーブルを使い回しせず、データベース設計を行なってテーブルを追加する必要があります。逆にWordPressはデータベース設計ができない人でも開発できる敷居が低い仕組みと言えるのかもしれません。

WordPressではあらゆる場合で全てのプラグインが読み込まれている

プラグインをインストールした時にそのプラグインがエラーを起こすと、フロント画面だけでなく管理画面からログイン画面も全てまっしろになってどうしようもなくなる、というのがWordPressではありがちな現象ですが、これはあらゆる場合で全てのプラグインが読み込まれ処理されているからです。これもプラグインを増やすと重くなる原因じゃないかと思います。

concrete5では、アクセスしたページで使われているパッケージのデータのみ読み込まれます。もしパッケージに問題がありエラーを引き起こしている場合、管理画面ではそのパッケージの設定画面のみエラーで操作できなくなりますが、その他のページには問題がありません。フロント画面で追加パッケージが提供するブロックをページ内に配置していた場合は、そのブロックがエラーで使えなくなるだけで、その他のブロックやページ全体には影響を与えません。このような設計は初期状態では処理が複雑になり動作が重くなる要因かもしれませんが、アドオンを増やすことが直接パフォーマンスに影響を与えませんし、また問題が合った場合も影響範囲が限定されるため、より安心して機能追加を行なうことができる仕組みと言えるのではないでしょうか。

とはいえ、WordPressがダメ、concrete5がイイって言いたいのではなくて。

結局は設計思想の違い、何を捨てて何を取るかってことだと思います。WordPressは単一のアプリケーションとしてよくできていて、そこから大きく拡張せずに使う方が向いているのではないかと思います。カスタマイズも非常に容易で、数行のPHPコードを書き連ねることでほとんどのカスタマイズがまかなえるでしょう。ただし、大きく機能追加しようとすると急に手がかりがなくなり、大変です…。

concrete5はアプリケーションを動かすためのOS的なポジションで、CMSとして必要な機能が最初から盛り込まれているという印象です。機能追加するにはconcrete5の開発のルールに従う必要がありますし、MVC設計やデータベース設計について理解している必要があります。その代わり、そういう手がかりが最初から用意されているため、機能追加するのが楽です。開発者にやさしい。そこがありがたいポイントですね。

願わくば、公式のドキュメントをもう少し充実してくれたらいいんだけどな〜。


Share this entry

Blog Entry Topics