プログラミング文章読本~何よりメリハリ
2008.04.26
「あすなろBlog昇格記念」の新シリーズです。その名も「プログラミング文章読本」と題しましょう。
昔の名文を謳われた小説家がよく「文章読本」というタイトルで、「文章をどう書くか?」というエッセイを書いています。で....プログラムっていうのも、やっぱり「文章」なんですよね! ですから、「(あくまで)文章」という視点で、プログラムを考察するという企画モノです。プログラムは「動く」のと同時に、ソースの内容を「読む人へ伝達する」という重要な機能を持っています。ですから、「プログラムとしての機能性」以外にも、「読みやすさ」というのはとても重要な「性質」なんですよね。
ですから、「読みやすく、理解しやすいプログラムのためのTips」みたいな感じかな。私は結構その点で「過激!」かもしれませんけど、実際コレかなり重要なことだと思います。
じゃあ、本題。今日のテーマは「メリハリ」です。
小説だと、重要な場面の微に入り細に入り、精密な描写をするものですが、重要でない場面だと「『省筆』をうまく使って、読者の想像力を活用する」という重要なテクニックがあります。逆に悪い文章は、「何が言いたいのか、パッと見でよく判らない...」ということにもなります。
プログラムも同じですね。けど、プログラムの方が分が悪いです....確かに長いメソッドは「何か重要そうだ」と思わせますし、短いメソッドは「あまり重要ではなさそうだ」と思わせます。また、コメントの多い・少ないも「一見して判る重要性」を区別する手がかりになります。しかし、「ここ重要!」「ここはコンベンショナルに定義されているだけ(のたとえば JavaBeans のゲッタ・セッタ)」というあたりの区別に無関心なケースが極めて多いです.....
ゲッタ・セッタしかない部分を、フルコメントでずらずらと記述してあって、それがエディタ上で5ページ以上もあると、結構うんざりしますよね。要するにこれ、「メリハリ」という観点で改善できないか?とは思いませんか?
私がよく使う記述ルールはですね、こういうモノです。
重要ではない部分の記述は、出来るだけ改行をサボる
というものです。例えば、ゲッタ・セッタが並ぶのならば、
public String getString() { return string; }
public void setString(Srting s) { string = s; }
public int getIntVar() { return intVar; }
public void setIntVar(int s) { intVar = s; }
.......
という感じにしてしまいます。普通はこういうの、改行を入れますし、引数も何となくそれっぽい名前を使うのですが、これは
定義されていれば、特に実装に関心がないです
というのを積極的に示すために、あえてこういう書き方で書いてしまいます。ここで、たとえば、引数のポリモルフィズムを使う同名メソッドがあったとしましょう。
public String getString() { return string; }
public void setString(Srting s) { string = s; }
/** setString() は int も受ける */
public void setString(int val) {
string = String.valueOf(val);
}
public int getIntVar() { return intVar; }
public void setIntVar(int s) { intVar = s; }
.......
ね、setString(int) だけ、他のメソッド定義と書き方が違います。ですから、これは目立ちますし、わざわざこれを定義した甲斐もある、というものです。また、javadoc にした時も、「コメントが入ってる」という違いがあるので目立つわけです。
同じようなことで、私が使う「わざと改行しない」書法というと、「メソッド内で事前条件を示すのに、改行しない」という書き方(ガード、さすがに仕事だと表明は使いづらい....)があります。
/**
* @param x 負でない
* @param y 負でない
*/
public int sub( int x, int y ) {
if( x < 0 ) return -1;
if( y < 0 ) return -1;
....実際の処理
if( z < 0 ) {
return 0;
....実際の処理
return z;
}
これ、たとえば x, y が負の数だと処理自体に意味がないメソッドだとしましょう(Math.log() みたいなイメージかな)。このメソッドを呼んで、
もしx,yに負の数を与えて、何か問題が起きたとすれば、その責任は sub() というメソッドの側にあるというよりも、読んだ側の問題である
と言えるようなコンテキストがある場合(javadoc コメントでこの事前条件を公開もしています)、実際の処理の中で起きる「処理の終了によるリターン」と区別して、メソッドの先頭で「改行{}のないぶらさがりifで書く」ことで、これを明示します。
結構今でも、「return が一箇所にしかない=構造化プログラミング」と信じちゃってるプログラマがいるみたいですが、たとえば、
public void sub( int x, int y ) {
int ret = -1;
if( x >= 0 ) {
if( y >= 0 ) {
....実際の処理
if( z >= 0 ) {
ret = z;
} else {
ret = 0;
}
}
}
return ret;
}
なんていう、途中return を回避するために if のインデントがやたらと深くなったコード(これCOBOL?)なんかよりも、ずっと「意味深く」ありませんか?まあ、今ならば return を色分けして目立たせるエディタを使っていない....わけはないでしょうから、「途中の return を見失う」なんて可能性はほとんどないわけです。特にこういう if の連鎖でインデントが深くなったプログラム、というのは、「メリハリが全然なくて、ダラダラと書かれたプログラム」の典型じゃないか、とも思います....
さて、今回過激でしたね。これ結構私のオリジナルの工夫が多いのですけども、「読みやすさを向上させる」という点で気に入ってます。どうでしょう?
投稿者 : 杉浦 こずえ | 投稿日時 : 2008.04.26 09:23
あすなろBLOGのトラックバック・コメントは承認制になっています。
すぐにブログに反映されませんので、ご了承ください。






名前:minorutg2008年04月27日 13:09
いつも勉強になります。
IT 系エンジニア 6 年生です。
今回は特にスゴくスゴく勉強になりました。
素晴らしいコーディング・ルールだと思います!!