きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

仕様を網羅することの難しさ

何年前に下書きして放置したのか覚えてないけど、せっかくなのでUPしとく。
書こうと思ったことが思い出せないけど、
「空白文字とは」うんぬんの事は伝えておきたいことだから。



自分が書いた部分のコードを、ある特定のクラスの特定メソッド内に閉じたらば、
そのコードを網羅することは比較的簡単なことです。


大事なことは、コードを網羅することではなく、仕様を網羅することです。
その意味で、バイトコードからテストコードを自動生成することは誤っている。
つまりカバレッジ100%であったとしても、それはコード網羅なだけで、仕様網羅ではない。


例えば、「文字列の前後の空白文字を取り除く」という仕様書があったとしましょう。
そして、java.lang.Stringのtrim()メソッドがあるとします。
「空白文字」とは何かをここで考える必要がありますが、そこに注意は払わないことが多いです。
半角スペースだけでなく、全角スペースも含まれるのか?
そう考えて仕様書を見直すでしょう。
「文字列の前後の半角スペースを取り除く」になったとします。
さて、ようやくtrim()の登場です。
trim()は\u0000〜\u0020を削除します。
このような仕様の大半は実際のコードと乖離しているはずです。


また、「スペース」とは何だという話もあります。
常識的な範囲だから書かないのかも知れませんが、スペースは色々あります。
吾輩の手元にあるUnicode Standard version 4.0によると、少なくともこんだけある。
\u0020 SPACE
\u00A0 NO-BREAK SPACE
\u2000 EN QUAD
\u2001 EM QUAD
\u2002 EN SPACE
\u2003 EM SPACE
\u2004 THREE-PER-EM SPACE
\u2005 FOUR-PER-EM SPACE
\u2006 SIX-PER-EM SPACE
\u2007 FIGURE SPACE
\u2008 PUNCTUATION SPACE
\u2009 THIN SPACE
\u200A HAIR SPACE
\u200B ZERO WIDTH SPACE
\u2060 WORD JOINER
\u3000 IDEOGRAPHIC SPACE (いわゆる全角スペース)
\uFEFF ZERO WIDTH NO-BREAK SPACE


常識的とさきほど言った部分は、ASCIIという意味です。
それに限定されると、上記のスペースのうち\u0020のみとなるのでしょう。
ただし、それでもtrim()メソッドは、その\u0020以外を削除しているので結局ダメなんです。


加えて言うならば、Character.isWhiteSpace(int)の仕様も見ると良いでしょう。
9
a
b
c
d
1c
1d
1e
1f
20
1680
180e
2000
2001
2002
2003
2004
2005
2006
2008
2009
200a
200b
2028
2029
205f
3000