とりあえず Java コーディング規約を読んで思ったことを幾つか書いてみるよ!

経緯

> id:SiroKuro
> ぶっちゃけ自分の腕試しを兼ねて、こういう間違い探しやってみたいんだけど、何か良い題材は無いかな。だれか紹介してよ。
おぉ、ちょうどいいんじゃないでしょうか?ISID 版。

http://d.hatena.ne.jp/bleis-tift/20090804/1249389793#c1249471653

ということで読んでみました。読んでみた感想は……意外と好感触?だったりします。

とりあえず本編

名前をつける時はすべて英語を基本としてください。

JavaCodingStandard2004_P.9

クラス名には、機能 ID、連番等の意味のわかりにくい名前を使用しないでください。

JavaCodingStandard2004_P.11

賛成。ローマ字で付けられた名前は見難くてしかたがない。うちはNの規約を使ってるけど、ここが最大の不満点。

パッケージ名は、多少長くなってもできるだけ省略せず、わかりやすい名前を使用するようにしてください。

JavaCodingStandard2004_P.10

注意。java のパッケージ名は略称が用いられることが多い。
Abstract Window Toolkit ⇒ java.awt
Drag And Dropjava.dnd
Input Method ⇒ java.im
Remote Method Invocation ⇒ java.rmi
機能の略称が用意されているならば、それがよりパッケージ名にふさわしい。逆に言えば、略称が用意されるような特徴的な機能ごとにパッケージを分けるべきだとも言える。

インターフェースの命名規則は基本的にクラス名に準じます。
例外:クラス名との区別が必要であれば、先頭に”I”をつけてください。

JavaCodingStandard2004_P.11

懐疑的。C# に慣れているぶん妙な違和感を覚える。

抽象クラス名の命名規則は基本的にクラス名に準じます。
例外:適当な名前がないときは、”Abstract”から始め、その後にサブクラス名を連想させる名前を付けてく
ださい。

JavaCodingStandard2004_P.12

賛成。というより、このあたりは java 標準 API の通りかな。

すべてのテストやパッケージテストを行うクラス名は、「AllTest」もしくは「パッケージ名 + Test」としてく
ださい。

JavaCodingStandard2004_P.13

懐疑的。個人的には AllTest"s" かな。

コンストラクタと同じ名前のメソッドをつくってはいけません。

JavaCodingStandard2004_P.13

注意。そもそもコンパイル通らなくね?

役割、機能等が対になっているメソッドの名前は英単語の対称性を意識したものにしてください。

JavaCodingStandard2004_P.16

賛成。といっても難しいものではある。Host, Master, Server の対義語を正確に言える人って意外と少ない気がする。

メソッドのパラメータには、クラスのメンバ名と競合する名前を付けないでください。同じ名前になってしまう
場合は、”_”を始めにつけて区別する、this を使用する、等の対策をとってください。

JavaCodingStandard2004_P.16

注意。this を付ける場合は、付けたとしても変数名としては競合してしまうのでは。それはともかく個人的には this 派。変に prefix 付けるのは好きじゃない。

オブジェクトを参照する際は、そのオブジェクトの実装クラスを用いて宣言できます。しかし、実装クラスに適切なインターフェースが存在している場合は、必ずインターフェースを用いて宣言してください。

JavaCodingStandard2004_P.19

注意。実装クラスそのものが欲しい場合は必ず出てくる。ランダムアクセスが頻発するリストに対しては List ではなく ArrayList で宣言するなど、例外があることに注意すべき。

引数がプリミティブ型である場合には値そのものが渡されますが、参照型の場合にはインスタンスへの参照が値として渡されます。

JavaCodingStandard2004_P.23

お、偉い。

タブではなく、すべて空白文字を使うようにしてください。いちいち空白文字を入れるのが面倒な場合はエディタの置換機能を使って最後に一括変換するのも手です。

JavaCodingStandard2004_P.25

特に取り決めがない限り、インデントの空白は4文字分にしてください。

JavaCodingStandard2004_P.25

懐疑的。インデントのずれが気になるのならば、エディタの機能を使って揃えれば済むことでは?
インデントに空白を用いようとするから、空白4文字という規約が別に必要になってしまう。それならば「タブ幅は4で」の規約を1つ設ければ必要十分である。

長いコードを改行せずにだらだら続けていませんか?1コード行は原則として80 文字程度までにしてください。モニタ上で見づらいだけでなく、メール送信や印刷の際に見にくくなったり、フォーマットがくずれてしまったりします。

JavaCodingStandard2004_P.26

反対。問題が顕在化するのはエディタ幅の固定された環境に限っている。またメール送信や印刷に際しては、1行がジャスト 80 文字になっていることのほうが少ないはず。そのような前提の下、80 文字に決め打つことのほうが逆に見づらくする原因となってしまう。
この「1行 80 文字幻想」の大本は、COBOL の規約だと推測している。COBOL は「パンチカード」という、エディタ幅の固定された環境だったため、この規約が生まれたのだと考えている。
ちなみに私はメールでは 64 文字を基準にしていた。80 文字付近で折り返されたコードが 64 文字でさらに折り返されるのは、実に滑稽だった。

