長い「列」コードのために短い変数名を犠牲にしますか?


17

私は適切なプログラミングスキルを習得しようとするCSクラスのアマチュアプログラマーです。これが私のコードの見た目です。コードの端は103列まで拡張されています。

int extractMessage(char keyWord[25], char cipherText[17424],
                   int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);


    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }

これらの超長い変数名を得る前に、i、j、kのようなものがありましたが、教授「プロフェッショナルな世界」でそのような変数を使用するべきではなく、lenWordのような短縮変数でさえ不十分だと主張します「レナードの世界文学」の略です。彼は意味のある変数名を選択するように言っていますが、そうすることでコーディングの黄金律を破って80列以下に保つように感じています。これを回避するにはどうすればよいですか?


26
立ち止まるな; より便利な名前を追加します。たとえば、cipherColumn + (rowSize*nextWord) + nextWordその計算が何のためであるかを明確にする記述方法を考えることができますか?あなたが読みやすさの恩恵を得るので、私は、計算よりもその名前の短い賭ける減少ラインの長さを。また、割り当てを揃えないでください。最も長い変数の名前を変更する場合は、すべてを割り当てる必要があります。
-jonrsharpe

2
うーん。だから、新しい変数を作成し、cipherColumn +(rowSize * nextWord)+ nextWordの結果をそこに保存して、さらに使用できるようにする必要があると言っていますか?それはプロがすることですか?私は本当に求めています
-RaulT

8
はい、それは私の提案です。私はプロであり、それが私がしたいことなので、少なくともそのうちのいくつかは。
-jonrsharpe

11
黄金律は、読み、理解できるコードを書くことです。私たちはマシンではなく他の人のためにコードを書きます。マシンにはマシンコードがあります。一部の人にとっては、あなたが説明したように見えるコード(1文字の名前など)は、他のプログラマー(および今後のあなた-今後数週間または数か月で忘れられるため)に対する敬意の欠如です。80カラムに固執する理由はありません。80年代のMS DOSではありません。
RSM

3
@stijnはい、しかしそれは私たちがそれを必要とした最後の時です。パンチカードに保存する必要がある場合に、8ビット8086プロセッサ用にCコードをコンパイルしないように、21世紀には80列のゴールデンスターダードが重要だとは思いません。80年代にとどまらず、それが私たちを巧妙なハッカーにするのではなく、このテクノロジーを拡張する必要があります。賢いのは、シンプルさ、読みやすさ、テクノロジーを最大限に活用することです。フルHDモニターがありますので、それを使用します。
RSM

回答:


24

通常、ここにあなたのようなコードが投稿されているのを見ると、水平スクロールが嫌いなので編集します。しかし、それはあなたの質問の一部なので、ここで編集を示します。

int extractMessage(char keyWord[25], char cipherText[17424],
                   int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);


    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }
}

そのブレークは意外かもしれないが、それは、水平スクロールとバージョンよりも読みやすいですし、それが名前の短縮よりはましだijk

それはあなたが使用してはならないということではありませんijk。これらは、3つのネストされたforループのインデックスを作成する場合に適切な名前です。しかし、ここで名前は本当にあなたが何が起こるかについての私の唯一の手がかりです。特に、このコードは実際には何もしないためです。

変数名の長さに従う最も良いルールはスコープです。変数の寿命が長くなるほど、その名前と競合する仲間の変数が増えます。CandiedOrangeという名前は、スタック交換で一意です。チャットをしている場合は、「Candy」と呼んでください。しかし、今、あなたはその名前がCandideCandy ChiuCandyflossと混同される可能性のある範囲にいます。したがって、スコープが長いほど、名前は長くなります。スコープが短いほど、名前は短くなります。

行の長さが名前の長さを決定することはありません。もしそうなら、コードをレイアウトする別の方法を見つけてください。そのためのツールがたくさんあります。

私が最初に探すものの1つは、取り除く必要のないノイズです。残念ながら、この例は何もしませんので、すべて不要なノイズです。動作するものが必要なので、最初に何かをさせましょう。

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }
    return cipherColumn;
}

そこで、今では何かをします。

これで何かができるようになったので、何を取り除くことができるかがわかります。この長さのものは使用されません。これcontinueも何もしません。

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

私たちはソース管理の世界に住んでいるので、いくつかの小さな空白を調整してみましょう。行が変更されたと報告される唯一の理由は、その一部が列に並んでいたからではなく、何かをしているからです。

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn = 0;
    int cipherColumn = 0;
    int offset = 1;
    int nextWord = 1;

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

うん、それは少し読みにくいですが、そうでなければ、変更を検出するためにvdiffツールを使用する人を狂わせるでしょう。

次に、行の長さの制限を守ろうとしているので、これらの愚かな改行を修正しましょう。

