スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

モジュール分割とタスク分割 - 誰のためのデザイン?

困難は分割せよ
方法序説』 - デカルト

ソフトウェアの設計上重要な二つの要素、モジュール分割とタスク分割。その目的と必要性、効果とともに、初心者が陥りやすい過度な分割による弊害について書いてみたいと思います。

モジュール分割は誰のため?

まず「モジュール分割」ですが、その目的は、ソフトウェアの意味的、機能的な単位に分割することにより、可読性や再利用性、あるいは、複数人開発での分担効率をあげようというもの。ソフトウェア設計における最も基本的な部分であり、最終的な、成果物の品質を左右する重要な設計要素ですね。

さて、モジュール分割でググると、STS分割技法、TR分割技法などの技法を紹介するページがあたります。
例えば以下あたりはまとまっていて参考になります。 私の場合、基本組み込み開発の世界にいますが、開発の現場でこれら単語を聞くことは少ない気がします。組み込みソフトの開発が大規模化してきたあたりから、組み込みでもオブジェクト指向設計が浸透しているので、最近の「オブジェクト指向ネイティブ」な世代には、クラス設計とか、デザインパターンから入った人が多いからかもしれません。そういう方には以下記事が、構造化プログラミングを経てオブジェクト指向に至る歴史がよくわかっておすすめです。

さて、前振りはここまでにして、今回の主題に入りたいと思います。それは、モジュール分割はそのソフトウェアを搭載した製品やサービスのためのものではないという点です。モジュール分割の意義は、
  • 開発者のため : ソフトウェアの可読性、分業効率の向上
  • 部品の再利用のため : 成果物の一部(又は全て)を使った派生開発
にあります。

そうはいっても、実際は、ソフトウェアの品質は、それを作る「人」に依存しますので、開発効率をあげることが、プログラムの方が品質に直結するので、上の話は極論ですが、何のためかという観点は非常に重要です。この考えに立てば、「成果物として何をつくるか」よりも、「誰が作るか、どうやって作るか」、そして、「成果物の再利用のスコープはどこまでか」が、モジュール設計を考える上で重要になるからです。

なぜこんなことを強調するのかというと、ソフトウェアのモジュール設計を見ていると、過度なモジュール分割がなされているケースが多いように思うからです。 4788514346 もちろん、ソフトウェアの部品化や階層化は、再利用性という観点で非常に重要な観点なのですが、全てのプログラムがそれらを考慮しないといけないというわけではありません。むしろ、再利用性を全く必要としない部分について、過度なモジュール分割を行って、厳密なインターフェースを定義していくことで、開発者が増えたり、必要以上のドキュメントやテストが増えることになりかねません。内部設計としてきちんとモジュール化するのはもちろん必要ですが、そこを外部公開してしまったとたん、害の方が多くなることがあるので注意が必要です。また、拡張性が全く必要ないとわかっているようなケースで、過剰なフレームワークを作ったりするのも、同じく害しかありません。

本来のスコープを超えた過剰設計は、百害あって一利なしです。

タスク分割は何のため?

もう一つのテーマであるタスク分割について。モジュール分割が静的な分割であるのに対し、こちらはプログラムの動的なふるまいを決定する上で重要な要素です。タスク分割というと、uITRONや VxWorksのようなRTOSの設計がイメージされますが、Linux等の非リアルタイムシステムにおけるプロセル分割、スレッド分割でも同じような考え方は必要です。(※ 厳密にはメモリ空間の扱いとか、リアルタイム性の保証の話とかで、違う点はありますが。)
タスク分割の動機は大きく分けると以下二点になります。
  • (1) モジュール化のための分割
  • (2) 並列性、リアルタイム処理のための分割
(参考: リアルタイムシステムの開発手法)

(1)の方は、先のモジュール分割の延長ですね。その機能毎にタスクを割り当てようというものです。タスク分割にとっては(2)の方が本質で、基本的には独立した実行コンテキストをもって、並列処理させることが主な目的です。(2)をもう少し細かくわけると、
  • 処理要求の間隔とそれに対する処理時間の吸収のため、処理タスクをわける
    (例) 入力デバイスからのイベント受付と、それをキューイングして順次処理するタスクをわける
  • 互いに独立した処理の並列実行
    (例) 複数クライアント毎に処理タスクをわける
  • リアルタイム性の高い処理の優先実行
    (例) 緊急度の高いタスクに高優先度を割り当てて、優先的に割り込み処理させる。
あたりでしょうか。これらに該当しない処理は、実行時の要求事項という観点からは特にタスクにわける必要がないので、あるとすれば、(1)モジュール化のための分割、ということになります。

確かに、機能単位にタスクを分けるのは、ソフトウェア構造をわかりやすくする上で有用なことも多いのですが、これが過剰すぎる場合があります。分割された各タスクが各々完全独立、依存関係なく並列動作できるものなら問題ないですが、これが一連の手続きの前後、あるいは、上下関係出会ったりする場合が問題です。タスク分割するということは、タスク間のやりとりは、関数コールではなく、キューなりイベントフラグなりのメッセージになっているはずですが、この時のタスク間の機能呼び出しは、同期型のものもあれば、非同期のものもあるでしょう。ここでいう同期型は、要求メッセージを投げた後、結果応答があるまで、イベント待ちで要求元タスクを待ち状態にさせるというものを指しています。これって、単なる関数コールと何が違うのでしょうか?一件、独立性が確保されて、可読性があがったように思えるのかもしれませんが、 機能呼び出しがメッセージになると、
  • ソースコードツアーや問題発生時のバックトレースが困難になる
  • コールグラフが作れないので、静的解析が困難
  • コンテクストスイッチが入ることで、処理負荷が増える
ということで、実行効率や解析性を落とすことになります。

このようなモジュールに紐付いた不必要なタスク分割は、先に書いたような過度なモジュール分割がされたシステムでよく見かけます。おそらく、モジュール分割した単位で担当者がかわっており、それぞれがつくりやすいように個々でタスク設計をしたために、不必要なタスク間イベントリレーができてしまったのではないかと思います。タスク設計については、「分けることはいいことだ」では決してありません。システム全体としての最適化という観点を意識しての設計が必要です。

過ぎたるは猶及ばざるが如し

