« 2008年12月 | トップページ | 2009年2月 »

2009年1月

2009/01/27

メトリクスの威力

チケット駆動開発を上層部へアピールするのに最も効果的なことは、現場の数字を提示することだ。

社長や取締役、管理職は、数字が非常に好きな人達。
彼らは、いつも売上の数字とにらめっこしている。
彼らは月次売上のために、請け負ったプロジェクトの進捗や品質をすごく気にしている。

チケット駆動開発を実践すると、チケットに日々の作業状態がリアルタイムに入力されるため、進捗をリアルタイムに見ることができる。

RedmineTracでは、生成されたガントチャートから、赤色のタスクが遅延しているのが分かる。
カレンダーを見ると、月別のタスクの一覧が表示され、取消線のないタスクは作業中であることが分かる。
ロードマップから、バージョン単位の進捗が出るので、マイルストーンまでの残日数と比較して間に合うのかどうか考えることができる。
チケット集計結果であるサマリから、バージョンやコンポーネント単位の残チケット数が即座に分かる。
Redmineのレポート機能から、バージョンと月別の工数のクロス集計が表示されるため、月別でどれだけのコストがかかったのか、即座に把握できる。

RedmineTracは、プロジェクトの進捗のメトリクスを色んな観点で出力してくれる。

更に、TestLinkを使えば、全テストケース数、ケース消化率、NGテストケース数、要件カバレッジなど、テスト工程の進捗を表すメトリクスを出力してくれる。

statSVNは、曜日別の開発者毎のコミット回数、システムのLOCグラフなど、開発者の貢献度合い、システムの規模を表すメトリクスを出力してくれる。

以上のメトリクスを定期的に上層部へ見せれば、現場の状態をリアルタイムに完全把握できる資料として非常に喜ぶだろう。

しかし、メトリクスは現場リーダーや開発者にとって諸刃の剣。
プロジェクトの進捗が良ければ上層部へアピールできるが、遅れていれば何故問題を放置しているのか、と問い詰められるだろう。

だから、ずる賢い人達は、これらのメトリクスを操作して、遅延しているのにあたかもプロジェクトがスムーズに進んでいるかのように、品質が確保されているかのように改ざんするだろう。

そうなると、メトリクスはもはや現場の状態を素直に反映したものでなくなる。
これが「メトリクスを過信しない」という意味の一つ。

チケット駆動開発でソフトウェア開発の諸問題が全て解決されるのではない。
チケット駆動開発は、現場の問題を強力に見える化するだけ。
溢れたタスクをRedmineが解決するわけではない。

結局、現場リーダーや開発者の技術力、マネジメント力という問題解決能力のレベルが試されるだけなのだ。

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

2009/01/24

Redmineにお勧めソース機能が欲しい

今日、XP祭り関西2009が無事終了した。
参加してくれた人、ありがとう!

「チケットファーストでアジャイル開発!」で講演した時、ぽろっと話した「お勧めソース機能」を参加者の一人から質問されたので、メモしておく。

【仕様】
Redmineのリポジトリ欄で、選択したソースを表示した時、関連する他ソース一覧を表示する。
具体的には、そのソースを過去に修正した全てのソースのうち、

・同じチケットでコミットされたソース
・同じリビジョンで何度もコミットされているソース

で頻度が高い順番に表示する。

【要件】
本来のイメージは、Amazonのお勧め商品やiTunesのお勧め曲の表示機能みたいなもの。
例えば、Amazonの商品画面では、「この商品を買った人は過去にこんな商品も買っています」という商品が頻度の順に表示される。
iTunesでも同様に、この曲をダウンロードした人は、他にこんな曲もダウンロードしてます、みたいな機能がある。

この機能は、商品や曲のようなデータと関連性のあるデータを頻度の順に表示して、消費者へ他の商品も買うように勧める。
昨今の小売系Webシステムでは、販促として重要視される機能。

この機能のアーキテクチャの本質はデータマイニングであり、例えば、レコメンドエンジンとして既によく知られている。
たくさんのトランザクションデータが溜まるほど、質の高い関連データを表示することができる。

このデータマイニングの手法をソフトウェアに応用した場合、どこに使いたいか?

僕が欲しい機能は、一つのソースを修正した時、関連する機能やソースを洗い出す場合に、この手法を応用したい。
つまり、このソースを修正する時、過去にこんなソースも併せて修正しています、と関連ソースが一覧表示されると嬉しい。

というのも、実際の運用保守では、簡単な仕様変更であっても、影響範囲が広くて工数がかかる場面はよくあるから。
例えば、注文画面を修正した時、注文の業務ロジックだけでなく、実は共通ロジックにも影響していたという関連する機能調査に使いたい。

この時、RedmineチケットとSVNリビジョンが紐づいているデータはDBに格納されているので、強力な変更管理として使える。
つまり、ソースからチケット、更には仕様や要件まで追跡可能。

この時に、一つのソースを修正しようとした時、過去にこんなソースも一緒に直してますよ、という情報がポップアップ表示できると、開発者は自ら注意して調べるようになる。

よくある例は、1次開発でたくさんバグ修正した機能は、2次開発で修正する時もバグが出やすいこと。
その時に、過去にバグ修正した機能を触る時、開発者も自ら気をつけてくれるようになる。

今はRedmineにそんな機能はないけれど、インフラは既にあるし、SVNリビジョン回数が多いほど、関連ソース表示機能は有用になる。

チケット駆動開発が指摘した「ソースとチケットの紐づけによる変更管理」機能には、物凄いポテンシャルがあると思う。

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

2009/01/18

Tracのワークフロー

Tracを使い始めて、Redmineと異なる視点を感じる所があったのでメモ。

