Design by Contract(7)

ひとまず完成したと思ったら、
Contract4Jなんてのを見つけた。

見てみると・・・
これ、ほとんど同じ(笑)
まぁもちろんのこと、Contract4Jのほうが完成度高いけどね。

あったんだね。
ただ、SeasarとかSpringとかとの連携はできるんだろうか・・・

まぁそれは良いとして、
最近、プログラムしてて結構うまい評価メソッドができたので紹介。

まず、XMLのパース処理。これはMaskatのEventXmlParserクラスの一部だ。
リファクタリング前はこんなだった↓

if ("event".equals(node.getNodeName()) &&
  null == node.getAttributes().getNamedItem("type") ||
  "remote".equals(node.getAttributes().getNamedItem("type").getTextContent());
おお これはわかりにくい。
リファクタリング後はこんなになった。↓
if (isEventNode(child) && isRemoteEvent(child)) {
・・・
private boolean isEventNode(Node node) {
  return "event".equals(node.getNodeName());
}
private boolean isRemoteEvent(Node node) {
  return null == node.getAttributes().getNamedItem("type") ||
     "remote".equals(node.getAttributes().getNamedItem("type").getTextContent());
}

かなりわかりやすいよね。これはJUnitにも同じような記述がある。
テストメソッドがpublicでかつ頭がtestか確認していることろがそうだ。

次。これは仕事で。
2つのPointがある程度近い場合に処理をしないようにしたかった。

まずこんなのを書こうとした。
if (!(Math.abs(pt1.x - pt2.x) <= 4 && Math.abs(pt1.y - pt2.y) <= 4)) {
}
これはわかりにくい。 コメント必須だ。
だが、↓これで完璧。超わかりやすい。
private boolean near(Point pt1, Point pt2) {
  return Math.abs(pt1.x - pt2.x) <= 4 && Math.abs(pt1.y - pt2.y) <= 4;
}

if文やfor文の条件式などは、時として長くなる場合がある。
そんなときにメソッドの抽出を行うと、非常に見やすくなる場合がある。
非常に簡単で、非常に効果的なリファクタリングであろう。