モジュール設計にせよ、タスク設計にせよ、ただ一つの正解というものはありません。どちらにも言えることは、「何をつくるか」というだけでなく、「誰がつくるか」、「拡張性のスコープはどこまでか」を考えないといけないということ、そして、それを踏まえて、過度な分割をしすぎていないか確認すること、が大切かと思っています。

何事も、「過ぎたるは猶及ばざるが如し」ですね。
4434159372
【関連記事】
【関連書籍】
スポンサーサイト

ソースコードレビューと単体テストの違い

我々の犯す一つの大きな間違いは、原因を結果の間近にあると考えることにある。
ゲーテ

ソフトウェア開発において、できるだけ上流で欠陥を検出し、不具合を下流に流出させないことは、成果物の品質確保と開発全体の工数削減のために非常に重要になります。そのための代表的な手段が、「ソースコードレビュー」と「単体テスト(ユニットテスト)」です。
この二つ、どちらも同じようなもので、どちらか一方で、もう片方を代替できると思われることもありますが、実際に大きな違いがあります。今回は、その違いについて書きたいと思います。

ソースコードレビューと単体テストの違い

ソフトウェア開発のモデルでV字モデルと言われるものがあります。要求分析から詳細設計・コーディングまでの上流工程に対して、それぞれの工程に対応するテスト工程によって、その成果物が検証されるようなモデルです。

V字モデル

単体テストは、いわゆる詳細設計に対応するテスト工程になっていますが、ソースコードレビューはどこにマッピングされるものでしょうか。コーディングの一環と見方もできますが、単体テストと同じく、実装完了したソースコードを対象とするものですので、単体テストと同じく、詳細設計に対応する検証工程と考えるのが普通かと思います。

では、単体テストとソースコードレビューはどちらか片方だけすればいいものでしょうか。以下で紹介されている内容がわかりやすかったのでご紹介したいと思います。 ここに書かれている内容の要点だけまとめると、以下のような形になるかと思います。
  • ソースコードレビューも単体テストもINPUTは同じ。どちらも関数レベルのソースコード。
  • 検出率としてはソースコードレビューの方が優秀。
  • ソースコードレビューは、レビュアーのスキルレベルに依存し、見落としもあり得る
  • ソースコードレビューが品質向上工程で、テストの方は品質保証工程
品質向上と品質保証という言い方は、わかりやすいですね。

結局、両方必要ということなのですが、これらの違いはもう少し理解して、使い分けないと効果的な検証にはなりません。この違いをもう少し考えてみます。

テストは結果、レビューはプロセスを検証する

単体テストは、入力に対し、期待する結果がでるかを確認します。単体テストの指標として命令網羅(C0)や分岐網羅(C1)といったカバレッジ指標を用いることがありますが、これはあくまでテストの網羅率を計測しているものであって、評価そのものではありません。あくまで、検証対象は、INPUTに対するOUTPUTのみです。つまり、単体テストで保証しているのは、テストした範囲での入出力が仕様を満たしているということだけであり、設計の中身については何も保証してくれません。

では、ソースコードレビューの方はどうでしょうか。こちらは、入出力の対応を見るというよりは、関数の実装内容、ソースコードの中身を確認するのが中心になります。つまり、単体テストとは逆で、中身(経過)が正しいことを確認して、そこから結果が正しくなるはずということを検証するアプローチです。言い換えると、結果ではなく中身を検証するアプローチです。もう少しいい方を変えると、設計内容を検証するというものです。

そう考えると、単体テストはホワイトボックステストに分類されるかもしれませんが、関数レベルではブラックボックステストです。結果しか見ていない以上、単体テストだけで品質を保証するには、関数内が少しでも変われば、基本的には全部をテストしないと正しいということは言えません。ですので、効率的な単体テストで重要なのは、その再現性、すなわち、テスト実施者への依存性がなく、コード修正のたびに検証を効率的に実施できる仕組みになります。

一方、ソースコードレビューの目的は、その中身、つまり設計を検証することにあります。ソースコードレビューが、単なる機能レビューみたいになっているケースがありますが、それだけではソースコードレビューを実施する目的からすると不十分です。 ソフトウェアの実装は、たとえ関数レベルであっても、その作りによって、実行効率や拡張性、可読性は大幅に変わってきます。こういった、単なる結果が正しいかというだけではない、設計観点での検証がソースコードレビューでは重要になってきます。
よって、より良いレビューのためには、レビュアーの選定が重要になります。システムやサービス、商品の仕様に精通しているというレビュアーだけではなく、ソフトウェア設計の観点で適切なレビューができるレビュアーを入れることが重要です。そうでないと、ソースコードレビューが、機能レビュー、仕様レビューになってしまいます。

静的解析で単体テストとソースコードレビューの穴を埋める

詳細設計、コーディングプロセスに対する検証方法として、単体テスト、ソースコードレビューと並んで有用な方法が、静的解析です。有名どころでは、PG-ReliefやCoverity Quality Adviser等のツールを活用した静的なソースコード検証です。大規模なソフト開発になると、網羅的なソースコードレビューは非常に困難になりますが、静的解析のような機械的なチェックはその補完として非常に強力なツールになります。なお、一口に静的解析パターンマッチ型やビルドキャプチャー型等の種類があり、それぞれ得意とするスコープが違いますので、目的とするプロジェクトにあったものを選ぶことが必要です。わかりやすい説明があったので、リンクを貼っておきます。
今回は、ソースコードレビューと単体テストの違いをテーマに少し書いてみました。ソフトウェア開発のプロセスでは、様々な手順やアウトプット等がルール化されていると思いますが、単にルールだからといって実施するのではなく、っそのメリットや目的を正しく理解することが、効率的な開発及び品質向上のためには重要かと思います。

4817192631 【関連記事】
【関連書籍】

起こりそうにないバグが起こるのはなぜか

落としたトーストがバターを塗った面を下にして着地する確率は、カーペットの値段に比例する

発生確率の非常に低いバグ。窓は狭いし、条件も複雑。
そんなものがよりにもよって、こんなタイミングで、こんなところで発覚するなんて。。。
いわゆるマーフィーの法則? どう考えても運悪すぎない?

・・・というようなこと、経験ないでしょうか。

そうそう起こるとは思えないような発生確率が低い、発生条件も非常に限定的な不具合が、よりにもよって、最悪の時、場所で見つかる。しかも、しょっちゅう。。自分自身も「なんて引きが悪いんだろう。。」って考えていたこともありますが、よく考えれば答えは簡単です。

