failure of cake php
TRANSCRIPT
CakePHPCakePHP の失敗の失敗談談増えたのは残業時間
株式会社ブルーオーシャン岡田佳典
2008/6/27 1BlueOcean
自己紹介自己紹介株式会社ブルーオーシャン
◦Web コンテンツの企画・開発・運営◦やっと事務所が借りられる
岡田佳典◦Web システム開発◦CakePHP 関連情報の執筆
2008/6/27 2BlueOcean
発表の概要発表の概要CakePHP を使う中で遭遇した7つの失敗を次の観点から紹介します◦背景◦惨劇◦原因◦解決策
今後の開発にお役立てください
2008/6/27 3BlueOcean
第1の失敗第1の失敗
AppController::beforeFilter() にログインチェックを書く
2008/6/27 4BlueOcean
第1の失敗 第1の失敗 - - 背景背景ログインが必要なアプリケーションを作る必要があった
ほとんどのアクションでログインチェックが必要なため、コントローラごとにログインチェックを書きたくなかった
2008/6/27 5BlueOcean
第1の失敗 第1の失敗 – – 惨劇惨劇ログインチェックが不要なアクションを指定できなければならなくなった◦たとえば PagesController の display アクションなど
◦しかも、頼りのコントローラ名とアクション名は空の場合がある
派生クラスで beforeFilter() を実装する場合に parent::beforeFilter() を呼ぶ必要が生じる
2008/6/27 6BlueOcean
第1の失敗 第1の失敗 – – 失敗の原因失敗の原因AppController の beforeFilter() にログインチェックを書けば、すべての派生クラスでログインチェックを有効にできると手抜きをした
オブジェクト指向がもたらす効果がわかっていなかった
2008/6/27 7BlueOcean
第1の失敗 第1の失敗 – – 解決策解決策CakePHP 1.2 の場合は Auth コンポーネントを使う
CakePHP 1.1 の場合でも同等のコンポーネントを作る
2008/6/27 8BlueOcean
第1の失敗 第1の失敗 – – 解決策 解決策 – – 効果効果ログインチェックの有無をクラスの連携で設定できるようになる
意外とこのスタイルの方が保守しやすい
2008/6/27 9BlueOcean
第2の失敗第2の失敗関連するモデルにアソシエーションを動的設定する
2008/6/27 10BlueOcean
第2の失敗 第2の失敗 – – 背景背景多すぎるアソシエーションは重いという先入観から、必要に応じてアソシエーションを設定する方向性で開発していた◦bindModel()
2008/6/27 11BlueOcean
第2の失敗 第2の失敗 – – 惨劇惨劇bindModel() を実行してもアソシエーションが変更されないという不具合に遭遇した◦User モデルが Review を hasMany している時、 Review と Vote を関連づけたい
◦×$this->Review->bindModel(“Vote”);
原因究明に時間がかかった
2008/6/27 12BlueOcean
第2の失敗 第2の失敗 – – 失敗の原因失敗の原因CakePHP の仕様を理解していなかった
2008/6/27 13BlueOcean
第2の失敗 第2の失敗 – – 解決策解決策$this->User->Review-
>bindModel(“Vote”) で解決した
2008/6/27 14BlueOcean
第3の失敗第3の失敗関連するモデルの取得順を動的に指定する
2008/6/27 15BlueOcean
第3の失敗 第3の失敗 – – 背景背景データは表示順の変更やフィルタリングすることを考えて、必要に応じて取得条件を設定する方針で開発を進めていた
2008/6/27 16BlueOcean
第3の失敗 第3の失敗 – – 惨劇惨劇関連しているモデルの取得順を動的に変更できなかった◦User モデルが Review を hasMany している場合
◦×$this->User->Review->order = array();
◦×$order = array(“Review.id DESC”); $this->User->findAll($cond, null, $order);
2008/6/27 17BlueOcean
第3の失敗 第3の失敗 – – 失敗の原因失敗の原因CakePHP の仕様を理解していなかった
bindModel() の用途が完全に見えていなかった
2008/6/27 18BlueOcean
第3の失敗 第3の失敗 – – 解決策解決策bindModel() でアソシエーション設定を上書きすることで実現できた
bindModel() には「上書きする」という用途にも使える◦一度 find 系のメソッドを使えば元の設定に戻るため安心
2008/6/27 19BlueOcean
第4の失敗第4の失敗
何も考えないで自作ビヘイビアの設定値をインスタンスへ保存する
2008/6/27 20BlueOcean
第4の失敗 第4の失敗 – – 背景背景CakePHP 1.2 の登場からモデルの振る舞いを共通化しようというムーブメントが起こった( in 自分)
2008/6/27 21BlueOcean
第4の失敗 第4の失敗 – – 惨劇惨劇同じビヘイビアをアタッチしているモデルで最後の設定しか反映されなくなった◦どうやらビヘイビアのインスタンスはアプリケーションでひとつらしい
2008/6/27 22BlueOcean
第4の失敗 第4の失敗 – – 失敗の原因失敗の原因ビヘイビアはモデルインスタンスごとにインスタンス化されると誤解していた
2008/6/27 23BlueOcean
第4の失敗 第4の失敗 – – 解決策解決策ビヘイビアの設定値をモデル名の要素の下に保存する
$this->__settings[$model->alias][ ~ ]
2008/6/27 24BlueOcean
第5の失敗第5の失敗
コンポーネントのメンバ変数を startup() で初期化する
2008/6/27 25BlueOcean
第5の失敗 第5の失敗 – – 背景背景共通性の高いロジックを外部において再利用する手段としてコンポーネントが用意されていた
これを利用しない手はないと思った
2008/6/27 26BlueOcean
第5の失敗 第5の失敗 – – 惨劇惨劇startup() で初期化したはずのメンバ変数が未定義値に変わってしまった
原因究明に時間がかかった
2008/6/27 27BlueOcean
第5の失敗 第5の失敗 – – 失敗の原因失敗の原因startup() の用途を間違えていたコンポーネントの設計意図を誤解していた◦C++ のトレイトや限定多重継承に近い使い方が正しいみたい
オブジェクト指向の理解が不足していた(教えて詳しい人)
2008/6/27 28BlueOcean
第5の失敗 第5の失敗 – – 解決策解決策メンバ変数は startup() やコンストラクタ以外の場所で初期化する◦↑これらはクローンが実行するから
2008/6/27 29BlueOcean
第6の失敗第6の失敗契約プログラミングを導入する
2008/6/27 30BlueOcean
第6の失敗 第6の失敗 – – 背景背景テストよりも導入しやすく、確実に品質を向上させる仕組みが必要だった
2008/6/27 31BlueOcean
第6の失敗 第6の失敗 – – 惨劇惨劇isset(), array_key_exists(),
is_array(), is_string() を多用する羽目になり、かえって可読性が低下した◦特に Amazon との連携
assert() の中に式を書いてしまったために、どんな条件に違反したのかわからなくなった
2008/6/27 32BlueOcean
第6の失敗 第6の失敗 – – 失敗の原因失敗の原因assert() を書くコストを読み違えた
◦PHP のビルトインコンテナが配列しかないことが一因
◦PHP の配列は連想配列っぽい部分もあれば、そうでないっぽい部分がある
assert() 関数の中に式を書いてしまった◦正しくは恒等式を文字列で渡す
2008/6/27 33BlueOcean
第6の失敗 第6の失敗 – – 解決策解決策テストを使うSet クラスを使うSet::check() で配列のパスを検証Set::extract() で深い配列から目的のデータリストを取得◦ほか CakePHP guide 内で紹介予定
2008/6/27 34BlueOcean
第6の失敗 第6の失敗 – – 解決策 解決策 – – 効果効果ソースコードの行数が3割近く減った
2008/6/27 35BlueOcean
第7の失敗第7の失敗車輪の再開発
2008/6/27 36BlueOcean
第7の失敗 第7の失敗 – – 背景背景いわずもがな
2008/6/27 37BlueOcean
第7の失敗 第7の失敗 – – 失敗の原因失敗の原因いわずもがなあえて言うなら想像力の欠如と調査不足
2008/6/27 38BlueOcean
第7の失敗 第7の失敗 – – 惨劇惨劇弊社で再開発された主な車輪
◦レコードをスレッド形式で取得するメソッド
◦バリデーション機構◦国際化機構◦ログインチェックコンポーネント◦HABTM 取得形式→保存形式の自動変換
2008/6/27 39BlueOcean
第7の失敗 第7の失敗 – – 解決策解決策Model::findAllThreaded() を使用する
CakePHP 1.2 の新しいバリデーションを使用する
i18n, l10n 関連クラスを使用するAuth コンポーネントを使用するSet::extract() を使用する
2008/6/27 40BlueOcean
まとめまとめ
2008/6/27 41BlueOcean
大切なこと大切なこと新しい機能を調べるときには想像力を働かせる
面倒がらずに開発コードも読むCakePHP を書いている人たちのことを想像する
近年の開発手法を勉強する(テストなど)
2008/6/27 42BlueOcean
おしまいおしまいご清聴ありがとうございます
2008/6/27 43BlueOcean