ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

デスマーチになるのは、プログラムが書けないからでなく、”おじさんの運動会”だからだ

2007-05-11 18:27:37 | Weblog

さいきん、これ
どうしてプログラマに・・・プログラムが書けないのか?
http://www.aoky.net/articles/jeff_atwood/why_cant_programmers_program.htm

がはやっているようだ。

この文を読んで。。
あー、この書いた人がプロジェクトマネージャーになったら、開発はデスマーチ、プログラマは地獄だろうなと思った。

どうしてか。。を書く前に、まず、ここで話題になっている話を1つ
(以下斜体は上記サイトより引用)

ここでは、「Fizz-Buzz問題」というのを取り上げている。
それは、


1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。


というものです。

で、それについて、

 ちゃんとしたプログラマであれば、これを実行するプログラムを2分とかからずに紙に書き出せるはずだ。怖い事実を聞きたい? コンピュータサイエンス学科卒業生の過半数にはそれができないのだ。自称上級プログラマが答えを書くのに10-15分もかかっているのを見たこともある。


うん、この人は、プログラマでよかった。。
この人がSEかマネージャーになったら、このプロジェクトはデスマーチになるだろう。
もし、上級プログラマが10分かかっていて、
コンピュータサイエンス学科卒業生の過半数ができないのに、
自分が2分でできると思っていたら、
それは、世間が間違ってるんじゃなくって、自分の考えが間違っている。




そう考えないと、”おじさんの運動会”になってしまう。

おじさんが、子供の運動会に参加することがある。
そうすると、おじさんはなぜかこける・・・
なぜ、こけるのか。。
自分は走れるとおもっているけど、体はそう動かない。
なので、こけるのだ。

それと同じ。自分は2分でできると思って、計画を立てておいて、
2分でできない人が続出した場合、プロジェクトはこけてしまう。
でも、2分でできると思い続けている限り、
なぜ10分かかるのかの理由がわからないから、
永遠と転び続ける。。。

デスマーチの多くの原因は、この、勘違いによることがおおい。
プログラム能力の差異は、実は教育方法があるから、埋められるのだ。。
(その教育方法を、大学やプログラマが知らないということがあるのだが。。)




さて、このケースでは、なぜ、2分でできると考え、自称上級プログラマが10分かかるのか、考えて見ましょう。

まず、2分でできると考えた人は、こういうプログラムを書くと思う。

public class testpro2 {

	public static void main(String[] args) {
		for(int i = 1 ; i <=100 ; i ++ )
		{
			if ( (i % 3 == 0 ) && ( i % 5 == 0 ) )
			{
				System.out.println("FizzBuzz");
			}
			else if ( i % 5 == 0 )
			{
				System.out.println("Buzz");
			}
			else if ( i % 3 == 0 )
			{
				System.out.println("Fizz");
			}
			else
			{
				System.out.println(i);
			}
		}
	}
}

(上記< > ¥は、本当は半角です)




ここで、悩んだり、できなくなったりする理由は、この書き方が、仕様書とはちがっていることだ。

仕様書は、あくまでも

1.3の倍数かどうか調べよ!
2.5の倍数かどうか調べよ!
3.3と5の倍数だったら。。

ときている(たぶん、意図的にこの順番にしている)。

ここで、testpro2のif文を、この仕様書の順番で、

if ( i % 3 == 0 )

からはじめてしまうと、3と5の倍数のときも、これにひっかかって
Fizzと印刷してしまう。

かといって、elseifをつかわないで、ifでかいて
if ( i % 3 == 0 )
{
	System.out.print("Fizz");
}

if ( i % 5 == 0 )
{
	System.out.print("Buzz");
}



と書くと、今度は15の倍数のときの条件を、
仕様書には書かれているのに、プログラム上は書かない上に、
なにも出力しない場合、数字を書き出すためのフラグを持たないといけない。




もちろん、仕様書を無視し、同じ結果が出ればいいと考えるかもしれないが、
これをやり始めると、デスマーチになるのだ。。
修正で想定外のことが起こる危険がある。

たとえば、3と4の倍数の場合。。というのを仕様書に追加したとしたら、
それは(上記testpro2中でしめした)3と5の倍数の上に書くのか、
下に書くのか、このとき、どちらにかくかで、60で違いが出てくるのだが、
そーいう複合条件における、仕様のもれが、まさにデスマーチにつながってくる。

だからこそ、仕様書と、プログラムの条件判断は、あわせたいのだ。




で、この問題は、こうやって考えると(このケースでは)解決する。
(たぶん、この方法で解決するように条件が並べてあるように見える)

王道は、崩すべきではないのだ。
条件判断は、まず、
1.判断する値を全部集める=>今回はない

ここで、状態によって処理を換える場合は
2.わたしはだーれ?と聞き、状態を決定する
3.状態=>処理に変換が必要なら変換する
4.処理をディスパッチする

という方法をとる。さっき書いた決定表のketteiCntl.javaにおいても
そのようになっていて、「条件判定」が2にあたり、「実行」が4にあたる。
この間に、3に相当する「実行条件の選択」というのが入っている。

今回の処理の場合、3が必要ない(起動する処理は1つ、「印刷する」なので)

したがって、それを考えると、こういうプログラムになる。
/**
 * 
 * Fizz-Buzz問題
 * 
 */
public class testpro1 {