『発生確率が低い不具合が、たくさん残っているから』

100万分の1の確率で発生するバグだって、そんなバグが100万個残っていれば、すぐにどれかにあたります。『下手な鉄砲も数撃ちゃ当たる』。いや、『ゴキブリを一匹見かけたら◯◯匹いると思え』ですかね。母数がたくさんあれば、当たりもひいてしまいます。

なので、こういったバグを引いた時は、単に「運が悪い」といって片付けるのではなく、まだ見ぬ低確率のバグがまだまだ残っている、言い換えると十分バグは収束していないという認識をもって、次にどういうアクションをとるべきか考えることが重要です。とりあえずの対症療法で済ませるのか、根本対策すべきかなど、その対応は開発ステップによってかわってくるでしょうが、品質のレベルを正しく認識、共有することは、結構、意識的or無意識的に無視orごまかされがちなので、注意したいところです。

4873114799

【関連記事】
このバグ直しますか? - 原因療法と対症療法
バグを潜伏させない工夫
デバッグと不確定性原理
デバッグ指向のススメ


【関連書籍】

せっかく作ったのだから・・ - サンクコストの罠

過ぎ去りしことは、過ぎ去りしことなれば、過ぎ去りしこととして、そのままにせん。
ホメロス - 『イリアス

サンクコスト (sunk cost) という単語を耳にされたことはあるでしょうか。日本語では「埋没費用」と訳されます。Wikipediaを見ると、「事業に投下した資金のうち、事業の撤退・縮小を行ったとしても回収できない費用」と説明されています。マーケティング用語ですが、今回は、ソフトウェア開発におけるサンク・コストとその対応について少し考えます。

サンク・コストのわかりやすい例としてよく用いられるのが映画館の話です。これまた、Wikipediaからひっぱってきましょう。

ある映画のチケットが1800円であるとする。しかし映画が余りにもつまらない時、1800円払った映画を見るべきか、それとも映画館を出て残りの時間を有効に使うかが問題となる。
  • 映画を見るのを止めた場合:チケット代1800円は失うが、上映時間を有効に使うことができる。
  • 映画を見続けた場合:チケット代1800円に加え、約2時間(上映時間)を失う。
この場合、チケット代1800円が埋没費用となる。この埋没費用は、どの選択肢を選んだとしても回収できない費用である。そこで時間を浪費してまで、つまらないと感じる映画を見続けることは合理的な選択とはいえない。残りの上映時間を有効に使うことが合理的な選択となる。

4569701299 あるソリューションの開発に巨額の投資をしてきたが、他社がそれを大きく上回るソリューションを提供してきた。今の開発を続けても勝ち目はない。それでもとりあえず開発を完成させるべきか、それとももう一歩のところとはいえ、ここできっぱりやめるべきか。こういう事業判断もそうですね。
ついつい「せっかくここまでやったのだから。。」という考えをしてしまいがちですが、どちらにせよ過去の投資は返ってこないのだから、それらはサンク・コストとして考えてはいけないはずです。冷静に考えて見ればあたり前の話ですが、人間心理としてついついサンク・コストとこれからの投資を混同してしまいがちです。今までやってきたことを「無駄」だったと認めることは、精神的にはつらいところですからね。しかし、それは仕方のないことなので、きっぱりあきらめることが肝心です。

先の例は、事業判断の話になりますが、開発の現場でも同じような話があります。で、よくある話としては、初期の設計がまずい、あるいは、担当者のスキル不足から「こりゃ作り直した方が早いな」というケースです。こういう場合、「せっかくここまで作ったんだから」あるいは「この人もせっかく慣れてきたところだし」ということで、結局そのまま作り直さないでいることがありますが、この時サンクコストに囚われていないか判断が必要です。本当にその判断が正しいであれば、「せっかくここまで」というサンク・コストは無視して、今を基準にした判断が必要です。

こう書くとと、「問題がでたらすぐにあきらめましょう」と誤解されるかもしれませんが、そうではありません。それまでに払ったコストは返ってきませんが、そこで得られた経験はあるはずですので、それは考慮すべきです。これらは今後の投資額に利いてきます。 それに、プログラマという人種は「作り直し」が好きなので、本当に作り直した方が早いのかは、よく考えた上で判断する必要がありますね。
また、方針転換でリソース再分配する際には、部分最適だけに走って、プロジェクト全体のクリティカルパスに影響を及ぼしたり、長期的に無理が生じるようなことのないようにもしないといけません。

何にしても「引き時」というのはほんと難しい。それを痛感する今日この頃でした ^^;

【関連記事】
手堅い見積もりが遅れを生む - セーフティの弊害
このバグ直しますか? - 原因療法と対症療法

【関連書籍】
サンクコスト時間術 (PHPビジネス新書 66) (PHPビジネス新書 66) 斎藤 広達
ソフトウェア開発者採用ガイドJoel Spolsky 青木 靖
図解 実戦マーケティング戦略 佐藤 義典
ソフトウェアプロダクトライン―ユビキタスネットワーク時代のソフトウェアビジネス戦略と実践 前田 卓雄

守破離

規矩作法 守り尽くして 破るとも 離るるとても もとを忘るな
千利休

人気blog「分裂勘違い君劇場」の記事「中途半端に優秀なプログラマが「正しいプログラミングテクニック」だと妄信しがちな3つポイント」という記事が注目エントリになっています。ということで、ひさびさにコメントがてら投稿したいと思います。

あげられているのは、次の三つ。

  • 「変数のスコープは狭いほど良い」と妄信する
  • 「同じロジックのコードを2度以上書くな」と妄信する
  • 「プログラミング言語を極めるのが大切」と妄信する

いかにも議論を呼びそうな内容ですね :-)。既に多くのコメントが寄せられていますが、一言で言えばケースバイケースということにつきます。何にでも例外がありますからね。この辺、言うまでもなく「適切な」判断が一番なのですが、そうはいっても、初心者にとってその判断はなかなか難しい。そこで、「スコープは狭く」とか「コピーはだめ」とかいうコーディングルールになってしまいます。
但し、あくまでこれは「基本」であるということを忘れてはいけませんね。それを忘れて妄信する人はたしかに多いです。そういう人の中では、手段と目的が入れ替わっています。「手段」を妄信するあまり、いつの間にか「目的」の方が「手段」を正当化するための「手段」になっています。まさに本末転倒です。


