Learning without thought is labor lost; thought without learning is perilous.

孔子

過去のプログラマの忍者は、コード管理者泣かせのトリックを使いました。 コードレビューの専門家は、テストの中でそれらを探します。 新米の開発者はプログラマ忍者よりもそれらを使うことがあります。

これらを注意深く読んで、あなたが誰であるかを知ってください – 忍者、初心者、またはコードレビューア?

諷刺

ここに書いてあるのは悪いコードを書き込むルールです。 多くの人が忍者の道を辿ろうとしますが、上手くいくことはほとんどありません。

簡潔が肝心(Brevity is the soul of wit)

できるだけコードを短くしましょう。あなたがどれだけ賢いかを示しましょう。

そのためには捉えにくい言語機能も使いましょう。

例えば、この3項演算子 '?' を見てください:

// よく知られている javascript ライブラリから持ってきました
i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

すごいですよね?もしあなたがこのように書いたら、この行を見て i の値が何かを理解しようとする開発者は、愉快な時間を過ごすことになります。そして、あなたのところに来て、答えを求めます。

より短いことが常により良いと教えましょう。彼を忍者の道に導きましょう。

一文字の変数

The Dao hides in wordlessness. Only the Dao is well begun and well completed.

Laozi (Tao Te Ching)

より速くコード化するためのもう1つの方法は、あらゆる場所で1文字の変数名を使うことです。a, bc のように。

森の中の忍者のように、短い変数はコードの中で消えます。だれもエディタの “検索” を使って見つけることはできません。たとえ誰かがそうできたとしても、ab が意味することを “解読” することはできないでしょう。

…しかし、例外があります。本物の忍者は決して "for" ループのカウンタとして i を使いません。色んな箇所で使いますが、ここでは使いません。見回すと、より多くのエキゾチックな文字があります。例えば x または y です。

ループ本体が 1-2 ページ(できればより長くする)の場合は、ループカウンタとしてのエキゾチックな変数は特に良いです。そのループを深く見ている人は、変数名 x がループカウンタであることはすぐには分からないでしょう。

略語を使用する

チームのルールで、1文字や曖昧な名前の使用を禁止している場合、それらを短縮して略語を作ってください。

このように:

  • listlst.
  • userAgentua.
  • browserbrsr.
  • …etc

本当に感が鋭い人だけがこのような名前を理解することが出来ます。すべてを短くするようにしてください。あなたのコードを支持できるのは、有能な人だけです。

高く舞い上がる、抽象的になる

The great square is cornerless
The great vessel is last complete,
The great note is rarified sound,
The great image has no form.

Laozi (Tao Te Ching)

名前を選んでいるとき、最も抽象的な言葉を使ってください。obj, data, value, item, elem など。

  • 変数の理想の名前は data どこでもそれを使いましょう。確かにすべての変数は データ を保持していますよね。

    …しかし、もし data が既に取られていたらどうしますか? value を試みてみましょう、それもまた普遍的です。結局、変数は最終的に を取得します。

  • 変数をその型で命名する: str, num

    試してみましょう。若い忍者は不思議に思うかもしれません – このような名前は本当に忍者のためになるのでしょうか?はい、その通りです。

    確かに、変数名は中身に何があるかを意味しています: 文字列、数値またはそれ以外の何か。しかし外部からこのコードを理解しようとするとき、実際にはまったく情報がないことに驚くでしょう。

    実際、値の型はデバッグで簡単にわかります。しかし変数が意味するものが何か?どの文字列/数値が格納されるのか?相当の熟慮なしでそれを理解する方法はありません。

  • …しかし、これ以上このような名前がなかったらどうしますか? 単に数値を付け足します: data1, item2, elem5

注意力テスト

本当に気が利くプログラマだけがそのコードを理解できます。しかし、どうやってそれをチェックしましょう?

1つの方法は – 似た変数名を使うことです。datedata のように

できるだけそれらをミックスしてください。

このようなコードを素早く読むことは不可能です。また、タイポがある場合…うーん…私たちは長い時間行き詰まります。

スマートな同義語

最も難しいことは暗い部屋で黒猫を見つけることです。そこに猫がいない場合は特にそうです。

孔子

同じ ものに対して 類似の 名前を使うことは人生をより面白くし、あなたの創造性を外に示します。

例えば、関数のプレフィックスを考えてください。もし関数が画面上にメッセージ表示する場合、 – displayMessage のように display… から始めます。そして、次に別の関数でユーザ名のような、何かを画面に表示するとき、showName など show… から始めます。

実際には何もありませんが、このような関数の間で微妙な違いをほのめかしましょう。

チームの仲間の忍者と契約を結びましょう: もしジョンが “表示をする” 関数を display... で始めたら、ピーターは render... を使い、アンは – paint... を。どのくらい面白くて多様なコードになったかに注目してください。

…そして今やハットトリックです!

重要な違いを持つ2つの関数では – 同じプレフィックスを使いましょう!

例えば、関数 printPage(page) はプリンタを使うでしょう。そして関数 printText(text) は画面上にテキストを表示します。使い慣れていない読み手に類似の名前がつけられた関数 printMessage について考えさせましょう。: "これはどこにメッセージを置きますか?

プリンタ、または画面?" 本当に輝かせるためには printMessage(message) は新しいウィンドウに表示するべきです!

名前の再利用

Once the whole is divided, the parts
need names.
There are already enough names.
One must know when to stop.