【1】RedmineやTracを障害だけでなく要望も含めてタスク管理する発想は、Issue Trackingと呼ばれる。
元々、チケット駆動開発(Ticket Driven Development)は、バグ管理システム(Bug Tracking System)を汎用化した課題管理システム(Issue Tracking System)から発生した開発プロセス。

すると、障害管理で使われるステータスだけでは管理しにくい場面が出てくる。

例えば、ITILではシステム運用保守で、問題管理、インシデント管理、変更管理、リリース管理の4つの視点を提供する。

BTSのバグ管理は、問題管理と同じ。
問題管理のワークフロー(チケットの状態遷移図)は下記が普通だろう。

新規→担当→解決→検証中→検証完了→終了(リリース完了)

このパターンがプロジェクト管理ではおそらく最も基本的なワークフロー。
何故なら、開発者とテスト担当者がペアになって一つの問題を解決する基本的な作業パターンだから。
バグ修正という一つの成果物を二人の目を通すことによって、考慮漏れや検証漏れを確実になくせる。

だが、このパターンだけでSW開発全てが作業できるわけではない。

ベンダーへの問合せ、顧客から来た苦情への対応などのインシデント管理は、違うワークフローを必要とする。
ベンダーとのやり取りは下記のようなワークフローが必要だろう。

受付済→問合せ中→回答済→終了

つまり、インシデント管理は問題管理とは異なる状態遷移図になる。

TracやRedmineを実際のプロジェクト管理で運用し始めると、インシデント管理を運用しにくいとよく言われる。
その一番の原因は、BTSのデフォルトのワークフローである障害管理と現場で運用しているインシデント管理業務が対応できていないからだ。
バグ管理のステータスだけでSW開発全てを対応するのは所詮無理がある。

又、SW開発で最も制御しにくいワークフローは仕様変更。
このワークフローは、ITILでは変更管理で制御しようとする。

変更管理の基本フローでは、変更計画を作った後に、ソース修正とリリースを実施し、その後にレビューする。
下記のようなワークフローが必要だろう。

新規→設計中→方針決定→担当→解決→検証中→検証完了→終了(リリース完了)

方針決定のステータスまでは、設計者が担当し、その後は、問題管理と同じワークフローになるだろう。
このワークフローの途中で、仕様変更に対応する必要がないと判断したら、却下というステータスも発生する分岐もあるだろう。

結局、チケット駆動開発を実践しようとして混乱する根本原因の一つは、ワークフローと言う概念を認識していないから、と言える。
ワークフロー、つまり、チケットの状態遷移図は表裏一体の概念。

ここで、ワークフローとは、チケットの種類で分類すべき対象である。
Redmineでは、トラッカーと呼ばれる機能になる。
ITILの言う問題管理、インシデント管理、変更管理などは、Redmineのトラッカーの単位で管理すべき対象なのだ。

更に、このワークフローに出てくるステータスには、PGなら解決、テスターなら検証中のように、必ず一人の担当者がアサインされる。
上記の状態遷移図はアクティビティ図でも置き換えて表現できる。

上記をまとめると、SW開発の業務フローは、デスクトップアプリのイベント駆動プログラミングのように分析可能。
つまり、下記の3つの視点は同値。

チケットのアクティビティ図(フローチャート)
⇔チケットの状態(ステータス)遷移図
⇔チケットのステータスのデシジョンマトリックス(ステータスの組合せ)

この観点で、チケット駆動開発の代表的なツールであるTracとRedmineを比較してみる。

【2】Redmineでは、ワークフローを下記で制御する。
Web上の管理画面で制御できるので、非常に使いやすい。

Redmine.JP | Issue tracking system(バグ追跡システム)

Redmine.JP | チケットのステータスの意味

Redmine - RedmineIssueTrackingSetup - Redmine

つまり、Redmineでは、トラッカー(チケットの種類)、ロール(ユーザの権限)毎に、先行・後行ステータスのデシジョンマトリックスで制御する。

例えば、トラッカーには「バグ」「仕様変更」「ベンダー対応」「環境構築」のようにワークフロー単位で設定し、ロールごとに遷移できるステータスを制御する。
バグ修正のような問題管理は開発者やテスト担当者で相互にやり取りするが、変更管理では、最初に設計者が方針を決定した後に、開発者へ手渡すようなワークフローが必要になるだろう。
特に、最後にチケットを終了できる権限は管理者だけとし、必ず品質チェックを通るような運用は実際の現場では多いだろう。
つまり、Redmineでは、ユーザのロールによって、ステータスの変更を制御するのが簡単。

Tracでは、下記のような方法で制御するらしい。
trac.iniへ状態遷移のフローチャートを書くスタイル。

ワークフロー機能のカスタマイズ方法 - かおるんダイアリー

Trac-0.11のワークフロー - Do You PHP はてな

TracWorkflow ? The Trac Project

Tracでワークフローを追加するのは、正直難しい。
上記の設定方法を見ると、ワークフローというアクティビティ図で描かれたフローチャートを無理やり表現したものなので、trac.iniから理解するのは難しい。
できれば、trac.iniに直接設定するのではなく、RedmineのようにWeb上で制御できるようにして欲しい。

また、Tracでは、ワークフロー単位、ユーザのロール単位で状態遷移できる仕組みが僕にはまだ分からない。
管理者だけの問題管理用のステータスだけでは、インシデント管理や変更管理に対応するは正直無理がある。

残念ながらTracはRedmineよりもワークフロー管理機能が扱いづらいため、未完成なチケット駆動開発のツールのような印象を受ける。

しかし、Tracを扱う人達も上記の問題に気付いており、色々試されているようだ。
TracはRedmineよりもプラグインも多いため、ワークフローをカスタマイズできるプラグインが実現できればいいなと思う。

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

2009/01/12

ITの地殻変動はどこで起きているのか?

2009年になって、ITの地殻変動がどこに起こっているのか?を考えてみる。
#ラフなメモ書き。

【参考】
InfoQ: Martin Fowler氏が語る陥りがちなスクラムの落とし穴を避ける方法

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

チケット駆動開発 … ITpro Challenge のライトニングトーク (4) - まちゅダイアリー(2007-09-07)

【アジャイル開発の問題点】
1990年代後半から、サーバー+クライアントの2層方式を基本とするVBアプリからMVCを基本とするWebシステムへのリエンジニアリングがあった。
更に、システムが大規模化して、開発期間が短くなるSW開発の現場。

RUPなど、イテレーティブな開発プロセスの重要性が叫ばれるものの、実際の現場で運用するにはハードルが高かった。

2000年頃出現したXPは、ソフトウェアの歴史の中で、オブジェクト指向の次に当たるソフトウェアの革命。
SW開発が大規模化して官僚化していく中で、プログラマ中心の開発プロセスを提唱した政治的主張も併せ持つ。

オブジェクト指向は40年かかって、どのプログラミング言語でも当たり前の概念になった。
XPを代表とするアジャイル開発も、今後時間がかかっても、イテレーティブな開発プロセスの一つの例として普及するだろう。

アジャイルな開発プロセスの最大の特徴は、要件定義からリリースまでの短い期間で少しずつ開発していくこと。
このサイクルの単位がイテレーションと呼ばれ、小規模リリースというXPのプラクティスの一つにもなる。

アジャイルな開発プロセスの最大の利点は、重大な問題の早期発見。
要件漏れ、設計漏れ、あるいは、ビルド作業での重大な問題は、早期のリリースのタイミングで発見できる。
更に、顧客の要求が変更されても、次のイテレーションへ混ぜ込むことによって、システムへ反映できる。

しかし、最大の弱点は、イテレーションを管理するツールがないこと。
イテレーション計画は流動的なため、細かなタスク変更が多く、リアルタイムな進捗管理が難しい。

また、リリース後も機能追加や継続的なリファクタリングなどで、頻繁にソースが修正される。
更には、リリース後に稼動中の本番モジュールと、裏で開発中のモジュールの2つのコードラインが生きているため、バグ修正と機能追加が混在して、品質を維持するのが難しくなる。
つまり、高度な機能の構成管理ツールを必要とする。

もう一つ、XPが指摘した重要な点は、SW構成管理に関するいくつかのプラクティス。

ソース共同所有で、ソースのバージョン管理を再認識させた。
コーディング規約やペアプログラミングでソースの品質について再認識させた。
テスト駆動開発で、プログラマは、仕様をテストできる形でプログラミングするようになった。

そして、継続的インテグレーションで、コミットしたコードラインは、TestUnitで単体テストをクリアすることも含めて、常時リリース可能な品質を保証できるようになった。

そのおかげで、短期間のイテレーティブな開発スタイルが可能になる。

XPはScrumと異なり、マネジメント側面だけでなく、SW構成管理の側面も重視している。
その部分は、実は意外と意識から漏れていないだろうか?

【チケット駆動開発の意義】

チケット駆動開発のルーツは、BTS(バグ管理システム)。
古くは、Bugzilla、Mantis。

BTSは本来、障害管理に昔から使われていたが、このワークフローがとてもスムーズな為、障害だけでなくSW開発の一般タスクへ汎用化しようという発想が生まれた。
TracやRedmineは、チケット管理をメインとして、ガントチャート生成やバージョン管理との連携機能によって、プロジェクト管理機能を持つBTSを課題管理システム(Issue Tracking System)へ昇華させた。

そして、まちゅさんは、Tracのチケット管理からチケット駆動開発(Ticket Driven Development:TiDD)を提唱された。
まちゅさんの本来の主張は「チケット無しのソースコミット不可」。

このチケット駆動開発のアイデアを突き進めると、イテレーティブな開発を補完するアジャイルな開発プロセスであることが分かる。

チケット駆動開発の基本アイデアは、さかばさんによると、「BTSのチケットはXPのタスクカードと同じ」
XPでは、アナログのタスクカードでPostItなどで運用する。
チケット駆動開発では、チケットとしてタスクカードをデジタル化する。

チケットは作業指示書でもあるから、ステータスや進捗率を入力すれば、リアルタイムに作業状態を追跡できる。
更には、作業開始・終了日、予定・実績工数を入力すれば、ガントチャートを自動生成できるから、進捗管理に使える。
チケットは本来、バグ報告票でもあるから、バグ修正に関するチケットの集計結果から、信頼度成長曲線を作成して、品質管理に使うこともできる。

つまり、プロジェクト管理をチケット管理に置き換えることによって、プロジェクト内部の作業全てをリアルタイムにモニタリングできる。
チケット入力の運用さえきちんとできれば、イテレーション計画の頻繁な変更もコントロールできる。

更には、チケット集計結果やSVNリポジトリ統計のメトリクスを、プロジェクト運営の意思決定の材料として出力できる。

もう一つは、メインラインモデルと言う構成管理の発想。
メインライン(trunk)とそれから分岐したコードライン(branch)によって、本番運用モジュールと開発中モジュールの2つのソース管理を使い分ける。

メインラインモデルの利点は、バグ修正と機能追加という相矛盾した開発での品質を確保する。

本番運用モジュールはbranchとして管理し、障害修正のみ反映する。
開発中モジュールはtrunkとして管理し、機能追加して、いつでも最新機能を持つ。
当然、バグ修正のマージ作業はその都度、本番ブランチからtrunkへ反映させる。

このソース管理手法は、偶数バージョンは保守コードライン、奇数バージョンは新機能追加のコードラインと使い分けるRubyのように、多くの実践例がある。

但し、弱点は、マージ作業が発生することだが、Subversionならmergeコマンドによる自動化やマージトラッキング機能などで、マージ作業のコストは格段に下がりつつある。

【チケット駆動開発の新たな利点】

チケット駆動開発とメインラインモデルの組み合わせによって、SW構成管理に別の要素、変更管理の観点が出てくる。
これは、リファクタリング・バグ修正・機能追加など混在した修正理由による追跡が可能になったこと。

システムの大規模化によって、わずか1行のソース修正であっても、検証コストは大きくなる。
ソース修正の影響範囲が確定できなければ、安易にパッチを当てることもできない。

しかしながら、チケット駆動開発のインフラのおかげで、

「ソースAの修正で影響を受けた過去のソースはどれか?」
「バグXの修正はビルドYに反映されているか?」

の追跡が可能になる。

更には、メインラインモデルのインフラのおかげで、バグ修正と機能追加は別々のコードライン上で行うから影響範囲を狭められる。

上記の運用によって、ソースからリバースして設計するのが非常にやりやすくなった。

昨今のSW開発では、RailsやSeasar等のフレームワーク、JUnitなどのTestUnitによって、単体テスト品質は維持できる。
更に、継続的インテグレーションのおかげで、常時リリース可能なコードラインを保障できるインフラもある。
しかしながら、設計者が作る肝心の仕様書の品質が非常に低い。

その理由の一つは、動くプログラムもできていない時の要件定義や設計には必ず重大な漏れが発生しやすいこと。
これは、短期間のイテレーティブな開発で、早期に失敗を発見することで対応可能。

もう一つは、アジャイル開発によって、仕様書にも頻繁な修正が入り、その整合性を保障するコストが大きいこと。

仕様書を作るSEのモデリング力にも問題があろうが、SEの本来の仕事は、顧客の要望から本来の要求を吸い上げて、システムの論理的整合性を保障するのがお仕事。
一つの仕様の変更が他の機能にどれだけ影響を及ぼすのか、考慮できるインフラも必要。

その時に、変更管理のインフラがあると、例えば、過去のパッチの経緯から今回の修正では別の機能にも影響があるとか、今回の仕様変更で上がった別のリスクは既に過去のパッチで反映されているので対応不要、などのような回答を見つけることができる。

SEとは、要件や仕様の変更管理に関する仕事が実は非常に大きいのだ。

【チケット駆動開発の可能性】

チケット駆動開発は、XPのタスクカードをチケットへデジタル化することによって、下記の新しい視点をもたらした。

・バグ修正や機能追加、仕様変更などの新たなワークフローを定義できる
・チケット集計結果から、ソフトウェア・リポジトリ・マイニングによって有用なメトリクスを出力できる
・進捗、品質をリアルタイムに計測できるため、プロジェクト運営の意思決定の材料として使える
・ソースの変更をチケットと関連させることによって、ソースの変更理由が追跡可能になる

今、僕が持っている疑問点は、XPのストーリーカードは、チケット駆動開発のどの機能に配置されるべきなのか?という問い。

変更要求を親チケットに書いた時、更に細かな作業は子チケットとして分割されて、チケットの親子関係が発生する。
その場合、チケットの親子関係をどのように表現したら、プロジェクト管理で使い物になるのか?

この問いは、究極的には、要件管理に辿り着く。

チケット駆動開発は、SW構成管理に変更管理という観点をもたらした。
今は下記のトレーサビリティを保障するインフラまで作れる。

TestLinkのNGのテストケース
→Redmineのバグチケット
→修正ソースのSVNリビジョン
→Hudsonのビルド番号

しかしながら、要件は一体どこに配置すべきなのか?

今、試そうと思っているのは、TestLinkの要件管理機能。
TestLinkには、要件のCSVをインポートして、テストケースと紐付ける機能がある。
テスト実行後、テスト結果の画面で、要件がテストケースをどれだけ網羅しているか、更には、要件に紐づくテストがどこまで消化されているか、表示する機能がある。

この要件網羅の機能があるので、この機能を使って、W字モデルのような開発を行いたい。

すなわち、要件定義や設計工程で仕様書を作ると同時に、テスト計画やテスト仕様書も作り、そこで要件漏れや設計漏れをあぶり出したい。

丁度、テスト駆動開発が、テストプログラムを先に作ってから実装するように、テストケースを書きながら仕様書を作るようにすれば、検証可能にならない仕様は問題点として、はっきり出てくるだろう。

残念ながら、TestLinkのver1.7.4の要件管理機能は現場で使えるレベルではない。
しかし、ver1.8からXML-RPCが使えるので、RubyやPHPのプログラムでTestLinkを操作して、要件とテストケースのアサイン、更には要件カバレッジ出力を試している方もいる。

下流工程の構成管理は、オープンソースの各種ツールが揃ってきた。
目指すは、上流工程の成果物の品質Upのために、構成管理のインフラを整えることだ。


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

2009/01/06

エンジニアリング無しのアジャイル開発はありえない

ソフトウェア工学とアジャイル開発の関係について、平鍋さんの素晴らしい記事があったのでメモ。

【元ネタ】
An Agile Way > ソフトウェア設計で大切なこと(1/2) : ITmedia オルタナティブ・ブログ

InfoQ: Agileの衰退と凋落

オブジェクト指向やテスト技法をはじめとするソフトウェア工学の知識とスキルは、ソフトウェア開発に携わる人には絶対必要なもので、その上で、プロジェクトマネジメント手法としてのアジャイルがある。

ということは、もういちどちゃんと言っておこう。そう思った動機は、James Shoreの「Art of Agile Development」を訳したこと。そして、それはXPの本だったこと。
ここ3年くらいXPという言葉はAgile界では下火になっていて、AgileといえばScrumという風潮だったのが、「エンジニアリングの無いScrumは所詮うまく行かない」、というJames Shoreの当然な一撃があった。