さて、この手の話でよく引用されるのが「守破離」とう言葉。茶道や武道で用いられる上達に至る経緯を表した言葉です。「守」は、師についてその流儀を習い、その流儀を守って一般的には、「守」の段階ではまず型に従うことに徹して技を磨き、「破」ではその型を破ることで自分の型を見出し、「離」の段階で、元の型から離れ独自の境地に達する。
本質を端的に表した言葉ですが、これを実践するのはなかなか難しい。特に、ステップ移行のタイミング。早ければ独りよがりになり、遅すぎればいつまでも進歩しない。そうならないためには、自分の得意分野をひとつは持ってそれを極めつつ、視野を広くもって周りにも目を向ける。局所最適を防ぐにはほどよいノイズがあるくらいが調度よいものです。


4571300271 【関連書籍】
プログラミング作法 Brian Kernighan Rob Pike
チェンジ・ザ・ルール! 三本木 亮
組込み現場の「C」プログラミング 標準コーディングガイドライン 福田 晃
改訂版 組込みソフトウェア開発向けコーディング作法ガイド[C言語] (SEC BOOKS)
武士道 (岩波文庫) 矢内原 忠雄

【関連記事】
過学習と局所解
このバグ直しますか? - 原因療法と対症療法
ルールを破る時のルール

【関連リンク】
ソフトウェア開発の守・破・離

かわいいコードに旅をさせよ

人は誠実な批評よりも心にもないお世辞を好む。
プラトゥス

設計レビューやソースコードレビューといったレビューは、ソフトウェアの品質確保だけでなく、開発者のスキル向上のためにも非常に有意義です。このレビューを有意義なものとするために心がけてべき最も重要なことのひとつが、
「自分の書いたソースコードや設計書に対して客観的であること」
です。簡単そうで、これがなかなか難しい。

人間、自分で作ったものは愛着が出ます。これはソースコードも同じ。エレガントなモデル設計やスマートなアルゴリズムに仕上がったものは誇らしいけど、混乱した設計や実装も、こんなはずじゃないんだ、分かっているんだとかばいたくなる。なので、人からつっこまれると、ついつい、ソースコードの味方をしてしまうことがあります。これは、ちょっと過保護で、ソースコード君のためにはなりません。

では、客観的な立場に立てているどうかはどうやったら分かるでしょうか。ひとつの方法は、「レビューの指摘に対して、ソースコードを書いた本人が嫌な気分になるかどうか」で分かります。人の書いたソースコードレビューでは、気になった点をどしどし指摘するし、人の意見にも「うんうん」とうなずくのに、いざ、自分のソースコードの時には、ついつい守りに入っている、そんな経験ないでしょうか (私はあります ^^;)。自分のソースコードであっても、人のコードと同じような気分で、レビューに望めるようになれば、かなり客観的になれていると言えるでしょう。

レビューに関しては、「責める」のではなく「褒める」とことが大事だという意見もあります。確かに、自分の書いたコードや設計が褒められるのは悪い気はしません。褒められて伸びるというのも否定しませんが、そこで喜ぶのはその成果物を客観的に見れていないということです。「褒める」という行為によって、自信をもたせることもひとつ重要な点だとは思いますが、悪い点はそこそこに、良い点ばかりを見るように仕向けるのは決していい方法とはいえません。

489100388X「プラス思考」「ポジティブ・シンキング」という言葉があります。この言葉を「いいように考える」という意味で使っている間は、決してスキルアップはありません。マイナス面に目をつむって、いい部分だけ見ていては、それ以上の改善はありません。「いいように考える」のではなく「よくするように考える」、悪い点があるのなら、そこをどうやっていい方向に持っていくかを考える、守るだけでなく攻める、そういう姿勢が重要です。批判は単に「耐える」ものではありません。素直に受け入れてそれを力に変えることが重要です。レビュアは敵ではないんですからね。

なお、レビュアの方も単に攻撃してやろうという気持ちだけではいけません。意見を受け入れられるように的確な対案をまじえながら建設的な指摘する、そういうレビュア側の姿勢も、高品質・高効率なれビューには非常に重要です。


【関連書籍】
ピアレビュー―高品質ソフトウェア開発のために Karl E.Wiegers 大久保 雅一
「ほめる」技術 鈴木 義幸
ソフトウェアインスペクション Tom Gilb Dorothy Graham 伊土 誠一
ソフトウェア・レビュー技術―基礎から実践までのノウハウ 織田 巖
ピープルウエア 第2版 - ヤル気こそプロジェクト成功の鍵 トム・デマルコ ティモシー・リスター

【関連リンク】
ルールを破る時のルール
射撃しつつ前進

このバグ直しますか? - 原因療法と対症療法

急なれば標を治し、緩なれば本を治す
実に久々の記事です (^^;)。今回はバグ修正のリスクについて書いてみます。

医療用語には「対症療法」と「原因療法」という言葉があります。表面的な症状の消失あるいは緩和を主目的とするのが「対症療法」、症状の原因となる疾患そのものを制御する治療が「原因療法」です。 完全回復や再発防止のためには原因療法が必要になりますが、事情によりそれがとれない時に対症療法がとられます。

対症療法を選択する理由はいくつかパターンがあります。そのひとつは、症状の原因が不明な場合。この場合、分かっているのは症状のみですから、対症療法以外すべがありません。原因はわかっていても有効な対策がわからない場合も同じです。風邪薬なんていうのはそうですね。
もうひとつのパターンは、原因療法に伴うコストやリスクが大きいた場合。手術をするにもお金がかかりすぎるとか、体力がもたないとかいう場合がそうです。その他、原因療法を施す前の応急処置として対症療法がとられることもあります。原因療法と対症療法は、排他的なものではなく相互に補完し合う関係にあります。

475614599X さて、この話は、ソフトウェア開発におけるバグ修正にも当てはまります。ソフトウェア開発における実装フェーズでは、バグの検出とその修正というサイクルが繰り返されます。このバグつぶし、デバッグという作業は病気の治療に似ています。そして、それは基本的には、根本原因をさぐってそれを直す原因治療として行われます。