int calcCipherColumn(
        char keyWord[25], 
        char cipherText[17424],
        int rowSize, 
        char message[388]
) {
    int keyColumn = 0;
    int keyOffset = 1;

    int nextWord = 1;
    int cipherColumn = 0;
    int cipherOffset = (rowSize * nextWord) + nextWord;

    char key = keyWord[keyColumn];
    char keyNext = keyWord[keyColumn + keyOffset];

    while (key != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyNext != cipherText[cipherColumn + cipherOffset]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

そこで、ループ内のロジックは、ループ内の変化に焦点を合わせています。実際、以外cipherColumnはすべてマークできますfinal。そしてねえ!あれ見てよ。今、それを行う余地があります。

私がしたことは、さらに3つの変数を追加し、1つの名前を変更して、それらを少し再配置することだけでした。そして結果はたまたま行を短くして馬鹿げた改行なしで収まるようにした!=

確かに名前keykeyNext説明のことではないですが、彼らそれぞれが長いこと生きていない操作を行い、一度のみ慣れ、そして最も重要なループで興味深いことは何もやっていません。だから彼らはそうである必要はありません。追加の変数を導入することで、必要に応じて名前を長くする余地ができました。状況は変化するため、最終的には必要になる可能性があります。もしそうなら、呼吸の余地があるのはいいことです。

また、Jeff Griggのフォーム6バリアントスタイルで入力パラメーターをレイアウトして、行の長さの制限を尊重することも示しました。


わあ、それは説明です!ええ、コードは実際には何もしないことを知っています。おそらくほんの少しのスニペット以上のものを投稿すべきだったでしょうが、コードの列の長さと変数名に関してプロが何をするかについての一般的な考えを得ようとしていたと思います。しかし、あなたの答えは、これから私のコードに間違いなく実装するいくつかの非常に甘い変更を示しました!もう1つ質問があります。改行するのに適している場所はどこですか。オペレーターの前に?受け入れられた「標準」はありますか?
-RaulT

1
@RaulTは、作業中のコードベースを読むのに少し時間を費やします。他のコーダーを驚かせない、何を使用できるかがわかります。標準文書がある場合はそれに従ってください。しかし、最良の方法は、仲間のプログラマーに尋ねて、あなたのものがどれだけ読めるかを尋ねることです。ああとcodereview.stackexchange.comをチェックアウト
candied_orange

cipherOffsetの下にコメントを追加し、その式は明らかではないため、計算を説明します。3週間でその理由を忘れます。
ネルソン

15

他の人々はすでにいくつかの有用な提案を行っています。要約してみましょう。

  • 1行あたり80文字が80年代の黄金律だったかもしれません。最近では、ほとんどの人が100〜130文字で構いません。
  • 式の中で改行を使用します。
  • 中間結果を導入して長い式を分割します。

別の推奨事項を追加したい:長い名前について独断的ではない!変数のスコープが大きいほど、より多くの情報をその名前に入れる必要があります。一般的に、変数のスコープを小さく保つことは良い考えです。

たとえば、キーワード暗号化テーブルの列に変数があり、変数のスコープでこのテーブルが1つしか使用されていないことが明らかな場合は、それを呼び出すかcolumn、さらにはを呼び出しても問題ありませんcol。スコープが大きく、複数のテーブルが関係している場合、それを呼び出すのは理にかなっていkeyWordEncryptionTableColumnます。

別の例:2行または3行にまたがる本体を持つループがあり、配列の要素にアクセスするためにインデックスを使用する必要がある場合、indexの呼び出しに問題はありませんi。この文脈では、例えば少なくともほとんどの人にとって、はるかに読みやすいarrayIndexOfMyVerySpecialDataSetです。


1
あなたの答えに同意します。職場では、レガシーの理由とレビューボードを使用しているため、c / c ++には80文字/行を使用します。C#100文字/行の場合、読みやすさを保つために規則を破って100を少し超えることがあります。
peval27

うわー、なんて素晴らしい答え!! これらのすべての回答は素晴らしかったです、私が感謝して助けてくれてありがとう!
-RaulT

80文字の行は時代遅れであるという考えを押し付けることに強く同意します。特定のプロジェクトや場所に適用されます(主に一貫性のため)が、多くの場合、単に不要です。多くの開発者は、フルモニターでVisual StudioやIntelliJのようなものを使用しており、他のもの(ドキュメントなど)用の2番目のモニターを持っています。したがって、彼らは自分のコードのために多くの画面領域を持っています。1行あたり80文字しか使用していない場合、おそらく大量の未使用スペースがあります。そして、80文字の制限はあなたを傷つけます!特に、標準ライブラリが長いお尻の名前を強制する可能性があることを考慮した場合。
カット

1
私のポイントは、一部の言語では、80文字が大きな制限であるという事実を回避することは本当にできないということです。なぜそれが不必要になったのですか?また、最近では、ほとんどすべてのビッグネームエディタとIDEが優れたスマートソフトワードラップを備えているため、行の長さをまったく制限することはできません。行の長さは、読者が見ることができるものであれば何でもかまいません。より最適な結果を得るために、ウィンドウのサイズを変更できます。個人的には、このアプローチが理想的である場合があります。そして、このソフトラップがどのように機能するかにまだ失望していません。
カット

単純な変数名を使用するときは常に、スコープを100%確実にする必要があります。JavaScriptの閉鎖について学ぶために3時間を費やしました。
ネルソン

3

私は一般的に先生に同意します。ただし、失敗する大きなコードで大量に使用する変数がある場合は、その意味を明確にした後、その短縮形を使用することをお勧めします。複雑な算術式や代入がたくさんあるときのように、長い変数名ではそれをうまく読みません。

概要について:

ExtractMessage(char keyWord[25], char cipherText[17424],
               int rowSize, char message[388]) 

これは目的を果たさず、行の長さを制限するだけでは読みやすくなりません。これを読みやすくしたい場合は、次のようにします。

ExtractMessage(
  char keyWord[25],
  char cipherText[17424],
  int rowSize,
  char message[388]
  )
{

そして、タイプ識別子を整列させることさえできます(intの後にスペースを追加します)。ただし、次のように初期化または引数リストの概要を説明する場合は注意/制限してください。

int keyColumn    = 0;
int cipherColumn = 0;
int offset       = 1;
int nextWord     = 1;

問題は、名前を変更したり変数を追加したりすると、ブロック全体を再フォーマットしてきれいな外観を維持する必要がある場合があることです。導入する意味のない変更ほど作業のためではなく、バージョン管理システムでは恐ろしく見えます。同僚はあなたがファイルを変更したことを確認し、以前のバージョンとの差分をとってあなたが何をしたかを確認します。その後、すべての行が変更されると点灯し、実際の変更が不明瞭になります。これが実際にどれほど悪いかを使用する比較ツールの品質に少し依存しますが、一般的にコードを個人的にしすぎたり、1行のフォーマットを他に依存させることは良い考えではありません。

アウトラインは目的に役立つ場合があります。ほぼ同じ数十の連続した行がある場合、それらをアウトライン化すると、どこが違うかを簡単に見つけることができます。

職場では、バージョン管理システムに送信する前にコードに対して行った凝った書式設定を根絶する自動書式設定が行われている場合があることに注意してください。


1
個人的には、あなたの答えの最初のコードブロックは2番目のコードブロックよりもずっと読みやすいです。
マイルルーティング

1
三度目は絶対にしないでください、それを維持するのはメンテナンスの悪夢です。
jwenting

3

免責事項:私はここで少しポイントを誇張して、ポイントを明確にします。だから、塩の粒と最上級を取ります。

あなたの先生は100%正しいです:もう80文字ほどの「黄金律」はありません(Linuxコードを書いているのでなければ)。そのルールは、当時の端末のサイズのために確立されましたが、最近では、エンドウィンドウで150文字以上を簡単に詰め込むことができます。そして、その制限を超えても、エディターは行をソフトラップするので、スクロールする必要はありません。そして80文字を超えない唯一の理由はスクロールの必要性でした

そうは言っても、あなたのラインを無期限に成長させる必要はありません。行が長いほど、人間が解析するのが難しくなります。しかし、短い変数名は長い行の問題の解決策ではありません

解決策は、さらに適切な名前の変数を導入することにより、論理的に式分割することです。空白を賢くしようとしないでください。適切な名前を付けることができる任意の部分式を識別し、その変数を作成します。これにより、変数を計算するコードと、その変数を使用するコードの両方が簡素化されます


あなたの質問の一部ではありませんが、とにかくコメントしたいと思います:=演算子を垂直に並べることは非常に悪い考えです。

その理由は3つあります。

  1. 垂直方向に同義の演算子を含むブロックの編集はPITAです。最大の変数の長さが変更(名前の変更、追加、削除)されるたびに、ブロック内のすべての行をレタッチして、「いい」レイアウトに戻す必要があります。

    もちろん、この問題は有能なエディターを使用することで少し軽減される可能性があるため、これは小さな理由です。本当の理由は2番目です。

  2. 再配置によって導入されたこれらの偽の空白の変更は、などの最新のバージョン管理システムではうまく機能しませんgit。実際の競合が発生しておらず、アライメントが使用されなかった場合に競合が通知されない場合、マージ競合が大量に発生する傾向があります。これらの偽りの衝突のそれぞれは、あなたに貴重な時間を費やすことになります

  3. アライメントは意味論的意味をゼロにします。無意味です。アラインメントを使用してよりよく理解できるものはありません。ブロック内のすべての行は、それが何をするかを理解するためにそれ自体で読む必要があり、上下の行への接続は純粋に構文的な性質のものです。

アラインメントには意味的な意味はありませんが、多大なコストが発生するため、時間をかける前に習慣を学習する必要があります。


80文字という制限が気に入ったら、Fortranプログラミングを試してください。確かに、新しい標準では、Fortran行の制限が132文字に引き上げられましたが、制限を超えるプログラムのコンパイルが機能しなくなるという事実は引き続き有効です。プログラミングが得意であれば、行の長さの制限など、Fortranを嫌うようになります。その後、あなたはあなたの残りの人生のために癒されます。

私は自分でプロのプログラミングをする必要がありましたが、その線の長さの制限を最も嫌うことを教えてくれました。コンパイラーがそれを正しくコンパイルできなくなったからといって、単純で読みやすい行を部分に分割することほどイライラすることはありません。そして、1行で表現されたときに最も単純なコード行が間違いなくあります。


3

プログラミング環境の制限により、長年にわたって多くのスタイル上の規則(規則ではありません!)が生まれました。パンチカード時代に は、物理ソース行に表示できる文字数に厳しい制限がありました(これが、Fortranが行継続文字用に列6を予約した理由です)。数十年前には、私は80x24のアンバーオンブラックVT220ターミナルで作業していませんでした。私が使用したエディターは行を80文字に制限していませんでしたが、水平スクロールを避けるために最善を尽くすと、人生はずっと楽になりました。

Fortranの('77まで、IINM)の古いバージョンの下、あなたもできませんでし持っている以上の6〜8文字の長だったidentifersを。80年代になっても、Cは外部名の最初の8文字が意味のあるものであることを保証するだけでした(そのため、一部のライブラリ関数にはのような素晴らしい説明的な名前が付いていますstrpbrk)。

もちろん、21世紀の20年後、私たちにはもはやそのような制限はありません。より記述的な識別子を使用しない理由ありません

正しいコンテキストでのことijありk完全に合理的で意味のある名前です。ループ内の配列またはベクトルを反復処理していて、現在の要素を識別するために何かが必要な場合は、i完全にうまく機能します。次のような名前は使用しません。そのコンテキストcurrentElementはそれ以上意味がなく、視覚的な混乱を追加するだけです。

そうは言っても、あなたの教師は、すべてをより長く、よりわかりやすい名前で考えるように強制することで間違っていません-最初にその習慣を身に付け、次に必要に応じてどこを節約するかを学ぶと、あなたにとって人生はより簡単になります。誰かのようだった 8文字以下にフィットすべてに強制的に一度、それが少ないよりも多くの情報の側に誤るために間違いなく良いです。経験を積むにつれて、識別子の長さを節約できる場所と、もう少し説明的にする必要がある場所を学習します。


-1

これがcで機能するかどうかはわかりませんが、数式を複数行に分割する方法はありますか?私はそのような何かがPythonに存在することを知っています。

新しい行で+(rowSize * nextWord)+ nextWord]){を開始できるかどうかを確認します。(IDEでEnterキーを押してインデントされるかどうかを確認し、Cが前の式が現在の行で完了していることを確認します)


1
はい、これは間違いなく可能です。Cは、セミコロンのようなものを追加するまで、コードの行と行を認識します。それに伴う問題は、関数が50行を超えることはできず、私の例のコードには50行はないが、それは関数全体のほんの一部に過ぎないということです。必要な機能を実行できる意味のある変数を含む50 x 80のボックスにアルゴリズムを記述することは、非常に制約されています。これらの長いコードのチャンクを新しい関数に格納し続けることはできましたが、非常に多くの関数呼び出しが行われるようになり、コードを読むことができなくなります。
RaulT

5
「私は非常に多くの関数呼び出しで終わるように感じます、人々はコードを読むことを失います。」まったく逆です!別の方法にコードを抽出すると、あなたは彼らに説明的な名前を与えることを可能にする増加(特にあなたから抽出されている方法の)読みやすさを。メソッドが多すぎる場合、クラスは多くのことを行っている可能性があります(単一の責任原則)。メソッドを別のクラスに再度抽出すると、そのものにわかりやすい名前を付けることができます。
ローマンライナー

50行に近づいている関数は、おそらく長すぎて複雑すぎます(1の複雑さでのデータ初期化の例外を除きます)が、通常、そのような制限が議論されるとき、それらはコード行であり、単一行を分割しますコードの行、つまりセミコロンへの追加行は多くの場合、余分な行としてカウントされません。Prof!
スティーブバーンズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.