ソフトウェアを開発するときに仕様書を書くべき3つの理由
土曜日, 7月 5th, 2008 Posted in C++, PHP | No Comments »「Joel on Softwere」で、機能仕様書を書く重要性が延々と述べられているので、ちょっとまとめてみます。いきなりコーディング始めていませんか?
プログラムをデザインする
仕様書の最も重要な役割はプログラムをデザインすることだ。
仕様書を書くという行為自体によって-プログラムがどう機能するか詳細に記述するということによって-プログラムを実際にデザインするように強いられるのだ。
ここでいう仕様書とは機能仕様書のことで、内部仕様書(技術仕様書)のことではないです。機能仕様書とは、ユーザの観点から製品がどのように動くかを記述したドキュメントです。ダイアログとかメニューとかの仕様を書くアレです。
機能仕様書を書くことによって、プログラムがどのように動くかを深く考えることになります。これから作ろうとしているソフトウェアの動きを文章で書き、簡単な絵を添付した場合、上司や顧客からダメだしをされてもすぐに書き換えることができます。一方、2週間掛けて書いたプログラムをダメだしされた場合は・・・!?
アジャイル開発におけるテストファーストも、関数をコーディングする前に関数のテストを書くことによって、その関数の入力と出力の組み合わせを細かく考えます。そうすることで、その関数の仕様を詳細に検討することになります。
作ろうとするものがどう動くかをまず考えることが、デザインにつながります。
コミュニケーションにかかる時間を節約できる
開発のテスト期間中に、どんどん報告されるバグを片っ端からかたづけているとき、スピーディーに改修をこなしているアナタの集中力はMAX!(この状態をフロー状態と言います。)
しかし、突然鳴り出す電話。相手は試験チームのアイツ。いつもくだらない質問で電話してくるアイツです。
試験チームのアイツ:
「音楽CDを再生しながらプロパティダイアログを開くと、CDが停止するんですけど、これ不具合ですか?」
はぁ?不具合なわけないじゃん。つか今頃そんな質問すんなYO!
アナタ:
「それは仕様です。」
試験チームのアイツ:
「では仕様書への記載お願いします。」
げ。書いてなかったっけ?
こんな経験たぶん誰にでもあるんじゃないですか?ボクだけですか?
さて、ここからまた改修作業に戻るわけですが、「ピープルウェア」によるとさっきのフロー状態まで戻るのに15分はかかります。あぁ、なんという無駄。
2分間の仕様書への追記をサボったために、電話対応+フロー状態への復帰で20分の貴重な時間が無駄になります。20分の無駄も問題ですが、仕事が中断したことによるイライラで仕事へのモチベーションが下がってしまうことのほうが大問題です。
仕様書を書いておけば、こんなことにはならないのです。
スケジュールが立てられない
製品を開発するには時間がかかり、そしてお金がかかります。スケジュールを立てられるだけの仕様書がないということは、製品を開発するのにどれくらい時間がかかり、どれくらいのお金がかかるか分からないということです。
あなたは値段を見ずにジーンズを買ったりしないだろう。
まとめ
「Joel on Softwere」の仕様書を書く理由を自分なりに解釈してますが、ほかにも仕様書を書かないことによってこんな問題があるよってのがあれば教えて欲しいです。仕様書の書き方については「達人プログラマー」が参考になります。これはまたいつかまとめたいと思います。できれば。
参考資料
AGAG – Amazonアソシエイトサポートツール リリース
日曜日, 6月 8th, 2008 Posted in AGAG, cakePHP, PHP | No Comments »Amazonアソシエイト・プログラム(アフィリエイト)の利用をサポートするAGAGというサービスを開始しました。
AGAG – Amazonアソシエイトサポートツール
http://www.agag.its55.com/
Amazonアソシエイト・プログラムを使用して雑誌などを紹介しようとすると、雑誌が発売されるたびにリンクを変更しなくてはいけなくて、とても面倒でした。そこで、キーワードを登録しておくと自動で最新の商品を表示するサービスを作ってみました。
商品を検索するキーワードを登録しておくと、AGAGの自動サーチ機能が毎日自動でAmazonに検索をかけて、その検索結果を新しい商品から指定個数分表示します。AGAGが発行するコードをブログなどに貼っておくと、勝手にブログに表示される商品が新しいものに変わります。
このサービスを利用するには、ユーザ登録が必要です。
このサービスはCakePHPを使って作りました。初めてCakePHPで作ったサービスで、CakePHPってどんな感じかなというのを探るために作りました。
作ってみた感想ですが、CakePHPいい!
それほど難しいことはしてなくて、CakePHPができる範囲内で作ればかなり楽です。まあセッション周りとかちょこちょこ思い通りにならないこともあったけど、それを妥協しても作りやすさを選んだほうがプライベートで作るにはいいのかなと思ってます。
AGAGに関しての質問や要望などありましたら、このブログにてご連絡ください。
AGAGは今後機能追加などしていく予定です。
coreserverにgo-pearをインストールする
月曜日, 5月 26th, 2008 Posted in PHP, サーバー | 2 Comments »coreserverにPEARの管理ツールgo-pearをインストールしてみました。手順は次のとおり。
/public_html以下のブラウザからアクセスできるところにgo-pearのファイルをコピーするディレクトリを作成します。テキトウに。PEARをインストールするディレクトリはブラウザからアクセスできないところにしたほうがいいでしょう。今回は、次のディレクトリにインストールしました。
- /virtual/xxx/lib/go_pear/
パーミッションは777としときます。
go-pearはhttp://pear.php.net/go-pearをすべてコピー&ペーストで「go-pear.php」というファイル名でローカルに保存した後サーバへアップロードしました。
ブラウザからgo-pear.phpにアクセスします。「Welcome to go-pear 1.1.1!」のページでは、Next>>をクリックします。
Configurationの「1. Installation prefix ($prefix)」にインストール先のディレクトリを指定します。
- /virtual/xxx/lib/go_pear/
「10. Filename of WebFrontend」にブラウザからアクセスできるディレクトリを指定します。Installボタンをクリックするとインストールが開始し、しばらくたつとインストール完了の画面に移行します。
coreserverではPHPはデフォルトでSAFEMODEで動いています。PEARの管理画面はSAFEMODEだと使えないみたいなので、CGIで動かすように設定する必要があります。CGIで動かすには、PHPをCGIとして動かす方法について – CORESERVER.JP:コアサーバーに書いてあるように以下の内容を.htaccessとしてファイルに保存しサーバの「10. Filename of WebFrontend」で指定したディレクトリへアップロードします。
- AddHandler application/x-httpd-phpcgi .php
PEARの管理画面には認証をかけたほうがいいので、Basic認証の設定をしときます。「10. Filename of WebFrontend」で指定したディレクトリの.htaccessに以下を付け加えます。
- AuthType Basic
- AuthName "Input your ID and Password."
- AuthUserFile /virtual/xxx/.htpassword
- require valid-user
coreserverの管理画面で「ツール」から.htpasswordに記述する文字列を生成し、その文字列を.htpasswordにコピー&ペーストし、AuthUserFileで指定したディレクトリに保存します。
PEARを使う場合は、PHPのインクルードパスにPEARのパスを追加します。たとえばPHPのコードでインクルードパスを追加する場合は次のように実装します。
- $path = "/virtual/xxx/lib/go_pear/PEAR/";
- $inc_path = get_include_path();
- set_include_path(get_include_path() . PATH_SEPARATOR . $path);
cakePHPのセッションでハマる
金曜日, 3月 21st, 2008 Posted in cakePHP, PHP | No Comments »cakePHPを使って簡単なサイトを作っているんですが、セッションまわりで謎が多いのでちょっとまとめます。(自分用)
まず、セッションに入れたはずなのに画面遷移するとデータがなくなっている現象から。
HogeControllerのDoSomethingというアクションで、次のようにセッションにデータを入れます。
- $this->Session->write( 'search_category', $category );
- $this->Session->write( 'search_word', $word );
そしてDoSomethingのviewでは、DoOtherへリンクしているとします。
アクションDoOtherでセッションを確認すると、次のようになっていました。
- [search_category]=;
- [search_word]=;
DoSomethingで入れた値がDoOtherでは消えています。しかしキーは残っています。
cakePHPのフォーラムで次のようなスレッドを発見。
“cake1.1.18にversionアップしたらSessionが使えない?” フォーラム – CakePHP Users in Japan
どうやらCAKE_SECURITYがhightだとセッション開始のたびに
- $this->renew();
が呼ばれ
- session_regenerate_id()
されてしまうようです。
なのでとりあえずCAKE_SECURITYをmediumに変更。
んが、これでも問題は解決せず。
んで、同じくcakePHPフォーラムで次のようなスレッドを発見。
“セッションまわりの挙動がおかしい?時” フォーラム – CakePHP Users in Japan
viewで使っている画像のパスがrelative(相対パス?)だったら、アクションが複数回呼ばれることがあるらしい。
開発中のサイトでは、コントローラの$layoutは\cake\libs\view\templates\layouts\default.thtmlを\app\views\layouts\default.thmlにコピーしてレイアウトに関する部分だけ変更して使っていたので、
- <link rel="shortcut icon" href="<?php echo $this->webroot . 'favicon.ico'; ?>" type="image/x-icon" />
の部分を削除するとDoOtherでもセッションから正しいデータを取得することができました。
もう一つセッションに関する問題があるんですが、長くなりそうなので別記事で。
cakePHPでJavascriptを出力する
日曜日, 2月 3rd, 2008 Posted in cakePHP, PHP | 2 Comments »HTMLに以下のようなJavascriptのコードを埋め込み、srcでPHPなどの動的な処理をするファイルを指定すると、静的なHTMLに動的な処理を埋め込むことが出来ます。アクセス解析のサービスなどでよくありますね。
- <script src="xxx.php" type="text/javascript"></script>
で、srcにPHPのファイルを指定し、PHP側でJavascriptのコードを出力する処理を書けば実現できます。詳しいやり方は、PHP:JS(JavaScript)からPHPを呼び出しHTML上に出力する方法に丁寧に書かれているので参考にしてください。
で、cakePHPでこの処理を書こうと思ったわけです。まずは、Javacsriptを呼び出すHTML側では、
- <script src="/app/[コントローラー]/[メソッド]/[プロパティ]" type="text/javascript" charset="utf-8"></script>
のように書きます。controller側のメソッドでは、最初に
- header("Content-type: application/x-javascript");
を書く必要があるようです。viewでheaderを出力すると、Javascriptとして認識されません。
cakePHPの/app/core.phpのDEBUGモードが0以外だと余計なモノが出力されるのでJavascriptとして認識されないみたいです。ボクは動作確認はDEBUGモードを0にしてやっています。特定の場合だけDEBUG出力を抑制することは出来ないモノですかね。
Amazon Webサービスを利用するサイトをcakePHPで構築
月曜日, 1月 14th, 2008 Posted in cakePHP, PHP | 5 Comments »せっかくのMVCなので、Amazon Webサービスからデータを取得する処理をModelとして実装してみました。
ModelではとりあえずfindAllのみをオーバーライドします。後で必要になれば必要な関数をオーバーライドするつもりです。Modelは以下の通り。
- class Aws extends AppModel {
- var $name = 'Aws';
- var $useTable = false;
- function findAll( $category, $keyword, $count ){
- //データの取得処理を実装
- }
- }
実際にAmazon Webサービスからデータを取得する処理は、「ITmedia エンタープライズ:特集:後編 WebサービスをAmazonで知る――PHPでECS 4.0を使うテクニック (1/5)」を参考にしました。
ModelでDBテーブルを使わない場合は、
- var $useTable = false;
と書くとDBテーブルにアクセスしないらしい。
controllerでは、対応するDB以外のModelを使う場合、
- class BillsController extends AppController {
- var $name = 'Bills';
- var $helpers = array('Html', 'Form' );
- var $uses = array( 'Bill', 'Aws' );
- //以下略
- }
のように使うModelを配列で宣言する。このとき対応するcontrollerに対応したDBも配列に入れることを忘れずに。
coreserverでcakePHPを試す
月曜日, 1月 14th, 2008 Posted in cakePHP, PHP | 1 Comment »cakePHPの動作環境をレンタルサーバーのcoreserver上に構築します。ローカルでの動作確認はCakePHPをローカルで試すを参照してください。
cakePHPはダウンロードしてきたモジュールを解凍すると、次のようなフォルダ構成になります。
- /cakeroot
- /app
- /config
- /controllers
- /models
- /plugins
- /tmp
- /vendors
- /views
- /webroot
- .htaccess
- index.php
- /cake
- /vendors
- .htaccess
- index.php
レンタルサーバーで複数のcakePHPアプリを動作させる場合、容量を節約したいなどの理由でcakePHPのcoreは共通のファイルを参照したいと思って、次のような構成に変更しました。
- /virtual/xxx/lib/cake_core
- /cake
- /vendors
- /virtual/xxx/public_html/caketest.xxx.com/
- /app
- /config
- /controllers
- /models
- /plugins
- /tmp
- /vendors
- /views
- /webroot
- .htaccess
- index.php
- .htaccess
- index.php
/virtual/xxx/lib/cake_coreは複数のcakePHPアプリで共通とし、アプリごとに/virtual/xxx/public_html/caketest.xxx.com/以下のようにフォルダを構成します。
フォルダ構成を変更したことで次のファイルを編集します。/virtual/xxx/public_html/caketest.xxx.com/app/webroot/index.phpの、
- define('CAKE_CORE_INCLUDE_PATH', ROOT);
を
- define( 'CAKE_CORE_INCLUDE_PATH', DS.'virtual'.DS.'xxx'.DS.'lib'.DS.'cake_core' );
に変更します。
/virtual/xxx/public_html/caketest.xxx.com/index.phpの
- define('CAKE_CORE_INCLUDE_PATH', ROOT);
を
- define( 'CAKE_CORE_INCLUDE_PATH', DS.'virtual'.DS.'xxx'.DS.'lib'.DS.'cake_core' );
に変更します。
これでhttp://caketest.xxx.com/postsにアクセスしちゃんとなにやらエラーがでます。どうやらアクセス権のエラーっぽいので、/virtual/xxx/public_html/caketest.xxx.com/app/tmp/cache/modelsの、default_xxx_caketest_listとdefault_postsの属性を757に変更するとちゃんと表示されました。どうやら、/virtual/xxx/public_html/caketest.xxx.com/app/tmp/cache以下のディレクトリの属性を変更した方が良さそうです。
追記:2008/05/12
なんだかファイルの編集する箇所が大幅に間違っていたので訂正しました。
CakePHPをローカルで試す
火曜日, 1月 8th, 2008 Posted in cakePHP, PHP | No Comments »PHPのフレームワーク、CakePHPをローカルで試してみました。基本はCakePHP プログラマーズ リファレンスガイドの通りにやればいいんですが、ちょっと気になることなどをメモします。
ローカルの環境はWindows Vistaにxamppを入れています。
- CakePHPのインストール
CakePHPからcake_1.1.18.5850.zipをダウンロード。1.2系はまだbetaっぽいので1.1系で。C:\xampp\htdocsに解凍。
- DBの作成
A.3.ブログデータベースの作成の通りにテーブルとデータを作成。
/app/config/database.php.defaultを/app/config/database.phpにリネームする。/app/config/database.phpの$defaultを作成したDBに併せて変更- <br />
- var $default = array('driver' => 'mysql',<br />
- 'connect' => 'mysql_connect',<br />
- 'host' => 'localhost',<br />
- 'login' => 'ユーザ名',<br />
- 'password' => 'DBパスワード',<br />
- 'database' => 'DB名',<br />
- 'prefix' => '');<br />
ここまででいったんhttp://localhost/cakeにアクセスしてみると、
Your database configuration file is present.
Cake is able to connect to the database.と表示され問題ないことを確認する。
- Modelの作成
A.6.Post Model の作成の通りに/app/models/post.phpを作成する。
- Controllerの作成
A.7.Posts Controller の作成の通りに/app/controllers/posts_controller.phpを作成する。controllerからは$this->PostでModelにアクセスできる。
- Viewの作成
ビューのファイルは、/app/views以下に対応するコントローラにあうフォルダを作成する必要がある。今回はpostsというフォルダを作成する。A.8.Posts Controller の作成の通りに/app/views/posts/index.thtmlを作成する。
とりあえずここでhttp://localhost/cake/posts/indexにアクセスしてみる。んが、文字化け。UTF-8で保存したら文字化けするみたい。Shift-JISで保存すると問題ない。どこかに文字コードの設定があると思うんだけど、また今度調べよう。
続いて/app/controllers/posts_controller.phpにfunction view()を追加。これで投稿された記事を個別に見れるようになる。
さらにA.9.Posts の追加の通りに/app/controllers/posts_controller.phpにfunction add()を追加。フォームデータをPOSTで送信したら、$this->params[form]でフォームに入力されたデータにアクセスできるらしい。htmlヘルパーの$html->inputなどを使ってフォームの内容を送信すると$this->data['モデル']['フィールド名']でアクセスできる。
A.10.データバリデーションの通りに/app/views/posts/add.thtmlを作成し、新規作成画面のviewを作成する。
HtmlHelperの$html->input、$html->textareaの第一引数は対応するモデル/フィールドを指定する。第二引数はフォームの属性などを指定。’size’=>’40′で入力フィールドのサイズに40を指定。
モデル(/app/models/post.php)に$validateを定義することによってsaveが呼ばれたときにフォームからの入力をチェック(validate)することができる。新規作成画面へのリンクを表示するために/app/views/posts/index.thtmlに/posts/addへのリンクを作成。
- < ?php echo $html->link( "新規投稿", "/posts/add" ); ?></p>
- <p>
ローカルでは特に問題なく動作しているので、次回はcoreserverで試してみます。