しかし、これが製品リリース直前、あるいは、既にシステムの運用開始後、パッケージや組込みソフトウェアであれば製品発売してしまった後だったらどうでしょう。この場合は、不具合の原因がわかっていても、原因療法ではなく対症療法がとられることがあります。これは、修正のリスクを考慮してのことです。
このような運用直前あるいは運用中のケースでは、システムの品質は、一度は確認されているはずです。そして、バグの修正というのはそのシステムに変更を入れるわけですから、その部分の再確認が必要になってしまいます。しかし、大規模なシステムの検証コストは莫大です。全ての検証をやり直すなんてことはもちろんできません。よって、修正の影響範囲をしぼり、検証の範囲もしぼるということが必要になってきます。そこで、広い範囲に影響が及ぶような原因療法ではなく、見つかったバグの発生条件の場合のみに影響するような対症療法を選択するようなケースが出てくるのです。

別の医療用語に「トリアージ」という言葉があります。災害医療において、多数の傷病者を重症度と緊急性によって分別し、その対応方法を決める手順を指す用語です。このような緊急の場面では、重篤であっても救命不可能な患者は切り捨てられます。非常につらい選択ですが、できるだけ多くの命を救うためには必要な選択です。
運用直前や運用中のバグ修正も同じです。修正の時間は限られています。複数のバグがあったとしても、全てを修正して検証する時間はないかもしれません。つまり、バグの取捨選択が必要になります。先に書いたように対症療法でしのぐことによって検証時間を節約するというだけでなく、そもそも直さずにそのままにするという選択も時には必要です。検証コストを削減する一番の方法は、修正しないことですから。

分かっているバグを直さない、あるいは、原因がわかっていて根本修正もできるのに、表面的な回避しかしないというのは、プログラマにとっては非常に嫌な選択です。バグが見つかったら直したいというのが大半の意見でしょう。しかし、ソフトウェアの修正には、常にリスクが伴うということを忘れてはいけません。例え修正が正規のものであっても、隠れたバグをエンバグさせる可能性だってあります。マイナス×マイナスでプラスになっていたものが、マイナスになるかもしれないのです。修正したい気持ちは非常に非常に良く分かりますし、つらいのですが、ここはぐっと我慢が必要です。エレガントさよりも品質確保が重要なのです。

4873112990 ソフトウェア開発の現場では、「動いているコードはさわるな」ということがよく言われます。これは上のような話が背景にあります。しかし、これも絶対ではありません。時と場合によります。運用直前や運用中は、上のような対症療法が有効な場合が多いですが、開発に余裕がある場合は、原因療法でしっかり直しておくべき場合がほとんどです。
所詮、対症療法は一時凌ぎにすぎません。安易な解熱剤や鎮痛剤の服用と同じで、中途半端な回避コードは、不具合を潜伏させ、自体をより悪化させることすらあります。ですので、対症療法をとった箇所はきちんと管理し、適切なフォローをすることを忘れてはいけません。

不具合のない品質の高い成果物を作ることがプログラマ・エンジニアの役目です。この時、理想論に走るのではなく、限られたリソースの中でいかにそれを最大化するかを意識することが、プロのエンジニアとしては必要です。

# もちろん理想を追うのもわすれちゃいけません ^^)

【関連記事】
バグを潜伏させない工夫
デバッグと不確定性原理
デバッグ指向のススメ

【関連書籍】
ソフトウェアアーキテクチャ―ソフトウェア開発のためのパターン体系 F. ブッシュマン他
ソフトウェア開発の持つべき文化 IT Architects' Archive ソフトウェア開発の課題1
開発の現場 vol.007 - 運用・保守
ソフトウェアパターン再考―ソフトウェア品質学 各論 パターン発祥から今後の展望まで
達人プログラマー―システム開発の職人から名匠への道 Andrew Hunt
リファクタリング―プログラムの体質改善テクニック

開発プロセス改善 - ところで問題は何なのか?

解法を問題の定義と取り違えるな。ことにその解法が自分の解法であるときには注意
ライト、ついてますか―問題発見の人間学』 D.C.ゴース G.M.ワインバーグ
ちょっとばたばたしてたのでひさびさの更新になります。そのばたばたの原因のひとつでもあるのですが、今年度に入ってソフトウェアプロセス改善(Software Process ImprovementSPI)の仕事が増えました。しかし、多くのソフト屋さんの例に漏れず、私もこの手の仕事はあまり気乗りしません。というよりも、「そんなことより実装させてくれ!!」というのが強いといった方がいいかもしれません。とまぁ、愚痴ってみたものの、開発プロセス改善は決して「そんなこと」ではなく、今日の組込みソフトウェア開発において非常に重要なテーマです。今回は、プロセス改善について考える機会ができたことで、改めて感じたことを少し書いてみようかと思います。

私と同様、組込み業界に身を置いておられる方も、「組込みもこれからはCMMくらい取れないと!」ということで、手順・ルールが増えたり、厳しくなったりという経験をお持ちの方も多いでしょう。しかし、CMMといえど、所詮はルールや仕組みであって、それは目的ではなくは手段です。体系的な仕組みは短期的には面倒なことでも、長期的には効果を発揮することも多いのは事実です。しかし、その裏にある目的を意識せず仕組みを作ることだけに一生懸命になっていては本末転倒です。

プロセス改善については、どうもトップダウンの「押し付け感」が伴いがちです。そのため、現場から見れば「望んでもないことを押し付けられる」、上から見れば「現場は意識が足りない」という調子になってしまうことが多いです。これはなぜでしょう。一つには、課題認識があっていないということが挙げられます。「プロセス改善なんて工数の無駄だ」「プロセスがないなんて問題だ!」というやりとりでは、絶対に収束しません。まずは、「なぜプロセス改善が必要か」ということをお互い認識をあわせる必要があります。つまり、「誰にとって」「何が」「なぜ」問題かという点をまず明らかにし、その次に初めて解決策を検討するというステップが必要がなのです。

現場の人間が「プロセス改善は工数の無駄だ」といった時に、つい「長期的な視野に立ってないからだ」ということがよく言われます。大抵の場合、それも一理あるとは思いますが、決してそれだけではありません。それよりも、「もっと他にすべきことがある」というのがあるからでしょう。プロセス改善の目的は、開発効率の改善や品質の向上にあります。そして現場の人の多くは、その目的のための近道がドキュメント管理や、手順の定義がネックであるとは思っていないのです。では、何が必要かと思っているか。大抵の人は「工数」と答えるのではないでしょうか。

