ぷぎがぽぎ このページをアンテナに追加 RSSフィード

2008-09-26

[][]リファクタリング

つい最近 本家のblogsymfonyでのリファクタリング方法についての実例が5日間にわたって紹介されました。もちろんsymfonyを使っている方はもちろん参考になりますし、ファビアンが言いたいことなんかはsymfonyに関係なくリファクタリングのポイントでまとめられています。

ref:

http://www.symfony-project.org/blog/2008/09/18/call-the-expert-a-refactoring-story-part-1-5

http://www.symfony-project.org/blog/2008/09/19/call-the-expert-a-refactoring-story-part-2-5

http://www.symfony-project.org/blog/2008/09/20/call-the-expert-a-refactoring-story-part-3-5

http://www.symfony-project.org/blog/2008/09/21/call-the-expert-a-refactoring-story-part-4-5

http://www.symfony-project.org/blog/2008/09/22/call-the-expert-a-refactoring-story-part-5-5

メンテナンスチーム開発で必要となるポイントを指摘しています。

symfonyを知っていればそれほど難しい内容ではありませんがファビアンの意見を簡単にまとめてみました。

それに、設計勉強会にも都合により出れないのでここで発表代わりに。。(苦笑

1日目

  • リファクタリング前のコードとそのプロジェクト概要

2日目

3日目

  • コントローラー(actionクラス)のリファクタリング
    • コントローラーはフロー部分の担当。それ以外は書くな
      • Criteriaなんてactionクラスに入れちゃ駄目。それはモデルの担当
        • PropelだったらPeerクラスに書くのが正解
      • Userクラスの属性はmyUserクラスでちゃんとラッパすること
        • $this->getUser()->getAttribute('id') と $this->getUser()->getId() どっちが使いやすい?
      • メソッド名はよーく考えて命名することが重要
        • 正しく命名できればドキュメントがなくても何をするメソッドか解るから

4日目

  • 新しいFormフレームワークの使いかた
    • Formフレームワークも小さなMVC構造。Controller部分(sfForm),Model部分(sfValidator),View部分(sfWidget)で構成
      • だからアクションクラスからフォーム部分の処理を完全に分離できるよ
      • たとえば受け取った値を加工してupdateしたいときは updateObjectメソッドで $this->ogjectに変更を加えるのがお作法

5日目

  • Viewに関する部分は極力コントローラーに書くな
<?php use_stylesheet('homepage.css'); ?>

順番を指定したいなら第2引数でfirst, lastが指定可

<?php use_javascript('homopage.js'); ?> 

順番を(ry

まとめ

結果としてコントローラーのコーディング量を減らすことができ、見通しがよくなったよ

リファクタリングの最終目標はなんであれ以下の3つ

  1. よりメンテナンスが容易になるように考慮したコードにすること
  2. 拡張性が優れたコードにすること
  3. 既存のコードをうまく再利用することで新しい機能を書くためのコーディング量を減らすこと

わざわざこういう記事があることからもわかるように、

symfony(他のフレームワークの然り)を使ったからといってすぐにメンテナンス性がよいアプリケーションはできません。

プログラマがしっかりと設計理念を理解しておくことが必要ということですね。

にしても、symfonyってAskeetにしてもそうですがドキュメントの作り方が巧みだなと思う。

2008-09-18

[][]sfFormを楽して可読性を向上させる

1週間ぐらいsfFormと向き合っているにもかかわらず、仲良くなれてない。一通り使うまでしょうがないとわかりつつ。。

そして、symfonyの学習コストは確実にあがっていっている気がする。

ただし、プログラマとしてsymfonyのソースを読み解いたり、実装を理解するのは楽しいもんです。

話がそれそうなので本題。

symfonyの新しいフォームフレームワークとして登場したsfFormですが、なかなか面倒です。

決して楽ができるわけではないというところが痛いところです。

なので、symfonyで開発日記で紹介されているsfFormatasticPluginは導入したほうが良いです。

sfFormtasticPluginを使えばこのようにFormクラスを比較的簡単にYAMLで作り出すことが出来ます。また、Actionクラスは自分でFormクラスを書いていた時と全く同じです。sfFormtasticPluginを使うからといって、Actionクラスに手を入れる必要はありません。

symfony1.1使いに役立つかもしれないsfFormについての知識

ただし、build-formで作成したクラスや上記で作成したFormクラスをそのまま使うことはほとんどなく拡張クラスにて設定を上書きしたりすることになります。

そのときに、自動生成されたFormクラスのソースをコピペして変更したりするとソースの可読性が落ちてしまいます。

というのも、yamlの設定では項目ごとに記述しているのに、ソースでは項目ごとではなく、setterを使ってwidget毎やvalidator毎のメソッドに集約されてしまっているからです。

    $this->setWidgets(array(
      ‘mail’     => new sfWidgetFormInput,
      ‘password’ => new sfWidgetFormInputPassword,
    ));

    $this->setValidators(array(
      ‘mail’     => new sfValidatorString(array(), array(‘required’ => ‘メールアドレスは必須です’)),
      ‘password’ => new sfValidatorString(array(‘min_length’ => 6), array(‘min_length’ => ‘パスワードは6文字以上で設定してください’, ‘required’ => ‘パスワードは必須です’)),
    ));

というわけで、拡張クラスで項目の設定を変更するときは項目名を$keyなどの変数にいれておいて、以下のようなコーディングで項目毎の設定をconfigure()メソッド内に書くようにしています。

    //--------------------------------------------------//
    // mail
    $key = 'mail';
    $this->widgetSchema[$key] = new sfWidgetFormInput();
    $this->widgetSchema->setLabel($key, 'メールアドレス');
    $this->widgetSchema->setHelp($key, 'PCのメールアドレスを入力してください');
    // $this->widgetSchema[$key]->setHidden(true);  // フォームをhiddenにする場合
    $this->validatorSchema[$key] = new sfValidatorString();
    $this->validatorSchema[$key]->setOption('required', true);
    $this->validatorSchema[$key]->setMessage('required', 'メールアドレスは必須です');
    //--------------------------------------------------//
    // password
    $key = 'password';
    $this->widgetSchema[$key] = new sfWidgetFormPassword();
    $this->widgetSchema->setLabel($key, 'パスワード');
    // $this->widgetSchema->setHelp($key, '');
    // $this->widgetSchema[$key]->setHidden(true);  // フォームをhiddenにする場合
    $this->validatorSchema[$key] = new sfValidatorString();
    $this->validatorSchema[$key]->setOption('required', true);
    $this->validatorSchema[$key]->setMessage('min_length', 'パスワードは6文字以上で設定してください');
    $this->validatorSchema[$key]->setOption('min_length', 6);
    $this->validatorSchema[$key]->setMessage('required', 'パスワードは必須です');

この書き方でさきほどの書き方と同じ機能が実装されます。

メリットは

  • 項目毎の設定がわかりやすい。(arrayから可能な限り解放される)
  • 不要な機能はコメントアウトすればいい
  • 機能を追加、変更したい場合は行単位のコピペで対応できる

もちろんデメリットは行数が増える*1。。ですが、メンテナンス性では向上すると思いますがいかがでしょ?

*1:$r = $this->validatorSchema[$key] のようにリファレンス変数を用意するのもありですね

2008-09-17

[] お仕事募集中

業務委託(ニート??)のような形態で仕事をしていますが、もっと人脈を増やさないといけないと色々痛感中。

もちろん仕事につながることも大切ですが、そうでなくても勉強会やイベント(飲みでの会話など)で刺激を受けないと面白くない。

正社員じゃなくなった時点で、もっと活動的になろうとも考えていたのですが、

実質、体調管理の部分で保養したいという希望もあったので結構静かにすごしてきました。

PHP勉強会には参加しようとしても、気づいたときには既に募集が終わってばかりだったともいいますが。。

少しずつリハビリ兼ねて外にも活動していかねば!!

というわけで、外界に繋がりを求めてお仕事&飲みのお誘い募集中です。

2008-09-06

[] バッチのタスクデータベースを使う場合

symfony1.0系とそれ以降の違いで大きなものの1つがバッチ処理の管理方法です。

1.0系ではバッチ用のコントローラーをbatchディレクトリに作成していましたが、1.1系以降ではタスク(コマンド)で管理します。

もちろん、初期化コマンドが用意されているのでgenerate:taskにネームスペースとタスク名をわたすだけでOKです。

$ ./symfony generate:task batch:taskname

で、タスクの中でDBアクセスを行う場合は、本家では

    $databaseManager = new sfDatabaseManager($this->configuration);

を記述するように書かれていますが、

ref: http://www.symfony-project.org/blog/2008/06/14/batches-are-dead-long-life-to-tasks

このまま記述してタスクを実行しても次のようなエラーになります。

$ ./symfony batch:taskname
PHP Catchable fatal error:  Argument 1 passed to sfDatabaseManager::__construct() must be an instance of sfApplicationConfiguration, instance of ProjectConfiguration given, 

原因はアプリケーション名を指定していないからでした。

生成されたタスクファイルの以下の行をコメントアウトを外し、アプリケーション名をオプションで必ず渡すようにします。

  $this->addArgument('application', sfCommandArgument::REQUIRED, 'The application name');

これで、

$ ./symfony batch:taskname admin

のようにアプリケーション名を渡すことでデータベースアクセスが正常にできました。

よく考えてみれば当たり前だけどハマった。

2008-09-03

[] symfony1.0から1.1に慣れる ~ その1 ~

そのうちwikiにまとめた方が有用なんでしょうが、とりあえずここにメモ。

タスクはhelpで確認する

symfony1.1からタスクの利用方法がhelpオプションを指定することで確認できるので見ておいたほうが幸せになれる

$ ./symfony help <タスク名>

エスケープの設定

$ ./symfony generate:app admin --escaping-strategy=on --csrf-secret=HogeHageFuge

エスケープの設定が1.0のころと変わってるので理解しておくこと。

ちなみに、設定ファイルをいじらなくてもアプリケーション作成タスクのオプションでonにすればよい。

というのもescaping-strategyはデフォルトでoffになっているので。

また、csrf-secretはCSRF対策としてのトークンに用いる秘密のキーを設定できます。これもやっておくとよろし

データベースの設定もタスクで

ファイルを直接さわらなくてもタスクが用意されている。

$ ./symfony configure:database

アドミンジェネレータを使う場合は互換モードをonに

symfony1.1はアドミンジェネレータがまだsfFormなどに対応していないため、

compat_10: on にしなければならない。

[symfony1.1][Doctrine] DQL??

Doctrineは直感的なんだけど、DQLを覚えるのが面倒だなぁとぼやいてみる

2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |