« 2008年4月 | トップページ | 2008年6月 »

2008年5月

2008/05/29

オブジェクト指向言語と関数型言語の書き方の違い

【1】オブジェクト指向言語の書き方は「set-do-get」

複数の引数を渡して、価格を計算する処理を実装するとしよう。

手続き型言語なら、下記のようなシーケンス図になるように書くだろう。
つまり、1個の関数にたくさんのロジックを詰め込む。

C


例えば、Cのmain関数のように、1個だけの関数にロジックを詰め込んで、下手をすれば数千行に及ぶソースになる。
そうなると、もはや保守していくうちに、誰もが修正できなくなる。

オブジェクト指向言語なら、下記のようなシーケンス図になるだろう。
つまり、1個のクラスに必要な情報をsetし、状態を変化させて、必要な情報を最後に取得する。
副作用を起こす関数(set, do)と副作用の無い関数(get)を使い分ける。

いわゆる「set-do-get」の書き方。

Java

オブジェクト指向に基づいて綺麗に設計したシーケンス図は、階段状のシーケンスになることが多い。
つまり、複雑なロジックは、各クラスへ適切な粒度で分割される。

例えば、購入した商品の計算は、商品の価格と個数だけでなく、内税や外税のような消費税計算、あるいは、ポイントを使った割引など計算ロジックが複雑になりがち。

更に、会員が上得意か新規かという会員区分、あるいは、ギフト商品や優待会員向け商品など商品によって計算ロジックを動的に変えたい時が発生する。

だから、計算クラスを更に分割するなどのクラス設計をするのが普通。
この時に、ポリモルフィズムを使う。

Javaでは、ポリモルフィズムをState/Strategyパターンで実現する。
この時に、継承構造を使うことが多い。
そして、機能追加や保守していくうちに、継承構造が深くなり、サブクラスから親クラスをコールするような依存循環構造が発生して、手に負えなくなってくる。

Ajaxのような関数型言語の出現によって、オブジェクト指向によるポリモルフィズムは限界があるのではないか、と最近感じる。

【2】関数型言語の特徴~クロージャと継続

プログラミングGauche」では、関数型言語Schemeの最も基本的なルールは下記の2つだと喝破している。

2-1.lambda式は「レキシカルな環境を保持した手続き」(クロージャ)へ評価される。
2-2.手続き呼び出しは継続を使った引数付きgotoである。

クロージャの例として僕が分かりやすかったのは、クイックソート。
C言語で実装したクイックソートの関数では、ソート関数を関数ポインタとして引数で渡す。

PerlやRubyでは、テキストファイルを読み込んで、ゴニョゴニョ処理するロジックでクロージャを使う時が多い。

プログラミングGauche」では、「継続とはプログラムのその時点より後に行う計算」と説明している。

継続の使い道は、Webアプリなら、ログインチェックだ。
つまり、ログインに失敗して、再入力してログインに成功したら、途中まで読み込んだ処理の途中から再開して実行する。
更に、Webアプリで継続が使えれば、いつも問題になる「戻るボタンの遷移」が簡単になる。

クロージャと継続を使って、ポリモルフィズムを実現できないか?
つまり、複雑な条件分岐を、クロージャと継続を使って、もっとエレガントに書けないだろうか?

関数型言語でポリモルフィズムを実現する手法は、リフレクションだと思う。
複雑なループ処理、深くネストしたIF文などの制御構造そのものを一つの手続きに抽象化する。
IF文の判定式、条件分岐後の実行ロジックは、リフレクションで後から動的に決める仕組み。

関数型言語は、手続き型言語やオブジェクト指向言語と書き方がまるで違う。
もっと研究する余地がある。

| | コメント (0) | トラックバック (0)

2008/05/28

真のIT企業はメディア企業を目指す

【1】サイバーエージェント藤田社長のインタビューで気になる言葉があった。

(前略)アメブロ以外でも重要な新規事業案件はありますが、我々はメディア企業として成長したいのです。

これほど影響力を持っていて、収益性が高い商売は他のどの産業を見渡しても見当たらないですから。


藤田社長がメディア企業へ目指している点は示唆に値する。
実際、電通や博報堂などの大手の広告代理店、そして大新聞社やテレビ会社の給料は、30歳の普通のサラリーマンで年収1000万円以上にも達する。

かつて、ライブドアや楽天は、既存メディアを買収しようとしたが、手段は違うがその狙いも同じだろう。

Appleも同じ。
iTunesは音楽CDに限らず、DVDも含めたエンターテイメントメディアを売り出すエンジン。
Life is beautifulでも似たような記事がある。


(前略)そういうところまで踏まえた上でiTunes storeをもう一度見直してみるとAppleの戦略が見えて来る。
iTunes storeは今やWal-martに次ぐ世界第二位の音楽流通業者だが、ジョブズの目標はWal-martを抜いて業界一位になるなんて低いところにはない。
狙いは当然、iTunes store単体でCD全部の売上げを抜くこと。そしてその次のターゲットはDVD。
ジョブズはiTunes+iTunes storeを「CD」や「テレビ」に匹敵するメディアに育てようとしているのだ。

Googleも、検索エンジンによる広告収入のおかげで、強大な広告代理店だ。

特に日本の既存のメディア企業は、作ったコンテンツを規制に守られた電波の上に流して、広告で儲ける。
彼らは著作権や既存の業界慣行に縛られて、今のネット企業のやり方を真似ることができない。
朝刊を読むたびに、新聞社がインターネットによる影響力の侵食、そして著作権の侵食に危機意識を持っているのが読み取れる。

メディアは、行政・立法・司法に次ぐ第四の権力と言われる。
それぐらい政治的影響力があるのだ。

【2】しかし、おそらく日本の殆どのソフトウェア会社は、受託開発中心のSIer。
このビジネスは多重の下請け構造からなっていて、僕ら開発者を苦しめている所がある。
最近は海外へオフショア開発して、大手SIerほどプログラミング力が落ちて、更に首を絞めている所がある。

良くても、ハードウェアと抱き合わせでパッケージ製品を売るハードウェアベンダー。
そのハードウェアは昔からのメインフレーム中心。
Sunでさえも、自社のSolarisが売れなければ売り上げは増えない。

日本の製造業は世界に戦える技術力と品質を持つ。
しかし、ハードウェアの発想が強くて、ソフトウェア開発の意識が少ない気がする。
特に家電メーカーを中心とする組み込み系ベンダーは、CMM/CMMI、SEPG、SPIなどプロセス改善に力を入れるが、何となく違う気もする。

ソフトウェア開発では、開発プロセスも大事だが、それ以上に技術力、特にプログラミング力が大切だ。
プログラマが互いに競い合い、技術を磨く環境作り。

プログラマが仕事しやすい環境作り、優秀なプログラマによるチーム運営は、以前のQC活動とは違った発想を必要とする気がする。
だから、XPからPF(プロジェクトファシリテーション)が生まれて、開発者同士のコミュニケーションやチームビルディングに重きを置くようになった。

【3】真のIT企業はメディア企業を目指すのではないか?

それは、GoogleやAppleのように、技術力を基盤に、各種コンテンツを誰もがコスト無しで公開できて読めるようなインフラを作ること。

| | コメント (0) | トラックバック (0)

2008/05/27

要件定義はトリアージが鍵を握る

成功する要求仕様 失敗する要求仕様」ではトリアージの概念が説明されている。
つまり、システムを実現する要求は、納期やコスト、リソースの観点から優先順位付けして、高い優先順位から要求をまとめていくというもの。

ヨードンの「デスマーチ」でも、デスマーチプロジェクトから脱出する唯一の方法はトリアージを行うことだ、と書かれていた。

そもそもトリアージとは、救急医療の用語。
災害医療等において、有限のリソース(医師や医薬品など)を最大限に活用して、より多くの傷病者を治療するために、治療の優先順位を決定することを意味する。

Wikipediaによると、下記4個の色のついた診断書を傷病者の右手首に取り付ける。
ここでは、治療の優先順位は、赤→黄→緑→黒 の順番になる。

【黒 (Black Tag)】
死亡、もしくは救命に現況以上の救命資機材・人員を必要とし救命不可能なもの。

【赤 (Red Tag) 】
生命に関わる重篤な状態で一刻も早い処置が必要で救命の可能性があるもの。

【黄 (Yellow Tag)】
今すぐに生命に関わる重篤な状態ではないが、早期に処置が必要なもの。

【緑 (Green Tag) 】
救急での搬送の必要がない軽症なもの。

日本では、実は、伊丹駅付近のJR西日本の脱線事故で、トリアージが初めて大規模に実施されたらしい。

Redmineでチケット管理を始めてから、トリアージについて色々思う所がある。
ザ・ファシリテーター2」に出てくるFRCPの法則と絡めて、まとめてみる。

【1】機能(Function)

システム開発の要件定義では、まず、お客の業務をシステムがカバーできていることが最低条件。
これはまさに最低限の機能そのもの。
いわゆる正常系の業務フロー。

このカテゴリーでトリアージする目的は、不要な機能を捨てること。
直近のリリースに必要ない機能は、リソースが余っていない限り、作る必要は無い。
なのに、システム開発では、リリースに無関係な無駄な機能を作っている時が実は多い。
拡張性や保守性を重視しすぎて、逆に自分たちの仕事を無駄に増やしている。