Laozi (Tao Te Ching)

本当に必要なときにだけ、新しい変数を追加してください。

代わりに、既存の名前を再利用してください。新しい値をそこに書き込みます。

関数では、パラメータとして渡された変数だけを使用しようとしてください。

そうすれば、変数 now に入っているものを正確に特定するのは本当に難しくなります。また、それがどこから来るのかも。直感の弱い人は1行ずつコードを解析し、すべてのコードのブランチの変更を追跡する必要があります。

そのアプローチの高度のパターンは、値をループや関数の途中で、こっそり (!) 似たものに置き換えることです。

例えば:

function ninjaFunction(elem) {
  // elem を処理するコードが 20 行ほど

  elem = clone(elem);

  // さらに 20 行, いつの間にか elem のクローンを処理しています!
}

関数の後半で、elem を使いたい仲間のプログラマは驚くでしょう… デバッグのときにだけ。コードを調べた後、自分が clone に対して処理をしていることに気づくでしょう。

経験豊富な忍者に対しても、殺人的に効果的です。

楽しみのためのアンダースコア

変数名の前にアンダースコア ___ を置きましょう、_name もしくは __value のように。もしあなただけがその意味を知っているなら素晴らしいです。もしくは、特に意味はなく単に楽しむために追加するのもよいです。異なる場所で異なる意味をもたせるのも良いです。

あなたは、一発の弾丸で2匹のうさぎを殺します。1つ目は、コードがより長くなり可読性を下げます。2つ目は、仲間の開発者はアンダースコアの意味を知ろうとするために長い時間を費やすかもしれません。

賢い忍者はコードの1ヶ所にアンダースコアを置き、別の場所では避けます。これにより、さらにコードが壊れやすくなり、未来のエラーの可能性が高まります。

あなたの愛を示す

みんなにあなたの存在がどれだけ壮大かを見せてください! superElement, megaFrameniceItem のような名前はきっと読者を啓発します。

確かに、変数名には super.., mega.., nice.. などが書かれています。が、その一方で – それはその詳細を何も示しません。読者はその隠された意味を探すために時間を割くかもしれません。

外部の変数と重ね合わせる

When in the light, can’t see anything in the darkness.
When in the darkness, can see everything in the light.

Guan Yin Zi

関数の内側と外側で同じ変数名を使ってください。単純で努力は不要です。

let user = authenticateUser();

function render() {
  let user = anotherValue();
  ...
  ...many lines...
  ...
  ... // <-- プログラマは user を使って処理をしたい...
  ...
}

render の内側へジャンプしてきたプログラマは、恐らくローカルの user が外の user を隠していることに気づかないでしょう。

そして、外部変数、authenticateUser() の結果であるという想定で user を使って処理しようと試みるでしょう… トラップが飛び出しました! デバッガーの出番です…

至るところで副作用!

何も変えないように見える関数があります。 isReady(), checkPermission(), findTags()… それらは、外側のものを何も変えることなく、データを計算したり、見つけて返したりすると想定されています。つまり、“副作用” なしです。

本当に美しいトリックは、メインの処理に加えて “役立つ” アクションを追加することです。

is.., check, または find.. と名づけられた関数が何かを変更するとき、あなたの同僚の顔の驚きの表情は、きっとあなたの理性のたがを広げるでしょう。

驚かせるためのもう1つの方法は、標準ではない結果を返すことです。

あなたのオリジナルの考えを見せましょう! checkPermission の呼び出しで、 true/false ではなく、結果の確認が複雑なオブジェクトを返すようにしましょう。

if (checkPermission(..)) を書こうとした開発者はなぜ動かないのか不思議に思うでしょう。彼らに教えましょう: “ドキュメントを読みなさい!” そしてこの記事を見せてください。

強力な関数!

The great Tao flows everywhere,
both to the left and to the right.

Laozi (Tao Te Ching)

その名前に書かれていることで関数を制限しないでください。広くあれ。

例えば、関数 validateEmail(email) は(emailの正しさのチェックに加えて)エラーメッセージを表示し、emailを再度入力することを要求します。

追加のアクションは関数名から明白であってはなりません。本当の忍者のコーダは、同様にコードからもそれを明らかにしません。

複数のアクションを1つに結合すると、あなたのコードを再利用から守ります。

想像してみてください、emailのチェックだけ行い、メッセージを出力したくない開発者を。両方を行うあなたの関数 validateEmail(email) は彼にはマッチしません。そのため、彼はそれについて何かを尋ねるようなことはしないので、あなたの作業が中断させられることはありません。

サマリ

すべての上の “アドバイス” は実際のコードからです… 経験豊富な開発者により書かれていることもあります。たぶんあなたよりも経験豊かな ;)

  • それらのいくつかに従うと、あなたのコードは驚きに満ちるでしょう。
  • それらの多くに従うと、あなたのコードはあなたのものになり、誰もそれを変更したくないでしょう。
  • すべてを守れば、あなたのコードは啓発を求める若い開発者にとって貴重な教訓になるでしょう。
チュートリアルマップ

コメント

コメントをする前に読んでください…
  • 自由に記事への追加や質問を投稿をしたり、それらに回答してください。
  • 数語のコードを挿入するには、<code> タグを使ってください。複数行の場合は <pre> を、10行を超える場合にはサンドボックスを使ってください(plnkr, JSBin, codepen…)。
  • 記事の中で理解できないことがあれば、詳しく説明してください。