Failure Of Cake PHP

  • 4,824 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
4,824
On Slideshare
0
From Embeds
0
Number of Embeds
3

Actions

Shares
Downloads
30
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

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