boolean 変数は比較するまでもなく、それ自体が条件の結果を表していますので、これをtrue と比較する記述は冗長となり可読性が低下します。

JavaCodingStandard2004_P.30

懐疑的。true と比較することが冗長であるという認識は賛成だが、false と比較することまで冗長であると思われてしまう可能性があるのが嫌。もちろん false と比較するならば ! を用いるべきという考えは納得するのだが、いかんせん ! は幅が小さく可読性が悪い。

不等号の向きがばらばらになっていませんか?不等号の向きを統一することで、コードが読みやすくなります。特に意図することがある場合を除いて、向きは左向きに統一してください。

JavaCodingStandard2004_P.30

賛成。個人的な意見だけど、不等号は < と <= 以外、特に使うべきでもないし、使う意味もあまりないと考えている。

継承されないクラスはfinal を宣言してください。下記のメリットがあります。

  • クラスの継承及びメソッドのオーバーライドのないことがコンパイラに通知されるため、コードの最適化がより適切に行われます。
  • final を宣言することでそのクラスは継承されないことが明示され、可読性が向上します。
JavaCodingStandard2004_P.33

オーバーライドされないことがわかっている場合にはfinal 宣言をしてください。これにより、誰もメソッドをオーバーライドしていないことがコンパイラに通知されるため、コンパイラは最適化されたコードを生成することができパフォーマンスが向上します。

JavaCodingStandard2004_P.35

反対。「final を付ければコンパイラVM がよろしくやってくれるだろう」という不確かな情報と希望的観測を元に、行われるかどうかわからない最適化を狙うべきではない。また、final を付けたことでシステム全体の見通しは付け易くなるのかもしれないが、それを可読性の向上とは私は言わない。
継承されたくないクラスやメソッドである場合、かつそのときに限り、final を宣言すべきである。

デフォルトコンストラクタを明示的に用意することで、下記のことが可能になります。

例外:引数ありのコンストラクタでインスタンスを生成することを前提としているクラスの場合、デフォルトコンストラクタを作成する必要はありません。

JavaCodingStandard2004_P.34

懐疑的。というかインスタンスの生成は常に動的に行われるけどそれはまあ良いや。なにやら仰々しく書いてあるけど、要は「初期値が決まるクラスには引数 0 個のコンストラクタが用意されていると便利だよね」ってだけで、別に Class.newInstance がそこまで便利かといわれるとあまりそうでもない。bean は確かに便利だけど。

メソッドのオーバーロードにおいて、引数の数が同じになっていると、ソースコードを追いかけて引数の型を確かめなければ、どのメソッドが実行されているのかわかりにくいことがあります。

JavaCodingStandard2004_P.39

懐疑的。どのメソッドが実行されているかわかりにくくなるのは、引数の数が異なっていても起こりうる話。そもそも、引数の型によって処理内容が大きく変わるメソッドは同じ名前でオーバーロードするべきではないと思う。

何も処理をしない空のメソッドはありませんか?実装のないメソッドは空にせず、必要であればabstract として宣言してください。そうすることによってサブクラスでの実装漏れを防ぐことができます。

JavaCodingStandard2004_P.48

注意。「実装をサブクラスで定義するメソッド」は abstract で良いんだけど、「実装をサブクラスでカスタマイズし、デフォルトでは何も実行しない」というメソッドにしたい場合には空のメソッドとすべき。java.awt.event の Adapter 系のような感覚だな。

System.arraycopy()は配列をコピーするためのメソッドです。自分でコピー処理を書くのは無駄な上に、間違いを含んだり実行速度が劣ることがあるので、System.arraycopy()を使うようにしてください。

JavaCodingStandard2004_P.58

注意。そろそろ java.util.Arrays を使うようにしたいな。

ループの中にtry/catch ブロックはできるだけ置かないでください。パフォーマンスの低下につながり、ループ内の処理も大変見にくくなります。

JavaCodingStandard2004_P.60

反対。そもそもパフォーマンスが低下する vm ってどこにあるんだろう。

コレクションにある特定の型のオブジェクトだけを格納する場合、特定の型のオブジェクトのみを扱うコレクションクラスを新しく定義する方法があります。例えば、String しか格納できないようなコレクションを自分で定義するのです。

JavaCodingStandard2004_P.76

注意。かなり古いから、そろそろ使えなくなってきているはず。もうジェネリクスで十分だよね。

最良のパターン

この規約は、たぶん意外と良い立場で書かれているのではと思った。コーディング規約は守られるべき法律じゃなくて、良いコードのためのパターン集であるべき。デザインパターンのように、コーディングパターンと言うべきか。

最悪のパターン

一番最初に言及した「名前は全て英語」が無くなると、この規約はゴミクズと化すと自分では思っている。
「名前をローマ字」+「名前は省略せずわかりやすく」+「定数名は全て大文字」のコンボによって、定数名だけで40〜50文字もの長さになり、さらに「1行は80桁」制限によって、全てのコードはゴミクズとなる。何とかしてくれ。