【2】信頼性(Reliability)

最低限の機能を実現できると、お客は品質を求めだす。
このカテゴリーは、バグ修正や異常系の要求。

普通、バグ修正は機能追加や仕様変更よりも優先してやるべき。
理由は、品質が安定しないのに、機能追加や仕様変更で機能をどんどん増やしていくと、じきに品質をコントロールできなくなるから。

また、異常系の業務ロジック実装と、異常系に陥った業務のリカバリーロジックは、要求から漏れていることが多い。
理由は、お客も異常系の業務は殆ど使ったことがないから。

しかし、システムを構成するプログラムの8割は異常系業務の実装によるものといって差し支えない。
だからこそ、異常系業務の要件をあらかじめ根掘り葉掘り聞いておかねばならない。

異常系の中身は、プログラム内のException、DBのロールバックもあれば、ハード故障、フォールト・トレラントなどある。
例えば、小売系業務でクレジットカード決済が失敗した場合は、それなりの複雑な業務が発生する。

また、複数のWebサーバー、DBサーバーで本番系と待機系の二つを作り、ハードを冗長化する構成方法もある。
しかし、お金をかけずにハードの冗長化をせず、1台のサーバーで本番運用している所も多いだろう。すると、突然トラブルが起きてシステムが止まった時、それはお客の会社の業務が完全にストップすることを意味する。
そんな事態になったら、責任問題に発展する。

昨今はサーバーを含むハードウェアはとても安い。
信頼性を確保するために投資すべき。

【3】利便性(Convenience)

機能も信頼性も満足すると、お客は利便性を言い出す。
昨今の業務系Webシステムなら、もっと使い勝手を良くしてくれ、という要求が多いだろう。

最近は、業務系Webシステムもデスクトップアプリのように、リッチUIが普通になった。
良く使う技術は、Ajaxだろう。
他には、Flex/Air、Silverlight。

Ajaxを使えば、ブラウザ上の画面を常に最新情報で自動更新できる。
最新のWebブラウザは、JavaScriptエンジンの高速化に力を入れているから、Webシステムをうまく作ればデスクトップアプリと同じ感覚で使える。

しかし、Ajaxを使いこなすのは難しいと思う。
Ajaxのソースは、Javaのようなオブジェクト指向言語の発想ではなく関数型言語の発想。
クロージャや無名関数、リフレクションを多用しまくるので、敷居が高い。

更に、JavaScriptでサーバーに問い合わせずにクライアント内部でDOM生成できるので、画面の状態を保持するロジック、画面の状態を一つ前に復元するロジックが非常に難しくなる。
うまく設計しないと、すぐにスパゲッティコードになる。

また、使い勝手を重視した要件は大概、工数が結構かかる。
工数がかかる割には、期待するほどの使い心地にならないものだ。
だから、プロジェクトリーダーは、使い勝手向上の要望と工数を天秤にかけるのが普通。

【4】価格(Price)

機能、信頼性、利便性に満足したら、もっと安くしろ、とお客は言い出す。
システム開発が途方も無くお金がかかるのは、プログラマの単価が高いから。

大手SIerは、中国などに外注して、人月単価を安くする傾向にある。

最近思うのは、システム開発の現場は意外と手作業が多く、IT化されていない作業が実に多い。
システム開発の生産性が低いのは、システム開発のインフラがIT化されていないから。

ソース管理では、本番環境のモジュールはtrunk、裏で新規開発するモジュールはブランチのように、SVNリポジトリを分ける。
ソース管理は非常に重要なのに、ここでデグレが発生する時も実に多い。

継続的ビルド環境を作り、コマンド一発でモジュールをビルド&デプロイできるようにしておく。
そうしなければ、バグ修正をすぐに検証できない。

要件を仕様に落とた実装は、全てRedmineのチケットで管理する。
そうすれば、チケットとソースが相互リンクされるし、全チケットの状態管理もRedmineならすごく簡単。
駄目なプロジェクトは、タスク管理が曖昧で、誰が何をしているのか、プロジェクトリーダーさえ知らない。

生産性を上げれば、価格にも対抗できる。


| | コメント (0) | トラックバック (0)

2008/05/26

オブジェクト指向の次の思想は?

【1】オブジェクト指向という概念は、20年以上叫ばれてきた。
でも、正直、聞き飽きた所がある。

オブジェクト指向を生かした設計手法であるUMLも、以前よりもコミュニケーションが取りやすくなったが、所詮ダイアグラムに過ぎない。

オブジェクト指向開発プロセスの集大成であるRUPは、もはや馬鹿でかい開発プロセス。
誰もそれを完全にマスターすることは難しい。

プログラミング技術では、オブジェクト指向の最大の利点はポリモルフィズムだ。
一つの型(インターフェイス)を複数のインスタンスで動的に振る舞いを変える仕組み。
Javaでポリモルフィズムを実現するには、普通は継承を使う。

デザインパターンはオブジェクト志向のカタログ。
デザインパターンは、C++のベストプラクティス。
Javaもそれを引き継いでいる。

ポリモルフィズムを使いたい状況は、複雑な条件分岐。
いわゆるswich文、IF文が羅列しているプログラムを、複数のクラスへ分割する手法。

特に、業務システムは、業務の状態判定をフラグとIF文で実装していくうちに、IF文がどんどんネストして深くなって、誰も修正できなくなる。

状況に応じて、下記3つのデザインパターンを使うのが普通だろう。
それぞれの条件分岐のクラスのインスタンスは、FactoryかAbstractFactoryクラスで生成する。

1.switch文やIF文の状態判定から、状態やアルゴリズムを抽出する
→State/Strategyパターン

2.swich文で二つの型を比較して条件分岐したい時(いわゆるマトリックス型分岐)
→Visitorパターン

3.それぞれの条件分岐のアルゴリズムを組み合わせて、最大値や最小値を取り出したい時。
 State/Strategyパターンの変形と言える。
→Decoratorパターン

継承構造が複雑な場合、継承構造を複数のビューから眺めて2つの継承構造へ分離するBridgeというデザインパターンもある。

でも複雑性に対応しきれなくなっている。
一度、継承構造を入れてプログラミングすると、機能追加していくうちに、継承が深くなりがち。


【2】最近、Ruby、JavaScript、Scalaのようなスクリプト言語や関数型言語に触れて、ポリモルフィズムの実現方法が変わってきている気がする。

うしおさんの記事「私がScalaを選んだ理由 [初級~中級] JavaとRubyとScalaの比較」を読んで、その理由が少し分かった気がした。

結論から言うと、RubyやJavaScriptは、Javaと書き方が違う。
それは、関数型言語の発想と言っていいと思う。
その特徴は二つあると思う。
一つは、リフレクションを多用したメタプログラミング。
そしてクロージャ。

例えば、条件分岐はリフクレクションで極限まで共通化する。
それができるのは、スクリプト言語という特徴があるから。
型にとらわれないからできる。

Railsはmethod_missingという特徴がある。
これは、メソッドが無ければ勝手に生成してくれる。
正規表現が強いRubyらしい。
Railsはリフレクション使いまくりだ。

他にも、メソッドチェーン、短絡評価など。

ループ処理はクロージャで簡略化して書ける。
Javaなら、無名関数や無名クラスを作るのが面倒だが、スクリプト言語は、関数がファーストクラスなので、関数をプロパティのように扱える。

これらの性質を使うと、継承構造を使わなくとも、フレームワークが後で動的にメソッドを追加して、機能を増やすことができる。

JavaVM上で動く関数型言語Scalaでは、Implicit conversionsという機能がある。
これは、型を拡張する方法。

Implicit conversionsはまだ理解し切れていないけど、これを使うと、型を変更すること無しで、パッチのようにメソッドを追加できる。

詳細は、keisukenのHPを見よ。

そこでは、PersonクラスにImplicit conversionsを当てると、RichPerson.ageのインターフェイスを実行できる。
Personクラスには、ageインターフェイスはないのに!

【3】今まで手続き型言語の日陰に隠れていた関数型言語がにわかに存在感を増してきた理由は、WebとマルチコアCPUの普及だと思う。

WebもマルチコアCPUも、並列処理、分散処理に特徴がある。

今まで、1個のCPU上で、マルチスレッドに気遣いながら手続き型プログラミングしてきた。
でも、マルチコアCPUでは、ロジックを複数のプロセスへ分解して、プロセスを平行に走らせるようプログラミングする。

Webプログラミングも同じ。
複数のクライアント、複数の画面から飛んでくるリクエストの状態を保持する機構は、セッションしかない。
セッションはグローバル変数と同じ。
昔のデスクトップアプリのメモリリークと同じ問題構造を持つ。

プログラミングErlang」では、こんな一節がある。

なぜマルチコアCPUを気にするのか?

(中略)
デュアルコアマシンでプログラムが2倍以上速くなっても深い意味はない。

(中略)
2倍の高速化くらいでは驚かないにしても、10倍なら話は別だ。それが100倍なら本当にすごいことだ。

今日のプロセッサは高速で1つのコアで4つのスレッドを並列に実行できるので、32コアのCPUならば128個分のスレッドを使える可能性がある。
つまり、100倍の高速化も射程内にあるということだ。
100倍高速になるなら黙ってられない。
実現するにはコードを書けばいいだけだ。


そう、今のJavaに不満があるなら、コードを書けばいいだけだ。

| | コメント (0) | トラックバック (0)

2008/05/19

【告知】モデル検査

モデル検査の話がSEA関西プロセス分科会で出てくるので展開する。

Wikipediaによると、、

モデル検査(Model Checking)とは、形式システムをアルゴリズム的に検証する手法である。
ハードウェアやソフトウェアの設計から導出されたモデルが形式仕様を満足するかどうか検証する。

モデル検査を使う状況は、特に組み込み系プログラムの設計・テストフェーズが多い。
つまり、プログラムや設計図から状態遷移図を作り、状態遷移図からバグになりそうなアルゴリズムを探し出すというスタイル。
この手法は10年以上前から研究されており、最近のコンピュータ性能の向上から、一部で注目されているらしい。
とはいえ、モデル検査について知見のある技術者は数少ないだろう。


実は、4月のソフトウェア開発技術者試験の午後問題にも、モデル検査が出た。
正直びっくりした。

http://www.jitec.jp/1_04hanni_sukiru/mondai_kaitou_2008h20_1/2008h20h_sw_pm1_qs.pdf


~~ 第34回 SEA関西プロセス分科会のご案内 ~~

テーマ:動きの設計と検証、さらに自動化

講師 :藤倉 俊幸 (イーソル株式会社)

主催 :ソフトウェア技術者協会 関西支部 プロセス分科会
     
日時 :2008年05月30日(金) 18:30~21:00

会場 :大阪市立大学文化交流センター
    〒530-0001 大阪市北区梅田1-2-2-600
    大阪駅前第2ビル6階 ホール
    Tel 06-6344-5425 / Fax 06-6344-5524
    http://www.ado.osaka-cu.ac.jp/BUNKO/   


周辺略地図     http://www.media.osaka-cu.ac.jp/Toshi/yoteiti.html

    ※会場の部屋が通常(大セミナー室)とは異なりますので、
     ご注意ください。(同じビルの同じフロアです。)

内容 :
  ソフト開発においてはタスク設計が重要です。セミナーでは、
  モデル検査ツールLTSAについて説明した後、動作要求の仕様化と
  検証、タスク動作への変換について説明します。手順の概要は、
  以下の様になりますが、基本的に小難しい話は無しで進めます。

  1) 動作要求をマインドマップによって表現し、動作仕様を抽出します。
  2) 各動作仕様をFSP式に変換しLTSAによって実現可能な動作要求セットを作成します。
  3) 動作要求セットをタスクに分割し、同期構造の設計検証を実施し、タスク設計仕様を作成します。

  UMLを使用している現場への適用では、動作要求表現として
  シーケンス図や状態図を利用することで、これらの図からFSP式を
  自動生成することが可能になります。UMLへの適用に関する詳細は
  以下のURLを参照してください。

http://www.esol.co.jp/rcs/uml_tool.html

参加費用:
  SEA正会員:1,000円,SEA賛助会員:1,000円,
  学生:500円,一般:2,000円

  定員 :120名

申込方法:
以下のペ‐ジからお申し込みの受付を行っております。
http://www-ise4.ist.osaka-u.ac.jp/K-SPIN/application.html
### 05/28(水)までにお申し込みください ###

 ご注意)
 ・受付は先着順で,定員になり次第〆切とさせていただきます.
  申込受付後のキャンセルは原則としてお断りします.
 ・メール,FAXなどWebページ以外からの申し込みは受け付けて
  おりません.
 ・お申し込みの受付け後,確認メールが自動的に返送されます.
  確認メールを印刷し,当日受付時に持参ください.
 ・申し込み手続きについて不明点などございましたら,下記まで
  ご連絡ください.
  seakansai-office2007@media.osaka-cu.ac.jp
 ・参加費は当日会場受付にて現金でお支払いください
  領収書が必要な方は,申し込み時に「領収書要」にチェック
  してください.


| | コメント (0) | トラックバック (0)

2008/05/18

Redmineを使って気づいたこと

日々の新規開発をRedmineのチケットで進捗管理して気づいた点があったのでまとめてみる。

【1】ロードマップを見ると、進捗率が逆に下がる場合がある

下記のロードマップになるようにチケットを登録したと仮定しよう。


◆ロードマップ1:5月1日現在

進捗:0%

#1 機能Aの開発(新規)
#2 機能Bの開発(新規)
#3 テスト(結合テスト)(新規)


すると、普通は、0%→33%→66%→100% と進捗率が上がって終わるはず。


◆ロードマップ1:5月5日現在

進捗:100%

#1 機能Aの開発(終了)
#2 機能Bの開発(終了)
#3 テスト(結合テスト)(終了)


しかし、テストでバグが上がったり仕様変更が入った時、バグ報告をチケットに登録すると、下記のようになる。


◆ロードマップ1:5月6日現在

進捗:42% ← 終了3件/全7件だから。

#1 機能Aの開発(終了)
#2 機能Bの開発(終了)
#3 テスト(結合テスト)(終了)
#4 バグ1(新規)
#5 バグ2(新規)
#6 バグ3(新規)
#7 仕様変更1(新規)


つまり、進捗率は下がる!

最初にスケジュールを作った時に、バグがいくつ上がるか、とか、仕様変更がいくつ入るとか、予測することはすごく難しい。
実際に作ってみないと分からないのが普通だ。

しかも、バグを修正するたびにモグラ叩きのようにどんどんバグが発生する時もある。
特に、PGの出来が悪い時やあいまいな仕様の場合。

普通は契約上、納期は厳守なので、リリース間際の短い残り期間に残業して休日出勤して、最終的には徹夜してでも全てのバグを修正しなければならない。

だから、プロジェクトリーダーはあらかじめ納期までにバッファを入れて、バグ修正の時間を確保しておく。
でも、このバッファはすぐに浪費して足りなくなるのが普通。

進捗率は増加するだけでなく、減少する時もある現象は、プロジェクトリーダーの感覚ではすごくフィットする。
進捗率が減少する時は、各人のタスクが溢れそうで、納期までに間に合うか、ピリピリしている時だ。
バグ報告がどんどん増えている時、いくら時間があっても、バグ修正が永遠に終わらない感覚になるのが普通だろう。

進捗率が落ちた時は、デスマーチに入るか入らないかの瀬戸際。

ここで、プロジェクトリーダーが取る手段は、下記4つしかない。

1.品質を落とす
2.人を増やす
3.納期を延ばす
4.機能を削る

あなたなら、どれを選ぶか?


【2】プロジェクトリーダーが調整できる作業は、チケットのトリアージしかない

駄目なプロジェクトリーダーは、品質を落としたまま納品して、更に状況を悪化させる。
下手をすれば、契約違反、あるいは昨今なら社会問題にまで発展する。

政治力のあるプロジェクトリーダーは、顧客や上司と調整して、納期を延ばして、人を投入する。
だが、人を増やせば、コミュニケーションロスが発生したりして、逆に開発チームは混乱する時が多い。
たとえ納期を延ばしたとしても、残業や徹夜続きの毎日が更に長引くだけで、開発者も疲労する。

アジャイル開発やXPでは、スコープ管理と称して、機能(スコープ)を調整することでバランスを取ろうとする。

つまり、お客様が業務で使う90%の業務フローの機能とその品質は死守する。
そして、すごく稀な業務フローから生じるバグ、ある機能だけに生じる性能ダウンのバグ、Firefoxでしか再現できない環境依存のバグなど、主要な業務を使う時に無視できるバグ、あるいは別の代替手段がある仕様変更は、間をおいて納品するように後回しにするやり方。

下記の例になるだろう。


◆ロードマップ1:5月8日現在

進捗:100%

#1 機能Aの開発(終了)
#2 機能Bの開発(終了)
#3 テスト(結合テスト)(終了)
#4 バグ1(終了)
#5 バグ2(終了)
#6 バグ3(終了)


◆ロードマップ2:5月8日現在

進捗:10%

#7 仕様変更1(担当)


MIXIやGoogleが編み出すWebアプリは、「永遠のベータ版」と言われる。
この手法は、頻繁な間隔でリリースする手法を使うことによって、たくさんのバグ報告や仕様変更を「どのタイミングでリリースするか」という問題に置き換える。

この手法では、トリアージという概念を理解しきっていることが大事だ。
機能やバグ報告に優先順位とリリース日をアサインして管理することだ。

つまり、チケットの優先順位を付けて、チケットを取捨選択すること。
捨てるべきチケットもある。
限られた時間、限られたメンバーという制約がある限り、全てのチケットを実現するのは難しいから。

プロジェクトリーダーは、チケットの優先順位付けとチケットの対策立案が本来の仕事であるべきだ。

RedmineのようなBTSでチケット管理すると、プロジェクトリーダーはガントチャートを作るのが彼の作業ではなく、ロードマップ等の色んな集計結果から、実現すべきチケットと後回しにするチケットへ取捨選択するのが彼の仕事であることが良く分かる。

【3】CCPM(クリティカルチェーン・プロジェクトマネジメント)が提唱する工数見積からバッファを分散せず集中させる利点

上記のリスクがある限り、プロジェクトリーダーは、工数見積で2倍以上のバッファを入れたりする。
しかし、そのバッファを各タスクに分散させると、開発者も人間なので、学生症候群ですぐにバッファを使いきってしまう。

CCPMでは、TOCの発想を使って、クリティカルパス上のタスクが必ずボトルネックにならないようにバッファを入れるタイミングに注意する。
つまり、二つのタスクが合流するときは、合流バッファを入れて調整できるようにする。
他のタスクは、バッファを入れず、ギリギリの工数に設定し、一番最後に置かれたバッファで調整できるようにする。

チケット駆動開発でも、この発想は使える。
新規開発している場合は、開発担当のチケットはバッファを入れない。
テストでバッファを入れる。

結合テストや運用保守では、優先順位の高いチケットがクリティカルチェーンにある。
これらのチケットの依存関係から、バッファを入れるチケットを指定する。


Redmineのチケット管理は、チケットの状態をロードマップ・ガントチャート・レポートなど複数の観点から見れるので、プロジェクトのどこに問題があるのか分かりやすい。

プロジェクトリーダーの本来の仕事は、リスク管理であるべきだ。

チケット管理こそがBTSの肝。


| | コメント (0) | トラックバック (0)

2008/05/15

ソフトウェア開発をIT化する


【1】開発の殆どの現場はIT化されていない

「ソフトウェア開発をIT化する」という言葉は自己矛盾な気もする。
しかし、SIerの開発の現場をのぞくと、作業は実は殆どIT化されていない事実に気づく。

プロジェクトリーダーならば、顧客や上司から下記の報告をいつも求められているはずだ。

1-1・プロジェクトで開発する全機能のうち、今、進捗は何%で、後何%残っていますか?
1-2・システムテストで上がったバグは今いくつで、後いくつ残っていますか?
1-3・明日のリリースの前に、今残作業はいくつで、その優先度はどうなっていますか?
1-4・見積の工数と実績工数の差はどれくらいですか?

上記の数値を一瞬で出せる現場は、実は殆どないのではなかろうか?
理由は、顧客や上司が求める数値は引き算で要求されるので、一旦現状の数値をメモリに保持して計算しないといけないから。

プロジェクトリーダーは、上記の数値を毎日、彼の作業時間の殆どを使って計算して、翌日に報告しているだろう。

特に、システムテストで上がったバグ報告をリアルタイムに管理するのは至難の業だ。
普通は、最盛期に1日20件のバグが報告されるが、開発チームがバグ修正できる件数はおそらく1日最大8件ぐらい。

つまり、バグはどんどん溜まって増えていくので、そのバグに優先順位を付けて、いつ修正するか、を管理することがすごく重要になる。
この時に、BTSを使っていない開発チームは、膨大なバグに押し潰されて、システムの品質が歩留まりまでなかなか到達しない。

更に、XPが提唱する統合ビルド環境のない開発チームは更に状況が悪化する。
本番リリース前後では、たったソース1行の修正でも、テスト担当者、プログラム修正開発者、検証担当者の3人が加わるから、1時間で終わる作業でも、3人時間もコストがかかる。
つまり、たった1個のバグ修正を検証する作業に、すごくコストがかかってしまう。

プロジェクトファシリテーションが提唱する「プロジェクトの見える化」は、上記の現状をチーム全員が認識できる環境作りを重視している。
「プロジェクトの見える化」にIT化が使えないだろうか?


【2】IT化しやすい開発プロセスはどこ?

ソフトウェアの開発プロセスは普通、下記のフローだろう。

要件定義

設計

実装

テスト

そして、それを支えるプロジェクト管理のいずれも、殆どの現場はIT化されておらず、マンパワーでカバーしようとしている。

XPでは、テスト駆動、統合ビルドという発想で、テスト作業をプログラムで自動化し、検証作業を自動化しようとする。

BTSは、システムテストの検証作業を一つの業務システムと見なし、バグ報告をチケット単位に管理して、状態をトレースしやすくする。
例えば、MantisやBugzilla。
つまり、BTSはソフトウェア開発のIT化そのもの。

また、Testlinkというオープンソースのテスト管理ツールを使うと、要件とテストケースの紐づけができて、要件とテストの両方を管理できる。


【3】Redmineがプロジェクト管理をIT化する

更に、Redmineは、単なるBTSの機能だけでなく、プロジェクト管理の機能も実現している。
つまり、下記の機能のように、チケットを色んな角度から評価している。

2-1.活動
 チケット更新やSVNリビジョンを表示。

2-2.ロードマップ
 マイルストーン単位のチケットの状態と進捗%を表示。

2-3.ガントチャート
 チケット単位の進捗%と作業開始・終了日を表示。

2-4.カレンダー
 チケットの開始終了日やマイルストーンを表示。

2-5.レポート(サマリ)
 トラッカー(バグ・仕様変更・仕様追加)、優先度、担当者、バージョン(マイルストーン)、カテゴリ(機能別)ごとに、チケットの状態(未完了・完了)の集計結果を表示。

2-6.経過時間
  実績工数(単位:h)をトラッカー(バグ・仕様変更・仕様追加)、優先度、担当者、バージョン(マイルストーン)、カテゴリ(機能別)ごとに表示。

プロジェクト管理とは、プロジェクト内部で発生する作業や問題をPDCAサイクルで解決しようとすること。
Redmineでプロジェクト管理すると、下記のようなPDCAサイクルが発生するだろう。

Plan:チケットを新規作成し、アサインする。

Do:チケットの作業を開発者が完遂する。

Check:チケットの状態を様々な観点からチェックする。

Action:起きている問題、又は予期できるリスクに対して対策を立てる。

つまり、Redmineが他のBTSよりも優れている点は、Check(評価)の機能が充実しているからだ。

チケットの集計結果を色んな角度から評価できるので、プロジェクトリーダーは、その集計結果から、様々なリスクを対処しやすくなる。
しかも、チケットさえ作業担当者が正確に入力すれば、リアルタイムにプロジェクトの現状を誰もが把握できる。

RedmineでCheckの機能が充実している理由は、チケットの情報が全てDBにあるから。
DBにあれば、Ruby on Railsという優れたフルスタックなWebフレームワークのおかげで、一瞬で集計結果の機能を実装できる。

そもそも、自動集計という機能は、SIerが顧客の業務のIT化で行う作業と同じ。
経営層への売上集計レポートは、「会社のキャッシュフローの見える化」そのものだ。
お客様の会社のために、月末に売上計上し、月初に色んな観点から売上集計した結果を経営層へレポート提出するバッチを作っていませんか?

その発想をソフトウェア開発にも応用してみよう。

【4】IT化されたソフトウェア開発スタイル

現在、運用できると考える開発スタイルは下記2つの観点からなる。

4-1.開発の流れ

要件定義←Testlink

設計=プログラミング

実装←SCM(Subversion)

テストケース作成←Testlink

テスト実施・検証←統合ビルド環境

テスト管理&プロジェクト管理←Redmine

4-2.データの流れ

TestLinkのテスト実行画面にredMineの問題(チケット)へのリンクを張る機能がある。
つまり、Subversionと連携すれば、要件からソースまで一貫してトレースすることは理論上可能だ。

要件管理(Testlink)
↓↑
テストケース管理(Testlink)

【チケット】(Redmine)
↓↑
ソース(Subversion)

上記の環境が運用できれば、プロジェクト進捗を手計算する作業を離れて、リスク管理するというプロジェクトリーダー本来の作業に集中できるようになるだろう。


| | コメント (0) | トラックバック (0)

2008/05/13

RedmineがExcelよりも素晴らしい点

Redmineの使い方は下記を見よ。

http://www.redmine.org/projects/show/redmine

【1】以下、Redmineを使った感想を書いてみる。

1-0.ガントチャートがリアルタイムに表示される。
 こいつに一番感動した。
 プロジェクトリーダーは、ガントチャート保守に、彼の作業時間の殆どを費やす。
 その理由は、プロジェクトのリスクがガントチャートでしか把握できないからだろう。

 考えてみれば、作業の開始日と終了日、作業状態さえ入力すれば、リアルタイムにガントチャートは計算できるはず。
 殆どのITプロジェクトのガントチャートは、手作業でかなりの時間を浪費して作っているか、MSProjectのように保守しても理解しにくいか、どちらかだ。
 ソフトウェア開発のプロジェクト管理で最もIT化されていない部分と言える。

Redmine_gantchart

1-1.SVNリポジトリとチケットが相互リンクできる
 これによって、チケット無しのSVNコミットは禁止できる。
 本番稼動しているソースはチケット無しの修正は不可。

Redmine_rivision


1-2.SVNリポジトリのソース差分表示が読みやすい
 リビジョンごとに差分箇所を色分けしてくれている。
 ソースインスペクションが楽しくなる。
 他の利点として、プロジェクトリーダーでなくとも、誰もがソースインスペクションしやすい環境が整ったこと。

Redmine_diff



1-3.複数のプロジェクトを親子プロジェクトで管理できる
 例えば、本番リリース後、SVNのtrunkで新規開発しながら、SVNのbranchで運用保守モジュールを管理している場合、管理するSVNリポジトリ単位にRedmineでプロジェクトを作る。
 これによって、新規開発時のチケットと運用保守のチケットを別々に管理できる。
 Tracと異なる大きな利点。

1-4.ステータスのデフォルト設定に「却下」「フィードバック」がある
 「却下」とは、バグ報告を修正せずに終了すること。
 例えば、「このバグは仕様なのです」みたいなケースだろう。

 「フィードバック」とは「差し戻し」。
 例えば、バグ修正して検証したら、実はバグが直っていなかった場合、PGへ差し戻しになる。

 上記2項目がデフォルト設定されているRedmineは、実に良く考えられている。

1-5.ワークフロー画面で、ユーザの権限ごとにステータスを設定できる
 これによって、開発者やテスト担当者は、指定されたステータスしか変更できなくなる。
 この機能は業務システムで良く出てくるのだが、汎用的に上手に作っている。

1-6.チケット同士の関係リンクに「関係する」「先行する」がある
 例えば、新規機能を開発するチケットへ、関連するバグ修正のチケットを「関係する」リンクにする。
 例えば、機能Bを作る前に共通機能Aを開発する必要があるなら、BのチケットへAのチケットを「先行する」リンクをはる。
 これによって、ガントチャートのFS関係のようにできる。

1-7.活動の画面で、開発作業のログを見れる。
 SVNコミットログやチケットの記入内容などが表示される。
 RSS機能もあるので、プロジェクトリーダーは常に活動の画面を見張っておく。

Redmine_activity

1-8.カレンダーには、チケットの開始・終了日やマイルストーンを表示する。
 チームメンバー全員にプロジェクトのゴールや各自のミッションを説明するのに役立つ。

1-9.ロードマップは、バーンダーンチャートそのものだ。
 バージョンにマイルストーン名を入力しておくと、バージョンごとのチケットの一覧と進捗のパーセンテージを表示してくれる。
 プロジェクトリーダーは普通は、ロードマップから、残作業のボリュームを推し量り、対策を立てるだろう。

Redmine_roadmap

1-10.レポート(サマリ)は、その時点のプロジェクトのソフトウェアメトリックスそのものだ。
 レポートには、トラッカー(バグ・仕様変更・仕様追加)、優先度、担当者、バージョン(マイルストーン)、カテゴリ(機能別)ごとに、チケットの状態(未完了・完了)の集計結果を表示する。
 プロジェクト終了後、この集計結果からバグ経験曲線などを作ることもできるだろう。

Redmine_report

1-11.経過時間の画面で、実作業時間を表示できる。
 チケットの予定工数(見積工数)と経過時間(実績工数)から、工数見積の精度を上げることができる環境になる。

Redmine_worktime


【2】チケット駆動開発の手順

2-1.チケット記載の前準備

2-1-1.バージョン
 マイルストーンと同値。
2-1-2.カテゴリ
 システムの機能別の単位。
2-1-3.トラッカー
 チケットの種類。
 バグ修正、仕様変更、仕様追加、新機能開発など。
2-1-4.リポジトリ
 SVNを指定する。
 リビジョン単位のコミットログが一覧表示されるように、チームでフォーマットを統一しておく。

Redmine_repository

2-2.PLがチケットを新規作成する
 ステータスは「新規」から始まる。
 WBSから更にチケットへ作業を分割し、担当者にアサインする。
 バージョン、カテゴリ、トラッカーの指定が重要。この区別でチケットの状態を集計するから。

2-3.開発者がチケットを更新する
 ステータスは「担当」になる。
 気づいた点は、チケットの注記欄へどんどん追加していく。
 合わせて、進捗(%)や経過時間も毎日入力してもらう。

2-4.開発者がチケットを閉じる
 SVNコミット時に、チケットにSVNリビジョンがリンクされる。
 開発又はテストが完了したら、ステータスは「実装完了」「検証完了」になる。

2-5.PLはチケットの中身を精査する
 そのチケットの内容を本番リリースしたら、ステータスは「終了」になる。
 もし、実装のやり直しがあれば、ステータスは「フィードバック」になる。
 新規チケットを更に作り、新規チケットに「関連する」リンクを張る場合もあるだろう。

 ITプロジェクト管理が難しい状況は、当初のWBSにないチケットがどんどん増えていく時だ。
 しかも納期が決まっているならば、たとえメンバーの人数が増えようとも、消化できるチケットの枚数に必ず上限はある。
 チケットの状態管理がチケット駆動開発の一番の肝なのだ。

2-6.チケットの状態をPLが見張っておく
 下記の画面で、プロジェクトの進捗をリアルタイムに確認できる。

2-6-1.活動
 チケット更新やSVNリビジョンを表示。

2-6-2.ロードマップ
 バージョン単位のチケットの状態と進捗パーセンテージを表示。

2-6-3.ガントチャート
 遅れていると赤字で表示されるので、MSProjectよりも分かりやすい。

2-6-4.カレンダー
 チケットの開始終了日やマイルストーンを表示。

2-6-5.レポート(サマリ)
 トラッカー(バグ・仕様変更・仕様追加)、優先度、担当者、バージョン(マイルストーン)、カテゴリ(機能別)ごとに、チケットの状態(未完了・完了)の集計結果を表示

2-6-6.経過時間
  実績工数(単位:h)をトラッカー(バグ・仕様変更・仕様追加)、優先度、担当者、バージョン(マイルストーン)、カテゴリ(機能別)ごとに表示。

【3】Redmineでのバグ修正フローをアクティビティ図で書いてみた。

Redmine_flow

 プログラムに例えると、
「却下」は GO TO EXIT。
「フィードバック」は、Exception発生でRollbackしたケース。

 上記の図では、3人のアクターで7つのステータスが入れ替わる。
 だから、結合テスト以降のバグ修正フローを管理するのはすごく難しいのだ!!

| | コメント (0) | トラックバック (0)

Redmineでプロジェクトを見える化する

顧客の業務を良く見ると、EXCELはシステム化してない業務で使われる。
経理で締めの計上をEXCELで計算して提出。
営業マンが集めた顧客データをEXCELでまとめて提出。

IT業界も然り。
仕様書をEXCELで書いて開発者に渡す。
バグ報告票をEXCELでやり取り。

更に、Excelで扱う業務では、ソフトウェア構成管理(SCM)が使いにくい。
バイナリファイルのため、履歴が残せないから。

IT化の利点はリアルタイムに集計して業務の見える化をすること。
又、集計をリアルタイムに自動化できること。
なのに、Excelの集計作業で、かなりの時間を浪費しているのが普通だろう。

進捗管理をExcelとRedmineで比較してみよう。

DBにあれば色んな観点からリアルタイムに集計できるのに、Excelで管理すると、VBAマクロを使いまくって、Excelが一つの複雑なシステムとなる。
特に、プロジェクトリーダーと言われる人は、Excelのマクロがスペシャリストの人が多い。

DBさえあればRAILSを使って、カップラーメンのように業務システムを作ることができるのに。

PFでは「プロジェクトの見える化」を声高に叫ぶ。
しかし、実際のソフトウェア開発では、自分たちが今どれくらいの残工数があるのか、後何%の実装が残っているのか、すぐに提示できる所は実は少ないのではなかろうか?

SIerは顧客の業務をIT化するのが仕事なのに、自分たちのソフトウェア開発は他業界よりIT化がかなり遅れている。

プロジェクトファシリテーションでは、タスクかんばんでアナログで管理するが、僕はやっぱりプロジェクトの進捗の見える化を自動化したい。

RedmineやTracなどのWebベースのプロジェクト管理ツールを使うと、進捗や残工数、納期をリアルタイムに自動的に集計できる。

特に、Redmineの場合、入力さえすれば、ロードマップやガントチャートを使って簡単に集計できる!

| | コメント (0) | トラックバック (0)

2008/05/09

【PFP関西】役割の変化が与えるもの

PFP関西#13に参加してきた。
今回もワークショップが面白かった。
その時の感想を書く。


今日のワークショップは、1回目は「PFの効果」について真面目に話し、2回目は役割を決めて「CO2削減の効果」について話し、3回目に役割を決めたまま「PFの具体的な効果」について話し合った。

僕が面白いと思ったのは、各人に役割を決めると、ポンポンとアイデアが出て、全員がムードメーカーになったこと。
僕のチームでは、若旦那、仲居、女将、板前などに各人が役割がアサインされた。
すると、板前や仲居らしき発想がポンポン出る。しかも、皆で笑う。

役割がある方が、発言しやすいと感じた。

ザ・ファシリテーター2―理屈じゃ、誰も動かない!」に似たような話があった。
主人公の彼氏のいる会社の研究所は、ROIが低い問題があるのに誰も手をつけられずにいた。
そこで、所長が、研究所のスポンサーである各事業部の代表という役割をベテラン研究員にアサインした。
ベテラン研究員ならば、第一線から遠のいているが、研究の事業性という観点では経験が役立つ。
更に、ベテラン研究員にその役割をアサインすれば、ベテラン研究員を再生することもできる。

以前の会議では、お互いに遠慮しあって、有益な発言すらなかった。
しかし、実際にアサインしてみると、会議では、各人のいる事業部の研究が本当にビジネスになるのか、という観点で、お互いに鋭い意見を交わすようになった、と。
役割をちょっと変えただけで、組織はすぐに活発になる、と。

プログラマと言う立場だけでは、ITビジネスが分からない所がある。
役割をアサインされると、その役割が存在理由になって、自由に発言できる。
そして、その役割でしか見えないものがたくさんある。
その役割で要求されるスキルがはっきり見えるようになる。

サブリーダー、プロジェクトリーダーと言う役割をアサインされると、その役割に似合うような人格が形成されていく人もいる。
リーダーとしての役割をアサインされると、普段の言動や服装まで、皆から自然に注目されるから、自然に模範となるように自分を律していくもの。
いわゆる「高貴な人の義務」を自然に身に付けていくように。

逆に、「7つの習慣」では、役割が多いと人は時間に追いまくられて疲れ切ってしまう、というアドバイスもある。
特に、子供がいて働く女性の場合はそうだろう。
「7つの習慣」では「刃を研ぐ」習慣がその時のアドバイスになっている。

今の日本の大手SIerは、歴史が長い会社ほど、年齢構成が逆三角形になっている。
つまり、40代、50代以上が多く、30代以下が極端に少ない構成。
そして、昨今の売り手市場で、新人社員が極端に多いので、ワイングラス構造とも呼ばれている。

こういう組織では、若手にいくら能力があっても、それなりの役割をアサインされないので、経験値が上がらない。
だから、技術や業務ノウハウの継承に問題がある。
しかし、一番の問題は、30代という人間の自然学的構造から見て最も知能も体力も整っている年齢で、中間管理職、そして経営層という役割の経験を得られずに、単なるオペレーターとして終わってしまうこと。

おそらく、日本の大企業ほど、団塊世代の成功体験に引きずられて、昨今のIT化の流れに乗り遅れていると思う。

| | コメント (0) | トラックバック (0)

2008/05/06

Redmineは何?という人へ

とやかく言う前に、Redmine開発プロジェクトのRedmineを見た方が早い。
これすごくないか??

http://www.redmine.org/projects/show/redmine

Redmineを開発しているチケットが見れる。
活動リンクを見ると、今日5/6はたった1人だけがチケット更新してるだけ。

リポジトリのリンクから、ソースのリビジョンからソース差分を閲覧できる!
Ver0.7.0でチケット一覧検索でバグがあった、というソースを修正した中身をWebで見れるヨ!


ロードマップから、どのVersionにどんな機能が含まれているか分かる。
0.7や0.8は機能追加のビッグバージョンで、バージョンの下3桁が入ると、BugFixバージョンのようだ。

チケットのサマリを見ると、修正担当者は3人ぐらいか。
サマリのカテゴリ欄を見ると、結構機能があるんだな、とか。
でも、未完了チケットが1個ずつ残っているのが気になる。
使えそうなのはVer0.7.1からか。


しかも、しっかり日本語対応もできてるみたい。
コメントやチケットの記入者は殆ど英語使いのようだが。。

| | コメント (0) | トラックバック (0)

継続的統合を成功させるための6ステップ

ソフトウェア開発の初期コストと保守コストのグラフの良い記事があったのでメモ。

Miros?aw Jedynak - professional .NET blog: 6 steps to successful Continuous Integration

(引用)それぞれの方法について,初期コストと維持コストの対比が提示されているところが印象的。感覚的だけど,このグラフは同意できる。


6つの観点の比較だが、経験的に非常に共感する。
この記事の主張は、「統合ビルドは重要!」の一言。

1. Use source code repository

(引用)「SCM使えって当たり前だろ」と思いつつも,未だにOSのファイル共有だけってのもあるからなぁ。現実は小説より奇なりダ。
これは鉄板。SCM使う発想がない時点で,そのプロジェクトは終わってる。


非常に同感。
開発の現場は、教科書よりも奇なり。

SCMを嫌がる現場は、バイナリファイルをいじっている所が多い。
Excelで仕様書を書いているとか、PhotoshopやIllustratorでお絵描きしているとか。

結局、テキストで管理できないと、SCMの意味がない。

2. Introduce check-in policy

Redmineを使うようになって、コミットログにチケットNOを付ける運用ルールにしている。
これができないと、RedmineとSubversionを連携する意味がない。

駄目なプロジェクトは、SCMに関する作業品質が雑なこと。
単なるプログラミングだけでなく、コミットログも重要なのだ。

3. Automate build

自動ビルドできない開発では、サーバー上でビルドするのではなく、ローカルマシン上でビルドする時が多い。
だから、他の人がビルドできない。
結局、結合テスト以降のバグ修正をテスト環境へ反映して検証するのに非常に時間がかかる。

4. Create auto-deployable test environment

Mavenのような高機能なビルドツールを使っているかどうかだと思う。
Mavenでは、一度ビルドしたjarライブラリは、ビルドサーバーに保存してくれる。
単にビルドすればよいだけではなく、テスト環境ごとにライブラリが違う場合や、複数の依存ライブラリのバージョン管理する場合、に必要になる。

大規模プロジェクトやパッケージ製品開発では、必須だろう。

5. Use code quality analysis

(引用)品質検査ねぇ。いやいやツールそのものを批判する気はないが,運用がまずくてうまく回ってないケースをよく見るんで,あまり乗り気じゃない。

正直,FindBugsやCheckStyleなどのインスペクションはプログラマ個々人がたしなみとしてやるべきだと思ってる。なんでプロジェクト全体のサマリ出しても自分がやるって意識が薄くなるんじゃないかなぁって。


これも非常に同感。
品質検査が単なる手続きになってしまい、品質Upにつながらないプロジェクトが非常に多い。

本当は、ソフトウェアメトリックスを採取して、2次開発以降の継続的な開発でソフトウェア工学の知識を使えるようにすることがしたい。


6. Use unit test

(引用)うまく行ったときは効果絶大なんだけど,度重なる仕様変更などでテスト資産が不良債権化しないように維持するのが大変なので,バランス取りがとっても難しい。
これもまた,ある程度のマメさがないと良いテストコードを組んでもらえない。


これも非常に同感。
UnitTestが重要な認識は、プロジェクトリーダーだけでなくプログラマも共有している。
しかし、2次開発以降の継続的開発が進むと、テスト資産そのものもプログラムだから2倍以上のコストがかかるように感じる。

UnitTestの威力を運用保守で感じる時は、2つある。
一つは、ソースのマージ作業。
もう一つは、サーバーやDBなどの環境周りがバージョンUpした時。

前者は、作業ブランチからTrunkへマージした時、UnitTestで問題なければ、最低限の品質と検証は立証されたことになる。
但し、UnitTestのプログラムのマージ作業もあるので、作業量も2倍に増える感覚だが。

後者は、Oracleに不具合があったのでVerUpしたとか、Tomcatの性能が遅いのでVerUpしたとか、JDKそのものをVerUPした場合。
例えば、Oracleでは、10g以前の古いバージョンでは、256日以上稼動したままだとハングアップするというバグがあったらしい。

サーバー環境やDB環境を変更することは殆どないが、2次開発以降の継続開発では、環境周りをVerUPする時もある。
この時に、UnitTestで問題なければ、少なくとも本番稼動できるお墨付きの一つになる。


果たして、あなたのプロジェクトは、6ステップのうちどれだけ実践しているだろうか?


| | コメント (0) | トラックバック (0)

メインラインモデルとソフトウェアプロダクトラインの類似性

アジャイルプラクティス勉強会in関西に出て、メインラインモデルをソフトウェア構成管理の視点から興味深い指摘があった。

組み込み系では、メインラインでソース管理していても、多種類の似たような製品を作る派生開発が多い。
例えば、iPodのように、似たような機能だがどれも微妙に仕様が異なる家電製品など。

元々、組込系製品やパッケージ製品では、製品ファミリーを展開して、多品種少量生産で売り込むビジネスが多い。
だから、製品ファミリーのソフトウェア構成管理にソフトウェアプロダクトラインの概念を持ち込む手法は、10年以上前から実践されてきた。

有名なビジネスモデルは、MSのOffice製品やMSが展開する製品群がそれに当たる。

本来、メインラインモデルのように、リリースブランチ・メインライン・作業ブランチのようにソース管理を複数のラインで管理する時、コア資産とアプリケーション独自の資産を分ける。

この時、メインラインがコア資産に相当し、個々の製品ファミリーはリリースブランチに相当するだろう。
そして、個々の製品開発チームは作業ブランチで開発しているだろう。


しかし、メインライン上でコアとなるソースは管理して、派生開発のソースはブランチで管理するが、結局ブランチは独立したソース管理になってしまい、構成管理が破綻するケースが多い、と。

確かに、一度、ブランチを切ってリリースしていくと、ソースがどんどん膨大に増えてゆき、マージ作業が大変になり、誰も手を付けられなくなるのが現状だろう。

更に、ブランチとメインラインのソース管理が独立してしまうと一番困るのは、共通ライブラリに緊急のバグ修正が発生した時、全てのブランチで確認を取らないといけない時。

昨今は、ノートPCが熱暴走したとか、電池が爆発したとか、会社の存続に関わるバグ修正が時に発生する。
だから、そのようなケースが発生した時に、確認を取るのに時間がかかりコストもかかる、と。

これはまさにソフトウェアプロダクトラインの発想を実践しようとして、結局できなかったという話そのもの。

コア資産という再利用できるソースが、結局、各ブランチで独自展開して管理できなくなり、最終的には手に負えなくなる現状を示している。

パッケージ製品開発を誰もが夢見て実践して、なかなか成功しない理由は、メインラインでコア資産を制御することが難しいことにあるのだろう。

だから、Webシステム開発では、再利用なんか考えずに3年でシステムをリプレースしてしまえばいい、という極端な発想で開発するスタイルもある。

だが、3年で開発資金の元が取れるのかという心配もあるし、プログラマにとっても、保守しにくいシステムを運用していくのは嫌なものだ。

たとえWebシステム開発でも、1次開発が大成功すれば、必ずリピートオーダーがもらえて、運用保守しながら2次開発を進めることが普通。
顧客と深い信頼関係を築いた後ほど、1度作ったシステムは当初の予想以上に長く使われて、2次開発、3次開発とどんどんカスタマイズした機能を追加して、膨れ上がっていく。

その時に、運用保守のリリースブランチと、開発中のメインラインが発生する。

SVNでの現実的な運用方法は下記と考える。

1次開発中:
 トランクでソース管理。

1次開発リリース直後:
 Ver1.0でタグ付け後、Ver1.0のリリースブランチを切る

2次開発中:
 2次開発のソースはトランクで管理。
 Ver1.0のリリースブランチでバグ修正が入ったら、必ずトランクにマージする。
 当然、バグ修正後にVer1.1のタグも付ける。

2次開発リリース直後:
 Ver2.0をトランクからタグ付けして、トランクからリリースブランチを作る。
 Ver1.0のリリースブランチは終了する。
 3次開発のソースはトランクで管理する。


つまり、生物進化の系統樹のように、リリース中と開発中のソースをきちんと分けて管理するのが現実的だろう。

パッケージ製品開発のように製品ファミリーを展開する場合は、もっと複雑な管理が必要になるのだろう。

バージョン管理はソフトウェア開発で必須なのに、意外にないがしろにされている気がする。

| | コメント (0) | トラックバック (0)

分散リポジトリの使い道

最近、MercurialやGITなどの分散リポジトリのバージョン管理が流行している。
これはどのような状況で使うのか?

使い道は、プライベートブランチ。
つまり、SVNのトランクに入れるには不完全なソースの一時コミットとして使う。

自分のワークスペースでプログラムがまだUnitTestも通していない時、丁度昼前になったらどこかにコミットしておきたい。

ペアプロで書いている一時状態のソースをどこかにコミットして、自分のマシンで同期したい。
他人のマシンでは、Emacsのキーボード配置が違うので使いにくい時があるから。

ノートPCで書いている一時状態のソースをどこかにコミットして、別のマシンで同期したい。
自宅と会社ではマシンが違うから。

これらの場合は、いずれも書いている途中のプログラムを別マシンに同期したい時等が多い。

そんな時に、分散リポジトリが有効に使える。
分散リポジトリは、中央集権型のSVNとは違って、プッシュ型なので、ローカルにコミットしているのと同じ感覚。

となると、分散リポジトリへのコミットと、ソース保存は同じ。
1日100回、分散リポジトリにコミットするのも普通だろう。

更に、分散リポジトリでは特定のリビジョンを消すことも可能だという。
Eclipseのローカルヒストリーのように、ローカルのソースの不要な履歴を消して、必要なリビジョンのソースのみを持ってくるのも可能になる。

バージョン管理、ソース管理はソフトウェア開発で当たり前にもかかわらず、この部分がボトルネックになっている時もままある。

もう一度、使い方を見直してみる。

| | コメント (0) | トラックバック (0)

2008/05/04

ユースケース駆動開発実践ガイド

「ユースケース駆動開発実践ガイド」を読んで、この手法がまさにRUPなんだな、とようやく気づいた。
理解した内容をまとめてみる。
#一部はメモなので論理的整合性は無視。

【1】ドメインモデルはプロジェクトの用語集

 「ユースケース駆動開発実践ガイド」では、プロジェクトで実際に使われている単語を全て収録した「生きている」辞書だ。
 単なるプロジェクトの用語集よりもはるかに優れている。
 それぞれの単語間の関係がグラフィカルに表現されているから。

【2】ユースケースは叙述的に書く

 「ユースケース駆動開発実践ガイド」では、ユースケースに「~しなければならない」という命令形が混じる時がある。
 機能要求は「~しなければならない」のように指示的に書かれた要求。
 機能要求を分離してユースケースに割り当てなければならない。

 ユースケースに機能要求が混在している時は、ユースケースが良くない兆候。
 ユースケースは要求とリンクしているが、要求から分離すべきもの。
 ユースケースは、実行時の振る舞い要求だから。

 ユースケースから機能要求は省く。
 ユースケースに機能要求が混在していると、オブジェクトモデルの用語で記述できなくなる。

 また、ユースケースの汎化は無意味だ。
 ユースケースの汎化を書くと、それはユースケースの具体例に過ぎない。
 ユースケースはクラスではない。
 ユースケースはユーザーガイドの断片。

 手続き型の発想でユースケースを書くと、「~させる」という受動態が多い。
 オブジェクト指向の発想でユースケースを書くと「~画面が~する」のような能動態が多くなる。

 イベントとその応答の流れとしてユースケースを書く。
 ユースケースはユーザーとシステムの対話が記述されている。

 ユースケース中の単語はドメインモデルに合わせる。
 ユースケースはオブジェクトモデルの用語で記述されるべき。

 外部システムは常にアクターとしてモデル化される。

 また、長いユースケーステンプレートは良くない兆候だ。
 ユースケース内に長い機能要求のリストを含めるべきではない。
 ユーザがシステムをどのように使うか、システムがどのように応答するかを書くだけ。
 ユースケースとアルゴリズムは違うから。

 ユースケース図はパッケージごとの図式化された目次。

 ユースケースには、必ず正常フローと代替フローを必ず明記する。
 ソフトウェアプロジェクトの複雑性の半分以上は、代替コースを扱うことで生じる。
 全ての代替コースを担保していることを確実にするのが重要。
 

【3】ロバストネス図こそ要求と設計の間のミッシングリング

 「ユースケース駆動開発実践ガイド」では、ユースケースからオブジェクトモデルを導出する技術として、ロバストネス図が大事。
 ロバストネス図は、ユースケースをオブジェクトの絵として表現したもの
 取りこぼしていたオブジェクトがロバストネス分析中で発見される過程を「オブジェクトの発見」と呼ぶらしい。

 バウンダリオブジェクトは画面単位に作る。
 用語体系の統制にもなる。
 バウンダリオブジェクトに対する明確な命名ができる。

 コントローラーは論理的なソフトウェア機能である。
 最近のシステム開発では、コントローラーを使いすぎる傾向が多い。
 だが、コントローラーを抽出する時、「~を表示する」コントローラーが多くなる。
 表示するコントローラーは必要だ。存在意義がある。

 ロバストネス図では、オブジェクトと機能を混在させて表示する。
 コラボレーション図と本質的に違う。

 シーケンス図上にはコントローラーオブジェクトが存在しない。
 コントローラーの80%は操作として実装される。
 つまり、バウンダリやエンティティのメソッドとして吸収される。

 ユースケース記述をシーケンス図に貼り付ける。
 要求から振る舞いを設計する時に役立つ。

 いかにコントローラーをドメインクラスの操作へと進化させるか、が大事だし、最も難しい。
 基本思想は、責任駆動。
 基本アーキテクチャは、凝集性の最大化、結合の最小化。

 「ユースケース駆動開発実践ガイド」は、ユースケース記述と実際のプログラミングの間にある大きいギャップを埋めるノウハウが書かれているように思う。

【4】ユースケースをTestlinkで保守する

 TestLinkというオープンソースのテスト管理Webツールがある。

 Testlinkを使うと、要求とユースケース、テストケースを登録すれば、理論上は一貫してトレースできる。
 プロジェクト管理ツールRedmineと同様に、要注目のツールだと思う。

| | コメント (0) | トラックバック (0)

批判を受けながら立ち位置を決める

今朝の朝日新聞にある橋下大阪府知事のインタビューで、ちょっと気になった点があった。

「橋下劇場」連日盛況 芸風に危うさとしたたかさと


 「常に世論の反応を見て、批判を受けながら自分の立ち位置を決めていく。それを学んだのはテレビメディアでしょうね。38歳の人生経験だけで決めるのは無理です」

 ちょっと思ったことについて書いてみる。

 指導者の立場にある人の役割は変化を起こすこと。
 指導者がビジョンを出した時、そのビジョンから議論や批判が起きたならば、周囲に変化が起きた事実を示す。
 変化を起こさない指導者は存在意義がない。いなくてもいい。

 変化を故意に発生させた時、周囲の批判や議論を受けて、何が真実であるかを見極めて、自分のビジョンを修正する時もある。
 自らの人生経験だけで決めるのではなく、周囲の議論から出てきた真実を受け入れて、自分の立ち位置を決めていく。
 
 ソフトウェア開発のプロジェクトリーダーでも同じ。
 そのプロジェクトのビジョン、ゴール、ゴールに至るまでのプロセスのイメージは、プロジェクトリーダーなら誰でも持っているだろう。
 そのビジョンをメンバーに説明して、納得してもらって、メンバーをゴールへ引き連れていく。
 この時、プロジェクトリーダーのビジョン、指示が間違っている時もある。
 特に、工数見積の部分だ。
 その時は、メンバーに無茶を言っても、実現できる可能性は低い。
 メンバーの意見も聞き入れながら、可能な工数を設定して、スケジュール調整することが頻繁にあるだろう。

 プロジェクトファシリテーションでは、KPTやふりかえりというプラクティスがある。
 これがまさに、プロジェクトのゴールやビジョンについて、メンバーがどんな意見を持っているか、メンバーがどのような反感を持っているか、を探り出す部分。
 メンバーの意見をいかにうまく取り入れて、プロジェクトを進めるか?
 
 プロジェクトリーダーの立場なら、ゴールやビジョンは正直変えたくない。
 変える部分はゴールに至るまでのプロセス。
 行き先は決まっているが、そこに至るまでの道のりは、その時々に合わせればいい。

 人生経験が浅くても、正しい手法を持っていれば、リーダーシップを身に付けることができる。
 橋下府知事のコメントから、そんなことを感じさせられた。

| | コメント (0) | トラックバック (0)

2008/05/02

大規模プロジェクトはバージョン管理が重要になってくる

ソース管理について良い記事があったのでメモ。

Subversionベストプラクティス

複数のアジャイルチームでのバージョン管理

複数のアジャイルチームでのバージョン管理」の指摘は非常に重要なので、まとめておく。

【1】バージョン管理の目的

1-1. Fail First
 コードのコンフリクトや統合の問題を早期に解決する。

1-2. 常にリリース可能
 どんなに悪いイテレーションでも、その成果物はリリース可能にならねばならない。

1-3. シンプル
 チェックインやマージ作業などのポリシーはシンプルで明確であること。

 オブジェクト指向のパッケージ原則の一つに「再利用できる粒度とリリースできる粒度は同じだ」という法則がある。
 つまり、最終的にリリース可能であるということは、その成果物が公開された時、他の誰もが安心して使える品質レベルを保障しているということ。

 我々プログラマは、結局、他の開発者が使えるライブラリにするためにプログラムを書いている。
 バージョン管理は、その開発インフラを支える最も基本的なインフラなのだ。

【2】バージョン管理が必要になる事情

2-1.小さなプロジェクトでは、SVNトランクだけにチェックインして、開発するだけでいい。

 SVNトランクが常に最新ソースで、ビルドもされて最も安定している状態。
 このレベルは、5~8人のPGが1個のチームで1個のwarを作っている事とほぼ同じ。
 
 しかし、本番リリース後、運用保守と2次開発が平行開発するような場合、初めてリリースブランチが必要になってくる。
 本番環境で動く本番モジュールはリリースブランチで管理する。
 緊急のバグ修正は、このブランチ上で行う。
 
 2次開発中のソースはトランクで管理する。
 このソースは本番モジュールに混ぜない。
 理由はビルドが不安定だからとか、新機能のリリース予定日は決まっていて、その日以前にリリースするのはビジネス上よろしくないなどの事情があるだろう。
 
 重要なことは、リリースブランチにコミットされたバグ修正ソースは、すぐにトランクにマージする。
 つまり、トランクは前バージョン互換であるのが基本ルールだ。

 これによって、トランクの機能はリリースブランチと同じか、それ以上になる。
 但し、トランクの品質は、2次開発のソースが混じっているので、リリースブランチと同等かやや落ちるはず。

2-2.大規模プロジェクトでは、更に複雑なバージョン管理が必要になる。
 
 例えば、小売系Webシステムを考えてみよう。
 そのシステムは、コンシューマ向けはS2Struts+Ajax、バックエンドのオペレーター向けはS2Dao+Flexで作るとする。
 このアーキテクチャで作る場合、DB層に当たるS2Daoとそれに関連する業務ロジック層は、S2StrutsとFlexの両方で使えるように共通化しておきたい。
 その理由は、S2Dao層は、S2StrutsとFlexの両方からテストされるので安定した品質を速く作りこむことができるからだ。
 
 だから、下記のような依存関係になるように、S2Dao層をjar化しておく。

S2Struts(war)→S2Dao(jar)←Flex

 このアーキテクチャでは、コンポーネント単位に開発チームが作られる。
 1チーム5人程度で3チームが作られるだろう。
 
 SVNトランクへS2Struts、S2Dao、Flexごとのメインラインが作られるだろう。
 更に、Mavenを使うと、このコンポーネント単位にバージョン付けできる。
 だから、war1.0.1は、jar1.0.4を使う、といった風にバージョン依存関係を指定できる。

 だが、複数のコンポーネントのバージョン管理のルールはどうあるべきなのか?
 基本ルールがなければ、jarのバージョンが上がるとwarやFlexで動かなくなる事象が頻繁に起こるだろう。
 この場合に、「複数のアジャイルチームでのバージョン管理」のやり方が使える。


【3】バージョン管理に出てくる概念

 ここで再度、「複数のアジャイルチームでのバージョン管理」にある概念を整理しておく。

3-1.メインライン
 トランクがリリース可能な状態であること。
 これによって、トランクがブランチを切る幹線になる。

3-2.コードライン
 メインラインモデルでは、ブランチはコードラインと呼ばれる。
 正確にはブランチはコードラインの実装と見なされる。

 ここで、コードラインが「堅い」「柔らかい」という概念が現れる。
 この概念は、コードラインの安定状態を示す。

3-2-1.堅いコードラインは安定していて、十分テストがされ、変更されることはほとんどなく、リリース間近のもの。
 例えば、リリースブランチに相当するだろう。

3-2-2.柔らかいコードラインは不安定で、テストがほとんどされてなく、変更もしばしばで、リリースには程遠いもの
 例えば、作業ブランチやタスクブランチが相当するだろう。

3-3.ベースライン

 コードラインの親(つまりコードラインが生成された時の生成元)はベースラインと呼ばれる。
 メインラインはベースラインを持たないコードラインとなっている。
 
 この概念は、メインラインとコードラインが系統樹のように書かれる場合に良く出るだろう。

3-4.コードラインには2種類ある。

3-4-1.リリースコードライン
3-4-2.作業コードライン

 メインラインより上にあるものは全てリリースコードラインと呼ばれ、これはメインラインより堅固なコードラインを意味する。

 メインラインより下にあるものは全て作業コードラインと呼ばれ、これはメインラインより柔弱なコードラインを意味する。

 つまり、リリースコードラインは本番モジュールそのもので、バグ修正時ぐらいしか手が入らないコードライン。
 作業コードラインは、開発チームが日々チェックインしてビルドしながら作りこむコードライン。

 普通は、作業ラインの1イテレーションがリリース可能状態として終わるたびに、作業ラインからメインラインへマージして、機能を反映する。
 リリースラインにバグ修正が発生したら、メインラインへマージして、バグ修正を反映する。
 この2つの作業によって、常にメインラインは最新機能と安定した品質が保たれる。

【4】バージョン管理の基本ルール

4-1.運用ルールは色々あろうが、「複数のアジャイルチームでのバージョン管理」によると「最も基本的なルールは、下記2点だ。

4-1-1.安定のための変更を常に受け入れること
 このルールは、リリースコードライン→メインライン、メインライン←→作業コードラインへのマージ作業を指す。

4-1-2.不安定の原因になる変更を持ち込まないこと
 このルールは、メインライン→リリースコードライン、Aチームの作業コードライン→Bチームの作業コードラインのマージ作業は不可を指す。

4-2.このやり方を大規模プロジェクトで置き換えてみる。
 すると、下記3つを常に管理する必要があるだろう。

4-2-1.リリースコードライン
 本番環境で実際に動くwar, jar, Flexモジュールそのもの。
 ソースにコミットする場合は、バグ修正だけ。
 メインライン(trunk)からの反映すら行わない。

4-2-2.メインライン
 最新機能と安定した品質を持つモジュール一式。
 いつでもリリース可能な状態に置いておく。
 つまり、追加システムをリリースするたびに、このメインラインからリリースブランチを作る。

4-2-3.作業コードライン
 開発チームが日々作業するモジュール一式。
 基本はビルドは通すが、色んな業務フローに耐えうる品質まで至っていない場合が多いだろう。
 
 また、SQLインジェクション対応でビッグリファクタリングする時や、新しいフレームワークを試す場合は、作業コードラインから別ブランチを作り、そこで実験することもあるだろう。


 上記のバージョン管理は、実は、大手SIerよりもオープンソースに従事する開発者の方が使いこなしている。
 例えば、RubyAPIやMozillaFireFoxでは、安定バージョンと新規開発バージョンを上記のように使いこなしている。
 そして、世界中の開発者から送られたバグ修正パッチや改善要望を、適宜マージしながら、オープンソースを育ててゆくスタイル。

 システムはリリースしたら終わりではない。
 リリース後の運用保守が大切と言われる理由は、バグ修正による品質改善モードと、改善要望による機能追加モードがぐちゃぐちゃになりがちだから。

 プログラマにとってバージョン管理は必須であるにも関わらず、実は使いこなせていない人は多くないだろうか?

| | コメント (0) | トラックバック (0)

« 2008年4月 | トップページ | 2008年6月 »