2013年4月11日木曜日

コーディング規約 その3 (code conventions 3)

コーディング規約の 3回目は、ソフトウェアメトリクスに関するものである。

我々は、2005年にはメトリクスの計測ツールを導入したが、その後、使用するツールの都合により一時的に自動的な計測を停止している。
それでも、以下に掲げる規約は有効である。

なお、これらの基準を逸脱しなければならない場合は、実験的なプロジェクトの場合を除いて社内レビューを行い、その妥当性の検証が必要となる。

関数の大きさ

1個の関数(メソッド)の大きさは、7行までが理想で、多くともこれに +2した 9行が良い。

ただし、言語によっては使用できる構文が違うため、多少差をつけることにしたい。
  • Java -- 12行
  • c++ -- 24行
  • c -- 30行
  • ほか -- T.B.D.
1980年代半ば、私が学生アルバイトをしていた会社の社長と、関数(アセンブリ言語だったのでサブルーチンと読んでいたが)を小さくすると各々は単純になるが、数が増えたり、レベルが深くなって判りにくくなることを議論した記憶がある。そのときには良い答えを見つけることはできなかった。

2000年代に入っても、プロジェクトのメンバにリファクタリングして関数を単純にしてもらえないか相談したときに、彼らから同じような答えが返ってきた。 彼もまた、解決法を見つけていないようだ。

大事なのは関数が大きくなればなるほど「関数を分けなければならないのではないか?」という疑問を持つことである。

上記の基準はちょっと厳しいと思われるかもしれないが、頭の中でトレースするのにはあまり長くないほうが良い。

ほかの考え方としては、できれば 1個の関数を読むために、左右はもちろん、上下にもスクロールしたくない。

引数の数

気軽に使ってよいのは 3個まで。
Immutableなオブジェクトをコンストラクタで全部初期化したい場合でも 7個まで。

ローカル変数の数

3個までに収めるのが理想。言語別上限はつぎの通り。
  • Java -- 5個
  • C++ -- 7個
  • C -- 7個

制御構文の深さ

if, switch-case, for, while, do, try-catchおよび、 ? : 演算子を合わせて 3レベル。

厳しいと思われるかもしれないが、これを守るとコードが読みやすくなる。

使われ方としては、
  • tryを使う場合には、中に一重のループとその中に if文が 1レベル。
  • 二次元データを扱うにはループを二重に使いたい場合があるので、そうするとあと if文が 1レベル。
  • switch-caseの中に if文があって、その中で ? : 。
なお、3レベル以内だったとしても switch-caseの中で switch-caseを使用するのは非推奨。(我々の規約では 8タブを使用するので良いが、 4タブだとどの caseがどの switchに対応するか追跡するのが面倒になり、間違いの元になる。

クラスの大きさ

メンバの変数や関数の数に制約は無いが、空行、コメントを合わせて理想は 500行まで。最大 1000行まで。

大事なことは、凝集度。

分けてはいけないものを分けると無駄な相互作用が発生し、そのためのアクセサが増えるだけでなく、そのアクセサが外部に公開されてしまうことが適切かどうかという問題が生ずる。

逆に一緒である必要のないものを1つにしてしまうと、ある部分の変更が外の部分に影響が及ばないか検証する範囲が広がり、無駄なコストが発生することである。

目覚めよ!正恩。

0 件のコメント:

コメントを投稿