	/*
	 * 実行部分
	 */
	public static void main(String[] args) {
		
		//	メイン処理(100までループ)
		for(int i = 1 ; i <= 100 ; i++)
{ int sts = 0; //==========================// // 条件判断部分 // //==========================// // 3の倍数 if ( i % 3 == 0 ) { sts = 3; } // 5の倍数 if ( i % 5 == 0 ) { sts = 5; } // 3と5の倍数 if ( ( i % 3 == 0 ) && (i % 5 == 0 ) ) { sts = 15; } //==========================// // 処理部分 // //==========================// switch(sts) { case 3: System.out.println("Fizz"); break; case 5: System.out.println("Buzz"); break; case 15: System.out.println("FizzBuzz"); break; default: System.out.println(i); break; } } } }

(上記< > ¥は、本当は半角です)

 こうすれば、条件変更があっても、「条件判断部分」が仕様書と一致しているので、仕様変更があったときでも、「仕様書と同じ順番でやってます。」といいきれる。
 同じ順番でやっている以上、仕様書どおりの順番で書いて、おかしくなっても、(さっきの例だと、3と4の倍数を、3の倍数の前に入れようが、3と5の倍数の後に入れようが、仕様書と同じ順番でコーディングできる。その結果、おかしくなったとしても)「いやー、あんたが書いたとおりやっておかしくなったんだから、そりゃーあんたが悪い」とは、口が裂けてもいえないけど、仕様の書き手に対して、どうしておかしくなったかは伝わる。

 そうすれば、仕様書の書き手とプログラムが一致するので、書き手があらかじめ順番を考えることができる。さらに、仕様書とプログラムが一致すると、自動生成の可能性も出てくる。ワーカーにも説明がつく。

 ワーカーに説明できる=プログラムが書ける必要性はないのだ。
 こちらの説明どおりに書いてくれれば、いいわけだし、自動生成にもちこめば、まさにかける必要はない。

 実際にプログラムを書くのはウィリアムのいたずら、後の人は、Excelシートをがんばって保守っていう作業もある。これで、1000個のソースとかを自動生成して管理する(保守要員1名で)という話もある。たぶん、保守してる人は、プログラムかけないと思う。でもシステムは回っているのだ。これでOK!




ところが、プログラマ側で勝手に仕様書と書き方を変えてしまうと、ちとこまる。
仕様書の書き手は疑心暗鬼になってくるし、実際、論理が破綻してしまうこともある。

保守も???ってなってくる

プログラマの技量によるところ大になり、自動生成もできない
(だから、1000個のプログラムを1人で直す。。。は無理なので、何人かに分けてとなり、人も増える)。。。

あちゃー、デスマーチなのですよ。。。

でも、こーいう事態が結構あるんだけどね。。




ちなみに、じゃあ、条件がすべて、上記のような体系でかけるかというとそうではない。

 まず、条件には、単純なIF文と、状態判定をするような複雑なケースがあり、複雑なケースにおいては、オプション型の、どんどんやることを追加していくものと、状態型のある1つの状態のとき、やることはこれ!という方法がある(今回は状態型を採用した)。
 そして状態型は、決定表に持ち込む方法と命題に持ち込む方法などがある(今回は命題に持ち込む方法を採用した)、詳しい話は、「開発の初めから順番に書いていってみる」で、決定表の話が終わった次に、条件判定の体系化というようなかんじの話で行う予定ですけど(そこで、どうして今回の条件の並べ方が、意図的に感じられたかは書きます)。。。

 今回は、そのなかの1つをつかって、ばちんとうまく言ったって言う話。

 だけど、これ、多分話をよんでしまえば、

 なーんだ!

 でおわってしまう話なんで。。あんまり、重要なことではない。
 (大学とかで、教えてあげればいいのに。。昔は、会社で教わったのね)




 で、実際、eclipseを立ち上げてから、testpro1をコーディングしてテストし、コメントを入れるまでで、だいたい10分かかった。

 つまり、上級の人は、
1.はじめに2分でおもいついている
2.でも、「いやまてよ、仕様変更があったら?」と考え直し
3.こっちの方法のほうが、きれいだよね!と考えを変えて
4.それをコメント入りできれいにコーディングしている

だから、10分かかってるってことだとおもう。

15分の理由、つまりあと5分でなにをしているかというと、いろんな言語をやっている人の場合、倍数のあまり0は、%なのか、mod関数なのかが気に係り、ネットでチェックしてるんだと思う。上級者になるほど、そーいうところは確認するような気がする。
(英語、できるやつほど辞書で確認をとるっていうやつ)

なので、この5分は別に。。指摘するほどのことでもない。

むしろ、重要なのは、思いついたプログラムをすぐに書くんじゃなくって、
一回、考えをためてから、書いていることだ。
 この「考えをためて、冷静になって考える」ことをしないと、ぐちゃぐちゃな場当たり的なプログラムになってくる。
 この差のほうが、むしろ重要だと思う。




あ、このほかにも、さっきの「どうしてプログラマに・・・プログラムが書けないのか?」「連結リストを実装」あー、そーねそーね、CのポインタにおけるJavaでの実装の問題、デザインパターンのおはなしとか、あのへんねえ。。。とか「実際的な問題を解くのに再帰が使える」あーそーねそーねー、再帰の実装の問題ねえ。。

と話したいことがみつかっちゃったんだけど、いい加減長くなりすぎたので、今回はここまで(シリーズ化しちゃう?)
この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« プログラムやテストデータを... | トップ | 「地球温暖化防止のためにPDF... »
最新の画像もっと見る

Weblog」カテゴリの最新記事