プログラムへのそのこだわり、意味ある?
皆さん、メリクリマッスル! ゼバ会です!
このクッソ寒い空の下でリア充どもを客観的に見つめながら、皆さんいかがお過ごしでしょうか。
さてさて、プログラマーの皆さんがプログラムコードを書くときは、通常多くの人が細かい部分にこだわりを持っていると思います。
インデントの仕方、括弧の付け方、空白の開け方、などなどなどなど。
色々ありますよね。
なんでも話によると、この「クセ」を分析することで85%の精度で人物特定ができるんだそうな。
ホンマかいな。
まぁ、コードの書き方はそれくらい多種多様だよってことなのかもしれません。
もっとも、さすがに精度85%はないかもしれませんね。
なんせ、通常多くの企業では、コードルールを作って書き方を規定してたりしますからね。
ルールの厳しいところだと、個人特定なんか絶対不可能なくらいにガチガチに固めてるところとかありますし、そういうところだと当然ながら個人特定は無理でしょう。
自由なところは自由ですが。
ただ1つ気をつけたいのは、コードの書き方にルールを定めるのは、別に個人特定されないためではないということです。
コードルールをチームで定める目的は、あくまでも「メンテナンスしにくいコードになることを防ぐ」ためです。
(つまり、理論上は「理想的な世界共通のコードルール」を作ることが可能ってこと。あくまで理論上ね)
もちろん個人特定させないことを目的としてコードルール作る人は本当に滅多にしかいないと思うんですけど、とはいえ、ルールを作る際にメンテナンス性の向上を目的にできていないケースがあるのも確かです。
なんというか、、、世の中的にルールを作った方がいいことになってるから、それに倣ってるだけ。
あるいは自分が見やすいかどうか、くらいしか加味できていないルールを作る人とか。
それでもルールに理由があるならいいんだけど、理由も説明も一切不明だったり、あるいはルールガチガチなのにコードフォーマッターがない(ルールは壁に張り紙で!)ところとか、だいぶ昔だけど実際に過去にありました。
今回は私のそういう経験を生かし、皆さんに「チームで統一した方がいいルール」と「個人的な趣味に留めておいた方がいい部分」とを区別できるようになっていただこうかなと思います。
〇適切な横幅の決め方
コードフォーマッターの設定において、通常多くの皆さんが真っ先に悩むのがこれでしょう。
横幅の文字数。
とはいえ、どれくらいにすればいいのか迷ったすえ、最終的にはエイヤで適当に決めてしまう人も多いのではないでしょうか?
1行の横幅に上限を定めるのは、当然ながら、エディターに横スクロールが発生することを防ぐためではありません!
設定が適切であれば、横スクロールなど絶対に発生しようがない横幅にちゃんとなりますので、ゆえに横スクロールは結果的には関係ないのです。
コードの最大横幅は、トレースをする人の「眼球の横移動」を防ぐために制限します。
分かりやすい例となるのがこちらの本。
非言語行動の心理学(V・P・リッチモンド/J・C・マクロスキー)
内容的には個人的にすごいお気に入りの本なんですけど、段組みが横に長くてとにかく読みづらい!
横幅38文字(半角換算で76文字)あります。
ちょっと試しに読んでみてください。
おそらく多くの人は、1行読むごとに眼球の横移動がかなり発生するのではと思います。
続いてこちらの本。
経営分析の基本がハッキリわかる本(千賀秀信)
読んでみてどうでしょう。
横幅は28文字(半角56文字換算)と1行あたり10文字しか減ってませんが、眼球がその割には横移動しないことに気づいたでしょうか。
全くしないわけじゃないでしょうけど、視線がポン・ポン・ポンとランダムに飛ぶような動きをしてるんじゃないかと思います。
もしかすると普段あまり読書をしない人には分かりづらいかもですが、普段から読書量がそこそこある人は通常、このような横幅の十分に小さい本を読むとき眼球は横にはさほど動かさないものなんです。
これがいわゆる疲れない段組みです。
プログラムコードは、書いている本人は、頭の中で構造を組み立てながら書いているため、この眼球の横移動が全く苦になりません。
眼球移動なんかよりよほど大変な作業を、頭の中でやっているからです。
ですので書くときの書きやすさを基準に横幅を決める人は、数値が大きめになりがちです。
ですが他人が書いたコードを読むとき、この眼球移動がバカにできなくなってきます。
眼球を横に移動させないと読めないような横長のコードは、頭の中に1度に入ってくる情報量が制限されてしまいます。
場合によっては横スクロールなんかも発生して、トレース時の見過ごしもしやすくなってしまいます。
そうならないよう、一般には「横幅120文字」が標準とされてはいますが、これはあくまで推奨値としては「最大」と捉えるべきでしょう。
なぜなら人間は横幅120文字もの文を、1度に視界に収めることはできないからです。
ですので、人類共通的な最適解が横幅120文字もあるはずないのです。
だったら疲れない段組みを見習って全角28文字(半角56文字)にしちゃえばいいのかというと、そういうことじゃありません。
それは小さすぎて逆にダメです。
なぜなら、横幅は小さすぎても(当たり前ですが)改行が多くなってコードは縦に延びるからです。
改行の多いコードは、当然ながらそれはそれで1度に目に入ってくる情報量は少なくなります。
その結果、次に述べる「コードの実行順序が上下で入れ替わる」現象がより多く発生してしまいます。
〇コードの実行順序が上下で入れ替わるコードルールの例
コードの実行順が上下で入れ替わる、とはどういうことでしょうか。
たとえば以下は、横幅を極端に短く制限された現場の例です。
このプログラムの実行順はどうなるでしょう。
function attachData(data)
{
const proc =
function() {
alert('OK!');
};
if (
checkData(
convert(data),
) == 1
) {
proc();
}
}
正解はこう。
function attachData(data)
{
1 const proc =
7 function() {
8 alert('OK!');
};
5 if (
3 checkData(
2 convert(data),
4 ) == 1
) {
6 proc();
}
9 return;
}
もー、バラバラ!!
このようなコード記述が頻発するような現場では、1行あたりの文字数を増やすことによって、実行順が上下逆転するのを防ぐことができます。
function attachData(data)
{
1 if ( checkData( convert(data) ) == 1 ) {
2 const function() { alert('OK!'); };
3 proc();
}
4 return;
}
これで、全ての処理が左上から右下へ流れるように書かれたことになり、加えて行数が減ったことも合わせるとかなり読みやすくなったと思います。
で、初心者時代に「そうか! 1行は多い方が読みやすいんだ!」とカンチガイした人が、1行を120とか140とか、無制限とかにしちゃうわけですね。
(聞いてるか~? 20年前のオレ! おまえのことやぞ~)
でも惜しい!
1行の文字数はいつでも常に大きい方がいいワケではありません!
行数不足で順番がグチャグチャになったコードは、横幅を増やすことで順番をそろえることができるのは「一部のコード」だけです。
世の中のあらゆるコードが、単に横幅を増やせば上から順になるわけではありません。
第一、横幅の大きすぎるコードは先に述べたとおり読みづらいし、読み漏らしによるデグレのリスクを伴います。
ですので、上記のような横幅制限のキツい現場で読みやすいように順番をそろえるには、無理にルールを捻じ曲げるんじゃなくてこうします。
function attachData(data)
{
1 const cd = convert(data);
2 const dg = checkData(cd);
3 if ( dg == 1 ) {
4 const m = 'OK!';
5 const p = () => { alert(m) };
6 p();
}
7 return;
}
ほら、横幅を増やさなくてもちゃんと上から順になりました。
変数代入を増やすことで、1処理ずつ順番にを心がけるやり方です。
ただし変数代入が増えることはデメリットにもなりえます。
「データの移動が増えた」ように見えてしまって、それで読みにくいと感じる人もいるからです。
ですのであまりキツキツなのも考えモノでしょう。
現実には、チーム内の全てのメンバーが的確に折衷案を選べる状態がベストです。
横幅ルールだけでなく改行ルールにも言えますが、要は機械的に制限するのが間違いなんです。
間違いというか、、、理想論としては。
プログラムそれ自体はコンピューターが理解できればいいのだとしても、それをメンテナンスするのはあくまで人間。
ですから「人間に読めないプログラム」では意味がありません。
前回も書いたとおり、プログラムコードの美しさはコンピューターに対する処理効率ではなく、コードを読む人に対する思いやりの大きさで決まるものです。
人間に対する思いやりの心は、人間にしかありません。
ですので最終的には横幅なり改行ルールなりは、
1.チーム内で定めた Cyclomatic complexity をキチンと守ると
2.1メソッドがちょうど画面内に収まる
くらいがちょうどいいことになります。
なぜなら、それくらいが「初見のコードを読みやすい」からです。
おそらく通常は横幅80くらいがちょうどいいはず。
もちろんメンバーのトレース能力にもよるでしょうけど、色んな人が雑多にいるからといってエイヤで決めちゃうのはダメだし、書くときの書きやすさで決めてもいけません。
横幅は、あくまでメンテナンスしやすい幅にです。
〇言語仕様上できても、なるだけ避けるべき記述
さてさてちなみに。
上記の例の中に無名関数が出てきました。
が、宣言してすぐに使っているだけで「なんだこりゃ」と思った人もいると思います。
(私も自分で書いてて思ってましたヨ!)
無名関数ってのは、これのことですね。
const proc = function() { alert('OK!'); };
proc の部分はあくまで変数名であって関数名ではないので、結果的にこの関数には名前がありません。
だから無名関数ってワケ。
もちろん上記の例はあくまで例だから無意味な処理も出てきましたが、もしここで無名関数の利用が必須だとしたら、1行を短くするための方法論として、こんな案を思い浮かべた人もいると思います。
(function() { alert('OK!'); })();
宣言したあと、その後ろに (); を付けて実行させちゃうテクニックですね。
C系統の言語(いわゆる「ポインターをどんどん引き継いでいく」系の言語)では、たとえそれが関数名ではなかったとしても、関数のポインターを出力する記述でありさえすれば、後ろに括弧をつけることでその場で実行してくれます。
同じように、配列を出力する記述の後ろに大括弧をつけて、一部の値だけを取り出すこともできます。
firstData = getData()[0];
上記は、getData という関数から配列が戻ってくる前提で、その先頭データを取り出しています。
なぜなら、それが配列名でなかったとしても、配列のポインターを出力する記述でありさえすれば、後続処理はそれを配列として扱うからです。
ですが、できるからといっていつでもやっていいとは限りません。
コンピューターにはそれが適切な関数呼び出しに見えたとしても、コードを読む人間が適切と感じるとはかぎらないからです。
メンバー内に達人しかいない場合は別として、通常多くの場合は極力避けるべきです。
なぜなら、次の人に対する思いやりがないです。
〇まとめ
今回挙げた以外にも、コードルールには様々なものがありますよね。
・開き中括弧( { )の直後は必ず改行すべし
・インデントは4文字固定にすべし
・行末の空白は必ず消すべし
・空行を2連続開けるべからず
エトセトラ、エトセトラ、ブラブラブラ。
場合によっては、コードルールが結構多いチームもあるでしょう。
これらのルールを決めるに際して本当に気をつけなきゃいけないのは、
1.そのルールを作ることで、本当にコードはキレイになりますか?
2.ルールをあえて作らなかった場合、メンバーの書くコードは汚くなりますか?
この2点です。
大事なことなので何度も言いますが、プログラムコードの美しさは次の人に対する思いやりの大小で決まるものです。
思いやりの問題なわけですから、ルールはやたら増やせばいいわけでも、フリーダムが一番いいわけでもありません。
最終的には、コードルールで縛るより、多少遠回りでも思いやりをもってコードを書くための講習会を定期的に開く方が、ずっと効率がいいことになるわけです。
理想論としては、「コードルールはメンバーが成長するまでの繋ぎ」くらいの気持ちでいるのがちょうどいいのかもしれません。
〇次回予告
ところでですけど、当ゼバ会に何度も出てきたこの言葉。
Cyclomatic complexity
当たり前のように使っちゃってますけど、分からない人もいますよね?
多分、過去の会で登場したときに検索してみて、「うーん、分からん!」と思った人もいるんじゃないでしょうか。
はい。すいません。
説明の会を挟むのをすっかり忘れてました。。。(汗
(こないだ誰かと話してて、その人に「うーん、でもその概念って中級者向けだかんねー」って言われてハッとしました)
でもこの Cyclomatic complexity は本当に本当に本~~~当に大事です!
なぜなら「プログラムが見かけ上複雑に見える度合い」であり、「最低でも必要なテストの個数」でもあるからです。
つまり、この概念を真の意味で極めれば、無駄なテストの数をドンドン少なくすることができるのです!
テストの数が少なくなれば、当然テストに要する時間は減り、バグだって出にくくなるわけで、その結果作業時間は減って、仕事はどんどん終わり、自由時間は逆に増え、あなたハッピーわたしもハッピー。人類みんなハッピーデーになるわけです!
てなわけで、いい機会なので次回は Cyclomatic complexity の数え方を覚えてしまいましょう!