最近思うのは、20代のプログラマの技術レベルが高い割には、30代以降の管理者の技術レベルが低く、特に新しいマネジメント技術を取り入れる能力が低いことだ。

アジャイル開発の有用性がこれだけ高まっているのに、管理者になるほど、自分が過去に作りこんだプログラミング技法やExcelによる管理技術に固執しがち。
だから、システムの大規模化、プロジェクトの短納期化の流れに付いていけなくなっている。

むしろ、20代のオープンソースに関わるプログラマの方が実は、RedmineやTracによるチケット管理を自然に使いこなしている。
更に、trunkとbranchによるメインラインモデルでコードラインを保守することによって、バグ修正と機能追加による並行開発を上手に運用している。

かと言って、

・Redmine/Tracのチケット管理
・Subversionのメインラインモデル
・TestLinkのテスト管理
・Hudsonによる継続的インテグレーション

の環境無しで、朝会やふりかえりだけのマネジメント手法を駆使しても、昨今の複雑化したSW開発を運用していくのは難しいだろうと思う。

SW開発のプロジェクト管理は、マネジメントだけでなく技術力も当然必要。
ツールとマネジメント(ツールの運用)がうまく組み合わさって、初めて開発プロセスが改善されていくはず。

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

2009/01/04

複雑度と単体テストケース数の相関関係

garyoさんから、ソースの複雑度と単体テストケース数について有益なアドバイスを示唆してもらったので、メモしておく。

SourceMonitor Version 2.4

SourceMonitorはフリーで、以下の言語のソースのソフトウェア複雑度(McCabeのサイクロマチック数)を測定できる。
例:C++, C, C#, VB.NET, Java, Delphi, Visual Basic (VB6) or HTML

McCabe's cyclomatic complexity

SourceMonitorで求められる複雑度(McCabeのサイクロマチック数)は、モジュール内の分岐の数(+ループの数)で計算される。

複雑度の数値は、下記の意味を持つらしい。

10 以下であればよい構造
30 を越える場合,構造に疑問
50 を越える場合,テストが不可能
75 を越える場合,いかなる変更も誤修正を生む原因を作る

話によると、複雑度が15以上ならばコードレビューを実施する会社もあるらしい。

当然、複雑度が大きいソースはIF文やFor文がネストしまくっている場合が多いから、複雑度が小さくなるようにリファクタリングする。
ソースをリファクタリングすべきかどうか判断する場合に、複雑度のメトリクスは使えるだろう。

更に、複雑度と分岐網羅(C1)は、下記によれば、ほぼ等しい関係にある。

循環的複雑度 - Wikipedia

M(循環的複雑度 ) は、完全な分岐網羅率(C1)を達成するのに必要なテストケース数の上限である。
一般に、あるモジュールを完全にテストしようとした場合、全ての実行経路を通す必要がある。これの意味するところは、循環的複雑度の大きいモジュールの方が経路数が多く、従ってテストケースも多く必要になるということである。また、複雑度の大きいモジュールは、ソースコードの意味を理解するのに多くの経路を追わなければならず、読解がより困難になる。
また、複雑度の大きいモジュールは凝集度が低いと予想される。この相関を想定する理由は、分岐点(判断ポイント)が多いモジュールは、単一の機能以上のものを詰め込もうとしている可能性が高いためである。


つまり、下記の結論が得られる。

ソフトウェア複雑度(McCabeのサイクロマチック数)
≒分岐網羅(C1)のテストケース数
≒単体テストケース数


JUnitを使っているならば、djUnitで単体テストのカバレッジが100%になるようにテストプログラムを作る。
この時、djUnitでカバレッジ100%になるためのテストメソッド数は、分岐網羅のテストケース数以上になるはずだろう。

つまり、ソフトウェア複雑度で得られる数値よりもテストメソッド数が少ないならば、最低限の単体テストをクリアしていないことになる。
実際の単体テストでは、分岐網羅のテストは当たり前であって、条件網羅(C2)のテストを完全でなくとも近いレベルまでテストしなければ、ケース漏れしているだろう。

SourceMonitorを実際に使ってみたら、複雑度が50(!)のソースもあった。
これは、分岐網羅のテストケース数だけで50個必要なわけで、単体テストでケース漏れが発生している可能性は高い。

昨今の業務システムは、フレームワークによる自動生成やテストプログラムも含めれば、10万行近いソース行数は当たり前。

例えば、プログラム1個当たり100行で、1000個のプログラムから業務システムが成り立っているとする。
そのシステム内のプログラムの複雑度の平均が10だとすると、単純に計算すれば、1万個の単体テストケース数が必要になる。
実際はテスト不要のプログラムもあるから、ケース数は減るだろうが、これだけの規模の単体テストをこなさなければ、品質を確保できないのが実情だろう。

いくらテスト駆動開発を実践していると言っても、単体テスト品質をクリアするために必要な最低限のケース数は必要。
ソフトウェアテストの知識無しでJUnitを使えば、無意味にケース数が増えてしまい、コストの割が合わなくなる。


JUnitを使っているなら、djUnitでテストのカバレッジを測定できる。
その時、最低限のテストケース数でもって100%網羅するように作る時に、上記の法則が役立つだろう。

テスト駆動開発に従事するプログラマは、テストケースの品質Upに注力しないといけない。

【参考ページ】
ソースコードのメトリクス(品質測定)を行うツール - ふにゃるん

コードの複雑度の判定基準は、"Complexity"のようです。このパラメータが"McCabeのサイクロマチック数"で合っているのかな?と思って、色々チェックしてみたんですが、「合って」いる模様です。

ソフトウェアテスト - Wikipedia

命令網羅(C0)、分岐網羅(C1)、条件網羅(C2)の説明がある。

【追記】
@akiyama924さんの指摘の通り、分岐網羅(C1)の場合、テストケース数は、ソフトウェア複雑度で得られる数値よりも小さくなる場合はある。
しかし、だからと言って、「 if (conditionXX) {xxx;} という行が10個並んでいるだけのコード」は、たった2個のテストケースだけで十分とは言えない。
まともなレビューアならば、条件網羅に近いテストでやり直せ、と突き返すだろう。
言いたかったのは、ソフトウェア複雑度に比例してテストケース数も増えるよ、ということかな。

akiyama924さんのツイート: "「ソフトウェア複雑度で得られる数値よりもテストメソッド数が少ないならば、最低限の単体テストをクリアしていないことになる」 https://t.co/wk3Bss61gv ↑ たぶん勘違いかと。"

akiyama924さんのツイート: "たとえば、 if (conditionXX) {xxx;} という行が10個並んでいるコードがあったら、McCabeの複雑度は11になるけどテストメソッド数は最低2つで分岐カバレッジ100%になるから。"

akiyama924さんのツイート: "書きたかったのは、「ソースコードがどんな構造であったとしてもMcCabeの複雑度の数以内のテストケースで分岐カバレッジを100%とするテストを実施可能」かな。"

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

SW構成管理とはそもそも何なのか?

チケット駆動開発をRedmineで運用し始めて、SW構成管理(Software Configuration Management:SCM)を強く意識するようになった。
しかし、SW構成管理をきちんと定義している書籍もHPも、日本には殆ど存在しない事実を知って、愕然とした。

CMMIでも構成管理プロセスを定義しているけれども、僕の中ではフィットしない。
抽象的すぎて、現場で運用できるレベルではない。
ITILの構成管理が、僕の中では最もフィットするが、何が核心なのか分かり辛い。

ソフトウェア構成管理を定義しているHPの文章を記載しておく。
#以下は、考えてみた書きかけのメモ。

【元ネタ】
ソフトウェア構成管理 - Wikipedia


1.構成の識別 - 修正を施すべきコードはどれか?
2.構成の制御 - 製品のリリースとその修正を制御する
3.状態の記録 - コンポーネントの状態を記録し報告する
4.レビュー - コンポーネント間の一貫性と完全性を保証する
5.ビルド管理 - ビルドのためのプロセスとツールを管理する
6.プロセス管理 - 組織としての開発手法を厳守する
7.環境管理 - システムの基盤となっているハードウェアおよびソフトウェアを管理する
8.チームワーク - 開発に関するチーム内のやりとりを促進する
9.バグトラッキング - 全ての障害について対処状況を追跡可能とし、かつコード修正と対応付ける

サービスサポート(ITILの構成管理) - Wikipedia


サービスを提供する為の情報システムは、ライフサイクルの中で大なり小なり様々な変更が発生する。サービス開始時からその構成情報が一切変わる事無く、サービスの提供終了まで、あるいは情報システムの更改まで保たれるという事はまずありえない事である。

構成管理では実在する全ての構成アイテムを明確にしたITインフラストラクチャとサービスの論理モデルを提供する事で効率的なサービスを提供する為の情報の維持管理を行う事を目的として以下の目標を掲げている。

1.すべてのIT資産の明確化
2.構成管理で管理する情報を他のプロセスへ提供する
3.ITインフラストラクチャと構成記録の整合性検証を行う

【福井信二が語る:第3回】構成管理・プロジェクト管理の原理原則 - 組み込み開発 - Tech-On!


構成管理の狙いは,成果物が徐々に細分化されていく変化と,同じ成果物の状態の変化を管理することである。

ソフトウエア構成管理の標準として「IEEE Standard for Software Configuration Management Plans(IEEE Std 828-1998)」および「IEEE Guide to Software Configuration Management(IEEE Std 1042-1987)」がある。これらは変化という「関係」を管理するものであり,「物」を管理するハードウエアの構成管理とは異なる。

構成管理で重要なのは,(1)構成識別,(2)ベースライン&プロモーション,(3)変更管理,(4)ステータス&アカウンティング,という4つの考え方である。

(1)構成識別
ソフトウエアが段階的に詳細化されていく様子を管理する技術である。
最初にすべての成果物を定義しようとするのは現実的ではないという考えに基づく。
その代わりに,誰が,いつ,何を定義するのかを,ソフトウエア構成管理計画書と呼ばれる表などを使って計画しておく。
これにより,適切なタイミングで物事を定義できるようになる。

(2)ベースライン&プロモーション
成果物の状態の変化を管理する技術である。
これは,ソフトウエアは成長するという原則に立つものだ。
基準線を設け,その基準線を越えたかどうかを判定することによって成長を管理する。

(3)変更管理
一度リリースしたものに対する変更は,その変更の主体者だけのものではなく,利害関係者すべてに影響する。
そのため,きちんとした組織を作って徹底的に管理しようというのが変更管理の考え方だ。
構成管理委員会(configuration control board)を組織して管理しようという動きが米国から発生した。

(4)ステータス&アカウンティング
構成管理の活動を通じて得た情報を,ソフトウエア開発の進捗の把握に使おうという考え方である。
構成管理の仕組みをうまく構築すれば,機械的にデータを集めるだけで進捗が分かるようになる。

Software Engineering Platform Blog > バージョン管理とソフトウェア構成管理の関係 : ITmedia オルタナティブ・ブログ


ソースコードなどのプロジェクトの成果物を管理する手段として、バージョン管理とかソフトウェア構成管理と言うものがありますが、この2つの違いというのは意外と知られていないものです。

というか、厳密な定義がないに等しく(各書(各所)によって同じ言葉を異なった意味合いで用いていることがあるため)非常に紛らわしかったりします。

広義のソフトウェア構成管理
  = 変更管理(Change Management)
  = 狭義のソフトウェア構成管理 + 変更依頼管理(Change Request Management)

といった式のイメージになるでしょうか。

1.バージョン管理(Version Control):
ソースコードなどのファイルを「いつ、誰が、なんのために、なにを、どのように」改訂したのかを版(リビジョンやバージョン)として記録し、構成の把握などに役立てること。

2.ソフトウェア構成管理(Software Configuration Management):
プロジェクトの成果物の構成を正確に記録し、必要に応じて過去の構成であっても正確に再現することができるように管理すること。
基本要素としては、バージョン管理(Version Control)、作業領域管理(Workspace Control)、ビルド/リリース管理(Build/Release Control)、プロセス制御(Process Control)が求められる


【考えたこと】
上記から、SCMを自分なりにまとめてみる。
SCMの目的は、成果物の細分化や状態の変化を管理して、構成アイテム(Configration Item)の任意のバージョンを再現できるようにすること。

1.バージョン管理
1-1.構成アイテムが段階的に詳細化される過程を管理する
1-2.構成アイテムの修正履歴を管理する

2.変更管理
2-1.構成アイテムの状態を記録し、一貫性と完全性を保証する
2-2.全ての障害の状態と対処を残し、ソース修正と紐づける

3.ビルド管理
3-1.いつでも最新バージョンの製品をビルドできる
3-2.リリースした製品の任意のバージョンを再現できる

4.マネジメント
4-1.構成管理の集計情報(メトリクス)をSW開発に活用する
 →ソフトウェア・リポジトリ・マイニングによって、プロジェクト管理に役立つメトリクスを出力して、SW開発の意思決定の判断材料にできる。

SCMで重要な概念は「バージョン」。
バージョンは2つの意味を持つ。

1.ある時点のシステムをいつでも再現できるポイント(タグ、バージョン)
2.ある時点でステークホルダー(顧客、開発者など)が要件や仕様などで合意した状態

バージョンがあるから、切り戻しポイントにいつでもロールバックが可能になる。
バージョンが発生するタイミングは、構成アイテムの変更をコミットするタイミング。
あるいは、別のアクターへ成果物を納品する時にバージョンが発生する。

例:お客から開発チームへ、要件を仕様として確定する。
←これはまさに、仕様というベースライン。
 ベースラインがSLA(品質保持契約)にも関連してくる。

例:開発チームからサーバーセンターへモジュールを送付する。
←ビルド番号を付けたモジュールを渡すから、ビルド番号にChangeLogが書かれているはず。

つまり、構成管理はSW開発プロセスをトランザクションに喩えた時、トランザクションマネージャに相当するだろう。
各工程の担当者の作業を一つのトランザクションと見なして、システムの整合性や一貫性を保障する仕組みなのだ。

SW構成管理のインフラがあるからこそ、プログラマや設計者は自分のアイデアを簡単に実装できる。
SW構成管理のインフラは、水道や電気のように、当たり前で安価である方が良い。



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

2009/01/03

RedmineとHudsonの関係付け

Redmineのチケットとバージョン管理を連携できる機能は、変更管理のインフラを提供してくれる。
変更管理について考えたメモ書き。

【元ネタ】
PERFORCE ソフトウェア構成管理の高度な実践方法(ベストプラクティス)

【1】変更管理が必要な場面

SEと呼ばれる人の仕事を眺めてみると、要件や仕様に関する変更管理プロセスに従事している時が多いことに気付く。
SEの一番の仕事は、顧客から要件を聞き取り、仕様書としてまとめて、開発者へ仕様を提示する。
つまり、業務のインターフェイスを設計すること。

設計工程で完璧な仕様書が作られる可能性は低い。
むしろ、要件漏れ、設計漏れが開発や結合テスト、あるいは受入テストで大きなリスクとして発覚することが多い。

昨今のシステム開発では、SeasarやRailsのような優れたフレームワークがあり、JUnitのようなテストユニットがあるので、単体テストをクリアした品質は確保できる。
しかし、肝心の仕様書が高い品質で開発者へ提示されるという仮定がそもそも間違っている時が多い。
だから、間違った設計書、低品質な仕様書を元にプログラムを作るから、当然、顧客の要望とずれたシステムが出来上がってしまう。
プログラマよりも設計者が作る成果物の品質の方がはるかに低い場合が、最近は多いように見られる。

仕様漏れが発生する理由の一つは、実際にプログラムを組んで動かしてみないと分からない部分がSW開発では多いから。
だから、アジャイル開発のようにインクリメンタル型開発では、小さく作って小刻みにリリースして、問題を早めに嗅ぎ取ろうとする。

他の原因として、たった一つの要望や仕様変更で影響を受ける機能はどれか、提示された仕様はシステムに確実に反映されているのか、という調査やその設計が不十分な時が多いように思う。
昨今の業務系Webシステムは、数万行に膨れ上がっているから、わずか1行のソース変更でシステムに影響を及ぼす可能性があるから、細心の注意を払う必要がある。
また、保守されていない仕様書がExcelで散在しているならば、稼働中のシステムにある機能の詳細な一覧を探すことすら難しいだろう。

稼働中のシステムにバグがあったとしても、顧客はバグありの運用をしている時が多い。
たとえバグがあっても、動いているシステムの方が、リアルタイムに保守されない仕様書よりも正しいのだ。

設計者は、ソースから仕様をリバースして設計するようになるが、この時に、過去のパッチの変更理由、モジュールのビルド履歴、ChangeLogがあると非常に役立つ。
パッチの変更理由を元に、仕様変更で影響を受けるかどうか、判断を下す材料になる。

【2】チケットトラッキング機能

Redmineでは、チケットとSVNリビジョンを紐付ける機能があり管理画面で簡単に設定できる。
SVNコミット時に「refs チケットNo」「fixes チケットNo」「#チケットNo」をログへ追記すると、リポジトリブラウザからチケットへ遷移できる。
更には、チケットから、チケットに関する修正を受けたSVNリビジョン全てがリンクされている。

