2009年08月07日

宗教戦争なんざどうでも良い

カッコをつけたコードはカッコわるいのか論争

ワロタ

俺も同じ理由でカッコをつける。更に言えば、
if (buffer == null) {return;}
よりも、
if (buffer == null)
{
  return;
}
とすることを好む。1行単文とでもいうか。ちなみに更に言うと
if (buffer != null)
{
  // 本文
}
とすることを好む。好むというか俺が作る場合90%こうする。関数の途中やif文の中からreturnで返るのは好きじゃない。可能な限り関数の最後まで行かせるように書く。 上で『1行単文』と言ったが、当然例外があって、例えはつくあそ新人・外国人選手リストを作ったときのソースの一部にある。
switch( theReadData_1 )
{
  case 6635:  fputs( "ギャラード,"   , theCsv );  break;
  case 6926:  fputs( "ラドウィック,"  , theCsv );  break;
  case 6927:  fputs( "シュールストロム,", theCsv );  break;
  case 6928:  fputs( "ヘイニー,"    , theCsv );  break;
  default:
    fwrite( theReadData, 2, 6, theCsv );
    fputc( ',', theCsv );
    break;
}
(いうまでもないが、当然一部抜粋だ。)
縦に同じ内容の構文が長く続くとき、このように1行に複文を書くことがある。


俺は、俺の書き方のルール(それは宗教と言っても過言ではないほど狂信的に)に従ってプログラムを書いている。そして、俺は前の会社で「時間はかかるがバグが少ない」という評価を受けていた。バグが少ないのは、俺があらゆるケースを事前に想定してプログラムを組むからであって、俺の書き方のルールとは直接関係がない。しかし、自分のソースに一定のルールを設けておけば、少なくともバグ発見時に、著者のような
if (buffer == null) pos++; return;
などというミスで時間を潰す心配は減る訳だ。このようなコーディングスタイルの積み重ねは、「バグが少ない」という俺への評価にまったく貢献していない訳ではない。

俺の書き方の方式は、2003年ごろにはもう確立されていて、あれから変わったのは「必要に応じてgotoを使うようになったこと」「つくあそ新人・外国人選手リストのようなときの、fputs関数の1つ目の『,』の位置を揃えること」「##で連結する目的以外でdefineマクロを使わないようになったこと」などまぁ数えられる程度だ。

以前はコーディングスタイルの統一を図るべく色々文書を書いたりしていたが、とあるベテランプログラマと出会い、それをやめた。彼は、プログラマとしては俺よりも非常に優れた人物であった。新しい技術はすぐに触って実験して理解してしまうという、彼がSFC時代から生き残ってきた理由が垣間見える凄い人だ。ところが彼のソースは、尋常じゃなく汚い。関数はおろか、ファイルすら分けない。コメントもほぼゼロ。100KBを越えるソースファイルなんてお手の物だ。しばらく一緒に仕事をして分かったことは、彼の頭の中にすべて入っている、ということだった。いやらしい言い方をすると、彼の担当箇所はすべて彼に押しつけてしまえば、難しい仕様でも仕様変更でもバグ修正でも文句言わずやってくれる。もちろん、彼が倒れてしまえばとんでもない事態になりかねないが、そこは流石のベテランプログラマ、彼のソースは汚いが、決してスパゲティではない。上から追っていけば何をしようとしているか、何を目的としてそのようなコードにしたかは、手に取るように分かる。

俺はこの方を見て、コーディングスタイルを統一することをやめた。外注に頼っているようなプロジェクトでは、その外注のコードや性格等が分からない以上、コーディングスタイルの統一はやむを得ないだろうが、社員+頼れる外注でやるのであれば、個々人のコーディングスタイルなど好きにすれば良いと思っている。俺は自分のスタイルを布教することはやめたし、他の人にも特に布教はしない。もちろん、議論する中で「それ頂き!」と思うことはあるが、それもまた個々の自由だ。


さて、最後に関係ない話を1つ。Cの分かるプログラマ諸氏に尋ねたい。

ある出向先の会社のソースで、***_main.cというファイルがあり、その文末で、
// 取得・設定関数
#include "***_etc.c"
// キー操作
#include "***_key.c"
// メッセージ関連
#include "***_message.c"
// サウンド関連
#include "***_sound.c"
// セーブ・ロード関連
#include "***_save_load.c"
として締めくくっているものがあった。当然、俺は疑問に思う。「cファイルをincludeするのって、(コンパイルはもちろん通るけど)やっちゃいけないことじゃなかったっけ」と。ところが、肝心の「なぜcファイルをincludeしちゃダメ」なのかが思い出せなかった。検索しても「それはダメだ」という意見は出てくるが「なぜダメなのか」が出てこない。出向先から本社へ帰ってきて、何人かのプログラマに訊いて回ったが、皆「俺はやらない」けど「なぜダメなんだっけ?」という状態だった。結局、1人の若い職人系プログラマが、「『畳の上では正座する』みたいなマナーの問題なんじゃないですかね」みたいなことを言い、面白かったのでそれをオチとして採用したのだが、当然、腑に落ちない(笑

どなたか、お分かりになる方はいらっしゃるだろうか。いらっしゃれば是非、ご教示願いたい。
posted by 小川 at 17:10| Comment(7) | TrackBack(0) | プログラム/マ | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
おいらのようなPHPerは基本PEAR標準ルールで書いてます。

if (buffer == null){
  return;
}

制御構造はこんな感じ。

んで、おいらもワンライナーって自己満足だと思うし、Perler特有の省略の美学はどうも。人が見てわかりやすいコードを書くことが最優先だと思ってます。

コーディングルールの統一というのは結局のところ個人の自由な発想を阻害して、業務の円滑な遂行を阻害するものになるんだと2002年ころに考えてからは、そんなことよりも別のことに労力を費やしたいと思うようになりました。

ただ、クラスやメソッド名称の衝突には気をつけなければいけないので、ネーミングルールに気を使うことが多いです。

あと、くだらないParseError防止のために、({"'を入力するときには必ず閉じるほうも同時に記述してます。

cのincludeについてはおいらもそういうものだと教わったのでよくわからないです。
Posted by miracleさん at 2009年08月07日 22:12
PEAR標準ルールっつーとコレですね。
http://pear.php.net/manual/ja/standards.php
C/C++系の方でも、コレに従っている(ように見える)方は多数見受けられます。「自分と同じ(=PEAR標準)方式」が多数いると、大人数の開発でも入りやすそうな気はしますね。まぁ、考え方がスパゲティな方のソースに出会えば同じかもしれませんが(笑

> くだらないParseError防止のために、({"'を入力するときには必ず閉じるほうも同時に記述してます。
あー、これはありますね。私は({だけですね。"'は、秀丸側で「次の"'までは文字列カラー」となるようにしてあるので、閉じ忘れはイヤでも気づきます。まぁ、({のほうも(私はC/C++なので)コンパイルしたり「対応するカッコへ移動」すりゃ気づくんですが、くだらん時間を割いてしまうので先に閉じますね(笑

あとはまぁ・・・秀丸に依存してる部分が多数ですwww
Posted by 小川@管理人 at 2009年08月09日 04:02
コーディングスタイルは「プログラミング作法」に載ってたと思うぞ。
まぁそれはいいとして。。。

#includeはヘッダでもソースでもどちらでもOKです。
以下は引用
--------------ココカラ
#include [インクルード](=組み込み)〔前処理指令/組込指令〕
構文 include行:=#incoude 前処理字句群
【参考】
include行::
#include |<h文字の列>|
|"q文字の列"|
解説 ヘッダやソースファイルを翻訳単位に組み込む。その動作はヘッダ名の形式によって異なる
1.<h文字の列>…(略)
2."q文字の列"…(略)
3.前処理字句群…(略)
--------------ココマデ
新ANSI C言語辞典 平林雅英著 技術評論社より

あれ? これ持ってなかったけ?
Posted by アレックス at 2009年08月10日 02:48
「プログラミング作法」持ってます。いや、アレックスさんから頂いたんだったかな? 「関数マクロを控える」「条件式に否定文を使わない」は実践してます。後者は使わざるを得ないときもありますが、最近は秀丸側で
if( *** != *** )
とか
if( !*** )
っていう文があると「!=」「==」「<=」「>=」の背景を紫、「!」の背景を赤ににするので間違いに気づきやすいです。(他の人が他の人の環境で見てどうだかは知りませんww)

「新ANSI C言語辞典」は持ってないですね。一時は良く本屋を探しましたが、今は、昔の教科書とK&RとGoogleでいいやー、ってカンジで探してもいないです(笑

> #includeはヘッダでもソースでもどちらでもOKです。
ええ、C言語の仕様上はそうなっていますが、学校の授業だったか先輩のアドバイスだったかで「#include "***.c"はすべきでない」と聞いた記憶があり、それがなぜだったのかが気になってしょうがないのです。

例えば「goto禁止」については、goto否定論者の論には一理あると感じますが、その論を否定するだけの論拠を持っていますので、状況に応じて私は使います。(それでも滅多に使わないけど、『コナミワイワイワールド エッチ005 アナライザ』では2箇所も使ってます。)同様に、まず「#include "***.c"はすべきでない」論の根拠は何なのかなー、と思っている次第なのです。
Posted by 小川@管理人 at 2009年08月10日 11:00
プログラミング作法は私があげたものですね。

C言語辞典は絶版になったという話です。

私自身は「#include "***.c"はすべきでない」と教えた事もアドバイスしたこともないですね。聞いたこともないかな。
ただ、理屈的には効率の問題なのでしょう。
ある部分のソースをインクルードで書いたんだったら、要するに関数化できる部分だし、それならいちいちインクルードしてその都度コンパイルしてリンクするのだったら、コンパイルするという手間が掛かりますわね。
今はマシンパワーが上がっているのでソースを埋め込んでコンパイルするというのが、それほど負担にはならないと思います。
それでもソース部分をインクルードで書くって言うのでしたら、ROMサイズの節約ぐらいしか、今のところ思いつかん。
本当に節約できるかは不明だが。。。

goto不要論は、ダイクストラの構造化プログラミングにその根拠がありますね。ただ、ダイクストラ自身は確か「gotoを使わないで全てのアルゴリズムが書ける。gotoを使うとスパゲッティプログラムになりがちなので使わない方がいい」というニュアンスで、絶対禁止を言っていたわけではなかったと記憶してます。
私自身も、「なるべくなら使わない方がいいと思うけども、どうしても使いたかったら、また使った方がスッキリしたソースになるというのなら使えばいいが、基本的には使わない」というスタンスです。
Posted by アレックス at 2009年08月10日 14:47
goto不要論について。

実はphpは5.3からgotoに対応しています。
http://jp2.php.net/manual/ja/control-structures.goto.php

しかしながら、今まで考えてこなかったせいもありいまいち「使ったほうがきれいに書ける」というシチュエーションがおいらは思いつかないので困っています。
小川さんアレックスさんともに「状況に応じて」使用するとお考えとのことですので、コメント欄では制約があるでしょうがちょっと状況というものを教えていただければと思います。

普段はoopバリバリなんですが。
Posted by miracleさん at 2009年08月11日 17:21
えー。。。私自身はgoto使った事ないです。
ただ、目くじら立ててまで「goto使うな」とは言わないで、goto使った方がスッキリするんだったらそれでいいではないか、というスタンスなだけです。

C言語なら、2重・3重ループから一気に抜ける場合とかですかね。
何にしても、それほど多い状況ではないです。
Posted by アレックス at 2009年08月11日 18:24
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック