Hatena::ブログ(Diary)

Fly me to the Juno! このページをアンテナに追加 RSSフィード

2009-03-21

ソースコードにWhy(なぜ)を残していますか?

つい最近Java界隈でSimpleDateFormatがスレッドセーフではない、という事が話題になりました。JavaDocにも「synchronizedではない」と書かれている事だけれども、日付の変換は良く使う上にフォーマットを繰り返し書くのは面倒なので、ユーティリティクラスとしてまとめておく事が良くあるっしょ。

こんな感じで。

package util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public abstract class DateConverter {
	
	public static String convertYYYYMMDD(Date date){
		DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
		return formatter.format(date);
	}
	
}

で、何もしらない人がこのコードを見たとき、毎回SimpleDateFormatを作成するのは無駄じゃん!*1と思ってこんな感じにしたとしましょう。

public abstract class DateConverter {

	private static DateFormat YYYYMMDDFormat = new SimpleDateFormat("yyyy/MM/dd");
	
	public static String convertYYYYMMDD(Date date){
		return YYYYMMDDFormat.format(date);
	}
	
}

冒頭にも書きましたが、SimpleDateFormatで行う処理はsynchronizedされません。複数のスレッドから同時にこのクラスにアクセスされた場合、違う結果が返された、という障害が起りうるわけです。しかも再現が非常にムズい、修正者泣かせの障害でしょう。はい、わかりましたわかりました、元に戻します…。となったところで、戻した理由を書いていなかったら同じ過ちが繰り替えされる可能性は消えませんよね。少なくとも繰り替えさないようにコメントを残しておきましょう、と言うのがこの日記の趣旨です。こんな感じ

public abstract class DateConverter {
	
	public static String convertYYYYMMDD(Date date){
		// bugs:xxxx SimpleDateFormatはスレッドセーフではないため、毎回インスタンスを作成するようにしています。
		DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
		return formatter.format(date);
	}
	
}

他にも、ユーティリティクラスについての議論で、今後も新しい人が入ってくる度にもめそうな事があれば、それについてコードに残しておく方がよさそうです。こんな感じ。

public class DateConverter {
	
	public static String convertYYYYMMDD(Date date){
		// bugs:xxxx SimpleDateFormatはスレッドセーフではないため、毎回インスタンスを作成するようにしています。
		DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
		return formatter.format(date);
	}
	
	/*
	 * こんな感じでコンストラクタの非公開の理由も書くといいかもしれませんね。
	 * 
	 * このクラスはユーティリティクラスのため、コンストラクタを非公開にしています。
	 * クラス修飾子にabstractを用いる事を検討しましたが、
	 * チームで議論した結果、abstractが示す意図とここでの用法は違うという意見が出たため、
	 * コンストラクタを非公開にすることになりました。
	 * 
	 * @see 2009/03/21の議論 http://kompiro.org/....
	 */
	private DateConverter(){}

}

JavaDocにWhyを記述することも考えられますが、JavaDocに記述すべきなのはそのクラスの利用者が注意しなければならない用途に関してかと思ってます。例えばDateConverter#convertYYYYMMDD(Date)の引数がnullだった場合、NullPointerExceptionが投げられます。*2nullを渡さないよう、利用者が気をつける、というルールであれば、JavaDocに素の旨を書いておくべきです。*3JavaDocに残すべきなのは実装を意識した振る舞いではないはずです。

そういえばかくたにさんも以前「ソースコードにコメント以外Whyを残す手段がない」と言っていた気がするその後どうなったんだろう。

*1:プロファイルした結果問題になるくらい問題になってた、とします。そんなことほとんどないですけど。

*2:それはDateConverterクラス実装者の責務っぽいけど

*3:でもJavaDocに書いておいても読まずに実装する人が多いので、コードの中に残せない理由をコメントに残そう、というのが今回の趣旨ですから

2009-03-12

銀の弾丸のかけらは皆の頭の中にある

InfoQの記事はどれも秀逸ぞろいですが、特にこの記事はいいと思ったのでご紹介。OOPSLA2007のパネルディスカッション、「"No Silver Bullet" Reloaded["銀の弾丸なんてない"の再装弾]」のまとめです。タイトルから言ってかっこいいよね。Dave Thomas氏がEclipse IDEの開発で暗躍してたとか知らなかったよ。

http://www.infoq.com/jp/articles/No-Silver-Bullet-Summary

ちょっとだけ引用してみます。前述のDave Thomas氏は「フレームワークは未完成で専門的に磨かれていない製品を出荷する最善の方法」とか言っていたり、今日のほとんどの企業アプリケーションは基本CRUDだけだよね。それじゃ第四世代のメインフレームでいいじゃんね。とか。

狼(Martin Fowler氏)が登場して、「なぜ俺たちは生きていけるのか」とか話してみたり。オブジェクト指向のアイディアは非常に狼にとって邪悪で危険だが、誰も実行していないので恐るるに足らず。とか。

感想というか、読んで思ったのは、銀の弾丸は完全な形のものなんか存在しなくて、みんなの頭の中にあるものを組み合わせて狼に立ち向かっていくものじゃないかなということ。「銀の弾丸」というソフトウェアとかのツールも含め、形のあるものを「使えば」解決するなんて事はなく、知恵を出し合って、実践を続けることで、狼を追い払うしかないんじゃないの?と思ったわけです。

いいことばかり書かれているので、是非読んでみてください。

2009-02-26

テストコードを書く意味

那須のKentBeckこと咳さん曰く

テストでは品質は上がらないですよ。テストはあくまでも品質をあげるきっかけ。品質をあげるのはプログラミングです。これは大昔からそう。

http://kakutani.com/20090213.html#p03

と言う言葉がありました。確かにそうだよな、と思ったのはいいですが、はてと思うこともありました。

じゃ、僕らはなんでテストコードを書くのだろう、

と。

以下、咳語録を自分なりに解釈して深く考えてみた軌跡です。

僕らはなぜテストコードを書くのか。それはCIにテストを組み込むことでデグレーションを起きたときに早期に気づくため、という答えもあるでしょう。が、僕が風呂に入ってぼーっとしていたら別の考えに気づきました。テストコードを書こうとすることにより、テスト対象のクラスの外側から渡ってくる値、入力と、返さないといけない値、出力を意識することで、テスト対象のクラスの質を上げるきっかけを増やしているのではないか?と思ったわけです。ソフトウェアで構築されたほとんどのシステムでは、フレームワークを用いていることが多い。いかんせん、フレームワークを使うとフレームワークから渡される値や返さないといけない値について無頓着になることが多々ある。JavaDoc等APIドキュメントにどうすべきか書かれている場合はまだ対応できますが、何もなかったらどうしますか?たいていの場合「気にしない」、と言う答えに辿り着くでしょう。でもそれって、フレームワークをブラックボックスとして中を見ない、という事なので、実はとっても不安なことだったりしませんか?自分の書いたコードが、フレームワークが想定している形かどうかどうやって検証するのでしょう?

フレームワークって想定されていない使われ方をすると、途端に意図したように動かなかったり、拡張できなかったりとひどい目に会うことが多くないですか?そういうことから逃れるために、テストコードを書こうとする姿勢が正しいコードを導く助けになってくれてるんじゃないのかなと思ったわけです。

2009-02-06

ソフトウェア開発の不思議

なぜよくあるソフトウェア開発ではきっちり要求を聞いて、かっちり仕様を決めて、その通りにカチカチに固めた開発をしようとするんだろう。

例えばなんですけど、僕がプラモデルをくみ上げるとき、最初から一つ一つきっちり部品を組むと必ず失敗していました。自分が不器用なことももちろんあるのだけれども、間違った部品をはめてしまって外すのに苦労した、なんて思い出ないですか?なのでそのうち最初は緩めに組んでおき、全体的に固まってきたらちゃんと組むという手順が効果的だと気づき、そうするようになりました。世の中ではこれを仮組みって呼ぶらしいです。

いや仮組みくらい、だれだってやってると思うんですよ。最初からうまく作ろうとしたってうまくいかないわけですから。

この「最初からうまく作ろうとしたってうまくいかない」という教訓はソフトウェア開発にも当てはまるって、いろんなプロセスで繰り返し語られているわけですけど、どうも一つ一つカッチカチにしようというフォースが流れている現場って世の中にたくさんあるのってなんでなんすかね。「契約」という約束を履行しなければならない、というフォースのせいでしょうか。だとしても、その契約の中に遊びがないのはなんでなんだろ。案件が取れなくなってしまうからだろうか。遊びがない分プロジェクトが失敗するリスクが高まります、なんてコンペとかで話でないんだろうか。

ユーザーも最初から作りたいものが完璧にかっちりわかってるんだったら、自分達でプログラマ雇う方が安上がりだからそうすると思うんだ。けど、完璧にかっちりわかってないからSIに発注すると思うんだよ。「システムの改善点を提案してください。」なんて言葉は、システムをより良くしたいから、と言うよりは、ほんとのところこのシステムっていいものかどうかわかんないから、なんだろね。

「最初からきっちり作りたい症候群」という病名でもつけてみようか。

2008-10-02

TeamKNOxの兄貴との飲み会

詳細が決まったのでお知らせしまつ。

場所:Foodium Bar 一瑳 品川店
日時:10/10(金) 19:00〜

料理を頼む時間がもったいないので、3,150円のコースにしました。ご参加くださる皆様よろしくおねがいします。