この機能のおかげで「ソースAの過去の修正で影響されたソースはどれか?」を探すことができる。
下記のような流れになるだろう。

【Subversion→Redmine→Subversion】
ソースAのコミット履歴を全て洗い出す

コミット履歴から全てのチケットを洗い出す

チケットから全てのSVNリビジョンを洗い出す

SVNリビジョンからコミットされた全ソースを洗い出す

Redmineでは上記の作業を画面上で見て操作するか、全文検索で洗い出すだろう。
少なくとも、ソースのコミット履歴から、過去にどんな仕様でソースが影響を受けたのか、チケットから調べることができる。

RedmineのDBは上手に運用すれば、要件や仕様も蓄積されるから、いつでも全文検索の対象となる。
Excelに書かれた仕様よりも、DBにある方がはるかに探しやすいメリットがある。

【3】ビルド履歴との連携機能

Redmineのプラグインsimple_ciを使うと、ビルドツールと連携することができる。
ビルドツールとBTSを連携するメリットは「バグXの修正はビルドYにあるか?」という質問にすぐに回答できるインフラを提供してくれるから。

このインフラがあると、結合テスト以降のバグ修正で大きな威力を発揮する。
特に、デグレが起きていないかチェックするのに効果的だ。

Redmine - PluginSimpleCI - Redmine

但し、Hudsonのビルド履歴をRSSリンクする場合に、Rubyのsimple-rssモジュールをrequireしないと動作しない。
下記のパッチを反映すると、Redmineのsimple_ciタブにHudsonのビルド履歴が表示されるようになる。

Hudson support for simple_ci

Redmine - Feature #2163: Hudson Plugin - Redmine

また、HudsonでもRedmineプラグインが下記でリリースされている。
Hudsonのビルド履歴には、ビルドに取り込まれたSVNリビジョンのコミットログが表示されている。
このプラグインで、ビルド履歴に書かれたRedmineチケットがリンクされるので、Redmineへ相互リンク可能になる。
日本人作者の方に感謝!

Hudson Redmine plugin 0.6 - @Inject

Redmine Plugin - hudson - Hudson Wiki

上記の使い方は下記になるだろう。

【Redmine→Hudson】
Redmineのsimple_ciタブでHudsonの直近のビルド履歴を表示

Hudsonのビルド番号のリンク押下

Hudsonの該当ビルド番号の画面に、ビルドに取り込まれたコミットログ全てを表示

【Hudson→Redmine】
Hudsonのビルド番号の画面を表示

表示されたコミットログにあるチケットNoのリンク押下

Redmineチケットを表示

Redmineチケットに表示されているSVNリビジョンから該当リビジョンを探す


ITILの講義を聞いた時、昔は問題管理に力点を置いていたが、昨今は構成管理や変更管理が重視される傾向がある、という話があった。
バグ管理システムRedmineと常時統合ビルドツールHudsonを組み合わせれば、変更管理の強力なインフラになりうる。


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

2009/01/02

チケット駆動開発でソースが綺麗になる

チケット駆動開発とプログラムの品質に関するメモ書き。

【1】チケット駆動開発でソースが綺麗になる

以前のプログラミングは、ソース1行とコメント1行をペアに書くのが普通だった。
実際は、プログラミング設計書の該当箇所をそのままソースにコメント化して、そのコメントに合わせて実装する開発スタイル。
又、障害修正が発生するたびに、修正日と障害管理No、パッチの範囲を示すコメントを入れていた。

たくさんの人のパッチが入るたびに、コメントが増えて、ガラクタがソース中にどんどん増えていく。
最終的に、本番稼働中のソースはたとえコメントであろうとも、コメントを削除するだけのリファクタリングすらできなくなる。

おそらくこの開発スタイルは、汎用機+Cobol時代に作られたものだろう。

昨今のプログラミングスタイルでは、ソース中に処理説明や修正箇所のコメント化はしない。
仕様に関するコメントは全てチケットへ書く。
ソース中に処理とほぼ同値な無駄なコメント、修正履歴を書く必要なし。
それらは、チケットというソースの一つ上のメタレベルに保持すべき情報。

チケット駆動開発のおかげで、ソースは綺麗になる。

【2】チケット駆動開発がデグレードを防ぐ。

チケット駆動開発が提供する変更管理、構成管理がデグレードを防ぐ。

デグレという用語 - プロフェッショナルプログラミングの世界 - Yahoo!ブログ

デグレード - @IT情報マネジメント用語事典

デグレが起きやすい根本原因は、バージョン管理が徹底されていないこと。
どのバージョンにどのバグ修正が反映されているのか、という管理は、プロジェクト管理の中で最も基本的な作業の一つ。
バグは結合テスト以降で多発するため、数多くのバグ修正のパッチを副作用無しに反映させるのは非常に難しい。

XPの継続的インテグレーション(Continuous Integration)を実施しているならば、trunkをいつでもリリース可能な品質で保障してくれるので、即座にビルドしてリリースできる。

全ての障害について対処状況を追跡し、かつコード修正と対応付けるバグトラッキング機能は、まさに構成管理の重要な機能の一つ。
バグ管理システム(BTS)は、このバグトラッキング機能を提供してくれる。

チケット駆動開発は更に、チケットとソースのリビジョンを相互リンクするインフラを提供するため、構成アイテム(Configration Item)の状態を管理しやすくなる。
「要件→チケット←ソース」というトレーサビリティのおかげで、ソースの修正理由をいつでも誰でも追跡できる。
仕様がコロコロ変わる場合、その履歴をチケットに残せるため、本来の要件を探る手がかりになる。

チケット駆動開発は変更管理のインフラも提供してくれる。

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

« 2008年12月 | トップページ | 2009年2月 »