では、工数とは何か?時間が足りないのか?人が足りないのか?実際はどちらも正しくないでしょう。実際は「スキル」が足りないのです。人月という単位はいうまでもなく形式的なもので、実際は全ての人が同じスキルをもっているわけではありません。そして、工数が足りないといった時に、多くの場合開発者のスキルが足りないということが多いと思います。

プロセス改善といった時に、まだまだこの「スキル問題」が議論の中心になることはあまりないような気がします。ノウハウの蓄積といったテーマがあがることがありますが、まだ少し違う気がしいます。もっとより、自由意志でのスキルアップのようなもの、これをうまく組織としてまわるようにしていくにはどうすべきか、これを考える必要があるように思います。それは自己啓発だからどうしようもない、そう言って片付けてしまうのは単なる思考放棄です。梅田信夫氏の著書「ウェブ進化論」でも紹介されていますが、Googleは20%の時間を自分のオリジナルなテーマに当てなくてはいけないという「20%-80%」ルールがあるそうです。ポイントは「当てなくてはいけない」という点です。さすがGoogleといってしまわず、このような仕組みも積極的に検討していく必要があるのではないでしょうか。これも、実開発の工数に影響を与えるかもしれませんが、「ドキュメント管理」よりははるかに技術者の「モチベーション」に効果的に働くでしょう。

さてさて、こうは書いたものの、やっぱり基本は会社にたよるのではなく自分自身の動機付けが一番。かくいう私も最近業務に追われ気味なので、ちょっと深呼吸して新しい言語でも勉強してみようかなと思う今日この頃です。
なんだかまとまりのない話になって、結局何が主題だったか分からなくなってしまいました (^^;)。
プロセス改善の話の続きはまた改めて。。

【関連書籍】
ライト、ついてますか―問題発見の人間学 ドナルド・C・ゴース G.M.ワインバーグ
デスマーチ 第2版 ソフトウエア開発プロジェクトはなぜ混乱するのか E・ヨードン
ウェブ進化論 本当の大変化はこれから始まる 梅田 望夫
ソフトウェア開発のためのプロジェクトマネジメント入門―CMM導入の手引き パンカジュ ジャロート
ソフトウェアプロセス改善と組織学習―CMMを毒にするか?薬にするか?
ザ・サーチ グーグルが世界を変えた ジョン・バッテル

手堅い見積もりが遅れを生む - セーフティの弊害

「予定より早く作業を終わらせても、最初のステップはそれを報告しないからです。現状の仕組みでは、作業を早く終わらせても何もご褒美はもらえないんです。いやそれどころか、ペナルティーが課されます。」
エリヤフ・ゴールドラット 『クリティカルチェーン

4478420459「なぜ、プロジェクトは予定通りに進まないのか?」。「予定通り進まないのがプロジェクトだ」と言う人もおられるでしょう(^^;)。最近読んだ「クリティカルチェーン - なぜ、プロジェクトは予定通りに進まないのか?」という書籍は、そんな「プロジェクトマネジメント」における常識に挑戦する書籍です。この手の本では、久々に共感するところの多かった影響を受けた書籍なので、紹介したいと思います。

この本、著者はTOC(制約条件の理論)の提唱者で、そのTOCを小説仕立てで解説した「ザ・ゴール ― 企業の究極の目的とは何か」がベストセラーになったエリヤフ・ゴールドラット氏です。「ザ・ゴール」は邦訳もベストセラーになったのでご存知の方も多いと思います。その後、「ザ・ゴール2 思考プロセス」「チェンジ・ザ・ルール」と続編が続いており、本書は「ザ・ゴール4」のような位置付けです。今回は、ザ・ゴールからの主題であるTOCをプロジェクトマネジメントに適用させたものです。

プロジェクトマネジメントといってまず出てくるのはPMBOK。もともとアメリカの非営利団体PMIがまとめたプロジェクト管理に関する知識体系ですが、いまや事実上の世界標準です。最近では研修に取り入れている企業も多いのではないでしょうか。プロジェクトマネジメントを系統的に捉える体系として、有用だと思います。PIMBOKに対し、本書で提案されている手法「クリティカルチェーン」の面白いところは、TOCの適用という点もさることながら、人間心理の特性を重視している点です。

セーフティ - 手堅い見積もり

中でも私が思わずなるほどと思ったのはプロジェクトの工数見積もりにおける「セーフティ(safety)」に関する考察です。ここでいうセーフティとは、あるステップを完了するのに必要な予想工数のマージン・余裕量のようなものとして定義されます。
工数見積もりの際に「これくらいでもできるかもしれないけど、念のためこれくらいにしておくか」という時の、
(念のためこれくらい) - (これくらいでできるかもしれない)
という量です。実際、開発ステップでは外的要因や想定外の障害があるため、ある程度のこのようなマージンを見積もりに入れることが多いです。

過剰なセーフティ

本書では、セーフティは大抵は8割くらいの確率で終わるくらいの量で見積もりをあげるだろうとされます。しかも、この8割の確率で終わるという工数は、5割の確率で終わる工数に比較して、2倍以上になるといいます。にわかには受け入れがたい数字ですが、場合によっては当てはまる気もします。
実際、プログラミングフェーズでは、何の障害もなくすんなり終わってしまった作業も、その見積もり時には、実際にかかった工数の2倍以上で工数を見積もっていたということはあるでしょう。これは特に、工数の小さいステップで顕著です。例えば、うまくいけば2時間程で終わる工数を1日といってしまうこともあるでしょう。このような丸めを入れてしまうのもよくある話です。
そう考えると、ステップを細かく割りすぎると、工数に余分なセーフティを与えてしまう可能性があると考えられます。正確な見積もりをしようとする行為が不確定性を高める。不確定性原理のようなものです。

セーフティの浪費

ここで疑問が出ます。では、なぜプロジェクは遅れるのか?セーフティがあるのならむしろ早く終わるのでは?と。

理由は簡単です。浮いた時間が有効に使われないためです。なぜか?これは、年末の道路工事のようなものです。予算を使い切らないと次年度の予算が削られるかもしれない、だから、予算を使い切るために必要のない公共事業を行うというやつです。開発業務の場合、あまり早く仕上げてしまうと、次回からさらに無理なスケジュールを要求されるかもしれない、だから報告しない。さらに言えば、残業代が少なくなれば収入も減るかもしれない。このような心理的な作用によって、セーフティは無駄に浪費されるというのです。

こう書くと保身のためにさぼっているように思えますが、実際そのようなつもりのない人でも、浮いた時間でコードのリファクタリングをしたり、念入りなテストをしたり、ドキュメントを整備したり。やることはいくらでもあるので、決してさぼっていなくても、浮いたセーフティは消費されることは確かに多いでしょう。

マイルストーンをなくす!

では、どうすればいいのでしょうか。本書では、まず細かいマイルストーンをなくすところからはじめます。そして個々のステップは最小の見積もりでスケジュールを立てる。細かいマイルストーンはなく、大きな単位でのおしりや、複数の作業が合流するところだけにポイントを置く。この時、個々のステップはぎりぎりの見積もりで引かれたものなので遅れる可能性は従来より高い。そこで、このポイントに大き目のバッファを置く。とまぁ、こんな感じです。
個々の「予定」を守ることは単なる局所最適に過ぎません。そこに目を奪われて全体としての「予定」が遅れないようにしようというのが主旨なのです。


とりあえずセーフティについて簡単に触れましたが、この他にも興味深い考察がなされています。興味を持たれた方は是非一読をお勧めします。私は、本書で得た考え方を自分の仕事に取り入れていきたいと思っています。

最初からベストのスケジュールをひけば、遅れることがあるのは仕方有りません。しかし、それを許容する風土がなければこのような管理は難しいでしょう。勿論、そのためにバッファを設けたりするのですが、この「予定より遅れる」ということについて、周りに納得してもらうのは少々頑張らないといけないかもしれませんね (^^;)

447837449X 【関連書籍】
クリティカルチェーン―なぜ、プロジェクトは予定どおりに進まないのか? E・ゴールドラット 三本木亮
最速で開発し最短で納めるプロジェクト・マネジメント―TOCの管理手法“クリティカル・チェーン” 村上悟 井川伸治
PMプロジェクト・マネジメントクリティカル・チェーン 中嶋秀隆 津曲公二
プロジェクトマネジメント標準 PMBOK入門 広兼修
ザ・ゴール ― 企業の究極の目的とは何か エリヤフ・ゴールドラット 三本木亮
デスマーチ 第2版 ソフトウエア開発プロジェクトはなぜ混乱するのか E・ヨードン

ルールを破る時のルール

人間の自由を奪ったものは、暴君でも悪法でもなく、社会の習慣である。
以前、はてなの伊藤さんのブログ(naoyaのはてなダイアリー)でエアコンの設定温度を例に「ルールが一人歩きする」という記事がありました。この中で、満員の図書館でエアコンの設定温度を下げてくれというお願いに対し、設定温度は決められているでと言って下げてくれなかった、という話がとりあげられています。「手段」であるはずのルールが「目的」になってしまった典型的な例です。まさに「ルールの一人歩き」です。

さて、これはルールに盲従してしまっている例、言い方を変えると間違った「ルールの守り方」をしている例です。しかし、逆にルールの間違った「ルールの破り方」もあります。最近ちょうどそのような経験をしたのでちょっと書いてみます。

ソフトウェア開発でいうルールと言えば、コーディング規約等もプログラミング上のものから、リーリス方法等を規定したプロジェクト管理上のものまで様々あります。
プログラミング言語の文法もルールのようなものですが、これは簡単には破ることができません。それに対し、コーディング規約やリリースルールのようなものは開発者が無視しようと思えばいつでも無視できるようなものです。そうなると大抵の人はなまけがちですが、中には、ルールだからといって必要以上の努力を払ってまでそのルールを遵守しようとする人もいます。このようなルールへの盲従は、その人が疲れるばかりでなくかえって迷惑なことさえあります。無駄な説明が多くて要点がわからない、コメントが多すぎてかえって読みにくい、ちょっとした変更なのに修正後のテストといってリリースがでない。。。等など。先のエアコンの設定温度と同じく、ルールの本来の目的が失われ、ルールを守ることが目標になってしまっています。

さて、このようなルールへの盲従は問題ですが、だからといって自由気ままにルールを破ったり無視したりしてはいけません。先の例のように、ルールに従うことは無駄な作業を発生させることがあります。しかし、それが本当に無駄かどうかは目的をよく考えた上で判断しなければなりません。タブ幅がなぜ決まっているのか、なぜドキュメントが必要なのか、なぜリリース前のテスト項目がこれだけあるのか。自分のポリシーと照らし合わせておかしいとかいうのは理由になりません。自分ひとりの開発では単なる足かせでも、複数人の開発では意味があるかもしれません。大抵のルールは局所最適ではなく全体最適のためにあります。勝手にルールを無視すると、他の人への影響があるかもしれません。

ルールの盲従も、ルールの無視も、本来ルールが何のためにあるのかを理解していないから起こります。必要なのはまずルールの目的を理解することです。また、ルールは目的ではなく手段なのですから変えることだってできるのです。ルールがおかしいと気付けば勝手に無視するのではなく、積極的に変えるよう働きかけるべきです。

赤信号だって一旦とまって左右確認して安全だと分かれば渡っても良いでしょう。しかし、信号「無視」はいけません。ルールを破るにもルールがあるのです。

【関連リンク】
ルールが一人歩きする - naoyaのはてなダイアリー

【関連書籍】
ライト、ついてますか―問題発見の人間学 ドナルド・C・ゴース G.M.ワインバーグ
仕事の哲学 P・F・ドラッカー
チェンジ・ザ・ルール! エリヤフ・ゴールドラット
まず、ルールを破れ―すぐれたマネジャーはここが違う マーカス・バッキンガム カート・コフマン
C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス

間違いを計算に入れる

調べ物をしようと思って検索エンジンにキーワードを入力して検索。「思ったより情報が少ないなぁ」なんて思ったら、実はスペルが間違っていた。

このような経験はないでしょうか。例えばメールソフトのThunderbird。「Thanderbird」や「sanderbird」「Thunderbard」では所望の検索結果は得られません。
一般的な英単語の微妙なスペル間違いであれば、Googleのスペル候補表示等で気付くこともありますが、キーワードが固有名詞だったり日本語だったりするとそうもいきません。
そもそもよく知らないものを調べようとしているわけですから、単語自体もうろ覚えということは少なくありません。
時には、情報側の方が間違っていることもあります。先程のThunderbirdの例では、「Thunderbard」や「Thanderbird」でも数百件のページがヒットしますが、これらは情報側が間違っているということを示しています。

以前「間違えやすい日本語」という記事を書きましたが、時には間違った表現の方が多く使われていることだってあります。例えば、「押しも押されぬ」と「押しも押されもせぬ」では、本来正しいはずである「押しも押されもせぬ」の方がヒット数が少なくなっています。

このような人間のしでかす間違いを逆手にとったサービスがあります。そのひとつが、百式さんで紹介されていたFat Fingersというサイト。オークションサイトeBayから検索するサービスなのですが、間違いがちなスペルを合わせて検索してくれるため、間違ったスペルで出品されているものも見逃さず検索してくれます。Googleのスペル候補
SEO等のマーケティング戦略として、このような「うろ覚え」をどう扱うかというのは面白そうなテーマです。

人間は間違えます。以前の記事(デバッグ指向のススメ)で書いたデバッグ指向プログラミングも、この考えに基づいた考え方です。

「間違いをなくす」ことはできませんが「間違いを計算に入れる」ということはできます。

【関連記事】
間違えやすい日本語
デバッグ指向のススメ

【関連リンク】
百式 - 間違いを計算にいれる
「うろ覚え」ユーザーを獲得しよう (japan.internet.com)

【関連書籍】
とっておきの秘技 Google検索の秘伝書 持丸 浩二郎 蒲生 睦男
ググる―検索エンジンGoogleを使ってネット上の情報を検索すること 津田 大介

デバッグと不確定性原理

客観的事実など存在しない。
あるのは自分の目を通して見た事実だけである
ハイゼンベルク

プログラムの動作がおかしい。そこで、デバッグのためにログ出力のコードを仕込んで動作させてみる。すると、さっきまで調子の悪かったプログラムが正常に動いている。プログラムをもとに戻すとやっぱり動作がおかしい。

このような経験はないでしょうか。いわゆる、デバッグにおける「不確定性原理」の一例です。

不確定性原理とは何か

ハイゼンベルクの不確定性原理(uncertainty principle)とは量子力学における基本原理ですが、これはデバッグに当てはまります。オリジナルの不確定性原理の概要をWikipediaの説明から引用しておきます。
極微の世界では粒子の運動量と位置を同時に決定することはできないという原理。位置をより正確に観測する為にはより正確に「見る」必要があるが、極微の世界でより正確に見る為には、波長の短い光が必要であり、波長の短い光はエネルギーが大きいので観測対象へ与える影響が大きくなる為、観測対象の運動量へ影響を与えてしまうからである。位置を正確に測ろうとするほど、対象の運動量が正確に測れなくなり、運動量を正確に測ろうとすれば逆に位置があいまいになってしまい、両者を完全に正確に測る事は絶対に出来ない。
冒頭のデバッグの例は、まさにこのような不確定性原理がデバッグに適用されたような形になっています。つまり、ログ出力というプログラミングに対する観測行為が、プログラムの動作に影響を与えてしまったために、もともとの状態が変化してしまっていたのです。バグが再現しなくなったのは、観測行為がプログラムの動作を変えてしまっていたのです。

では、なぜログ出力がプログラムの動作を変えてしまったのでしょうか?ログ出力を追加しただけで、アルゴリズムを変えたわけではありません。このような場合で最も多いのは、もともとのバグがタイミングに依存したものであった場合です。マルチスレッドや割り込み処理を行うようなプログラムの場合、ログ出力の追加による僅かなタイミングのずれが、バグを起こらなくしてしまうということは良くある話です。特に、ログの出力先がファイルやシリアル等の場合は、そのタイミングで実行タスクがI/O待ちでスリープしてしまうことがあるためよく起こります。
その他、コードの追加はメモリマップを変更してしまうため、メモリ破壊や変数の初期化漏れ等のバグの挙動を変えてしまうこともあります。

なお、ログ出力等のコード追加をしなくとも、デバッグのためにコンパイルの最適化レベルを変更したり、デバッガをつないだりするだけでもプログラムの挙動に影響を与えてしまうことがありますし、デバッガでブレークをかけたりする行為もプログラムの挙動に影響を与えてしまいます。

不確定性原理とうまく付き合う

では、この不確定性原理の影響を排除するには、どのようにすれば良いのでしょうか。残念ながら、これは「原理」であるので、完全に回避することは不可能です。しかし、何も悲観的になる必要はありません。見方を変えれば、これはデバッグのための観測についての指針を示してくれているものと考えられます。

オリジナルの不確定性原理の説明を再び引用すると、
位置を正確に測ろうとするほど、対象の運動量が正確に測れなくなり、運動量を正確に測ろうとすれば逆に位置があいまいになってしまい、両者を完全に正確に測る事は絶対に出来ない。
とあります。
デバッグに置き換えれば、正確な内部情報を知ろうとすればするほど、もとの動作に影響を与えてしまうということになるでしょうか。
ここで、見方を変えれば、
  • 動作に影響を与えないようにデバッグするためには、
    極力観測による影響が少なくなるようにすれば良い
と考えられます。

具体的な例をあげると、
  • ロギングを使用する場合、目的のログだけを出力する等、対象を絞れる仕組みを入れる
  • ログ出力のI/O負荷が問題になりそうな場合は、ログを絞ってメモリ上に残す
  • ブレークによる一時停止が影響しそうな場合は、条件ブレークを活用して最小限にブレークがかかるようにする。
    もしくは、ロギングを活用したデバッグを行う
等が考えられます。

不確定性原理によるリスク

冒頭の例でもそうですが、デバッグ用のコードの追加がバグを隠してしまうことがあります。このため、開発の終盤にはじめてデバッグ用のコードを抜いたり、最適化レベルを変更したりすると、とたんにプログラムが動かなくなる可能性があります。このような事を防ぐために、普段からデバッグコードを抜いたり、最適化レベルを変えても正常に動くかどうかをチェックしながら開発を進めることが必要です。

4873115930 【関連リンク】
不確定性原理 (Wikipedia)

【関連書籍】
デバッグルール 9つの原則、54のヒント
不確定性原理―運命への挑戦 (都筑 卓司)

人気エントリ
最近の記事
本のおすすめ

4274065979

4844337858

482228493X

4904807057

4873114799


最近のコメント
Links
プロフィール
  • Author:proger
  • 組み込み関係で仕事してます
ブログ内検索
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。