名前を長くすることを恐れないでください。長い説明的な名前は、短い謎めいた名前よりも優れています。長い説明的な名前は、長い説明的なコメントよりも優れています。
ロバートC.マーティン
私は理解しましたかクリーンコード正しいですか?コメントに入れる情報全体をclass/method/...の名前に入れます。それは次のような長い名前につながりませんか?
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions
あなたはクリーンコードのすべてを一緒に取らなければなりません。その本を何度も読んだ。私は頻繁にそれを私のチームの新しい開発者に貸しています。
はい、マーティンはコメントよりも長く説明的な名前を好むべきだと言っています。しかし、彼は単一の責任の原則も擁護しています。
SRPがいくつかの方法で定義されているのを見てきました。通常 "クラスまたはメソッドは変更する理由が1つだけあるはずです"、または "クラスまたはメソッドは1つのことだけを行う必要があります"。
だから、私は私の開発者に非常にわかりやすい名前を書くように言います。また、メソッドの名前が長くなりすぎていると、おそらく多くのことを実行しすぎていると私はよく言います。
メソッドの名前が管理できなくなっている場合は、リファクタリングが必要かどうかを検討してください。
Incrediblesパターンを回避するようにチームにも指示します。シンドロームから学んだように、「誰もが特別なとき、誰も特別ではない。」
クラスのすべてのプロパティまたはメソッドが同じWordで開始または終了する場合は、おそらくそのWordを省略できます。
これらが両方とも1つのクラスのメンバーであると仮定すると、以下は理にかなっていますか?
PageReloaderが多数あるようです。そのため、すべてのPageReloaderが行うことの基本クラスを作成します。
abstract class PageReloader {
//page reloader code
}
次に、名前は「エディターで使用される」ことが重要であることを示しているため、他の種類のVectorGraphicsReloadersが存在する必要があります。
abstract class VectorGraphicsReloader : PageReloader{
//vector graphics code
}
最後に、EditorGraphicsReloaderにアクセスします。これは、エディター専用に何かを行うVectorGraphicsReloaderです。
class EditorGraphicsReloader : VectorGraphicsReloader{
//editor code
}
のいずれか内で、これらのクラスには2つのプロパティが必要です。
public string Comments { get; set; }
public string Description { get; set; }
これらのプロパティが属するクラスは、それらがエディター、ベクターグラフィックスに固有であるか、すべてのページリローダーに共通であるかによって異なります。
はい、あなたはクリーンコードを理解していますが、あなたの例はかなり上にあります。
これはあなたが始めるものです:
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions
「ページリローダー」はおそらくページをリロードするため、「ページ」部分は冗長です。これはあなたに残します:
PageReloaderForDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions
ページは常に何かを表示しているので、Displaying
の部分も冗長です。これはあなたに残します:
PageReloaderForVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForVectorGraphicsThatAreUsedInTheEditorDescriptions
英語では、this-that-is-is-in-used-thatのように言い換えることができるthisのような構成体たとえば、食品に使用される着色は食品着色です。このルールを適用すると、次のようになります。
PageReloaderForEditorCommentsVectorGraphics
PageReloaderForEditorDescriptionsVectorGraphics
英語でも、this-for-thatのように言い換えることができるthis-thisのような構文。たとえば、水ボトルは水ボトルと言い換えることができます。このルールを適用すると、次のようになります。
EditorCommentsVectorGraphicsPageReloader
EditorDescriptionsVectorGraphicsPageReloader
そしてもちろん、あなたが適用できる他のショートカットがあるかもしれません。
たとえば、あなたのシステムではおそらく多くの種類のリローダーがありません。おそらくページのリローダーしかないので、次のようになります。
EditorCommentsVectorGraphicsReloader
EditorDescriptionsVectorGraphicsReloader
また、システムで「ベクター」について話す場合、「ベクターグラフィックス」について話すことはかなり明らかであるため、次のようになります。
EditorCommentsVectorReloader
EditorDescriptionsVectorReloader
...そして、これらは現実的にかなり長い名前だと思います。
いいえ、ボブおじさんはそれを言っていません。
彼の本には、クラス名に「すべてのコメント」を含める必要があると述べている部分はありません。
おそらく、特定の「ベクターグラフィックスなどを表示するページのPageReloader」は必要なく、すべての種類のページに同じPageReloaderを使用する必要があります。
彼の本には、彼が「謎めいた短い名前を説明的な意味のある名前で置き換える」と正確に何を意味するかの例がたくさんあります。
常にバランスを取る必要があります。通常、ソフトウェア専門家が話すとき、彼らは彼らの時間と場所の一般に理解されている問題に取り組んでいます。
名前が説明的でなく、不可解なため、メソッドのパラメーターとしてf、g、hを使用するなどの説明が必要な場合は、最初にこれらを長くして、より説明的にする必要があります。
プログラマーが過度に短い名前(多くの場合、ランダムな文字)を常習的に使用することは重大な問題と見なされていた時期があり、説明的な単語を1つまたは2つ使用するだけで、事態は大幅に改善されました。
今日では、反対の問題がしばしば見られます。不必要に冗長な名前を使用するプログラマー。多くの場合、特に何も説明しない、非常に一般的な用語のまとまりです。
最後に私の目を引いた後者の例は「ApplicationServices」でした。これが「ProgramTools」、「CodeStuff」、さらには「AppSvcs」よりもどのように説明的であるかすぐにわかりませんでした。
「VectorGraphics」は、意味を失うことなく「LineArt」にほぼ間違いなく削減できますが、「VectGfx」という省略形でも十分でしょう。
したがって、名前を説明的にするという原則は、名前をできる限り長くすることを意味するものとして解釈されるべきではありません。 高情報密度を含む名前を使用することです。
その要素には、音節や文字を経済的に使用することや、英語の優れたコマンドなどの暗黙の知識、および一般的なコンピューターの概念に精通していることが含まれます。
私はこの答えに同意します https://softwareengineering.stackexchange.com/a/409460/262662 Mike Nakisによるが、それ以外にもあります。
さらに、名前空間を作成して、これをグループ化することもできます。といった
_PageReloaders.EditorCommentsVector
PageReloaders.EditorDescriptionsVector
_
次に、同じ名前の変数がさらにある場合は、(短い関数/ブロックでのみ)できます...
_Reloaders = Utilities.Reloaders.PageReloaders;
Reloaders.EdtiorCommentsVector.doSomething(); // small scope only.
// equivalent to...
Utilities.Reloaders.PageReloaders.EdtiorCommentsVector.doSomething();
// And with prettier, so long as the segments are within about 40 characters, it doesn't matter. As it will look like this:
ReallyLongPath
.filledWithLongStrings
.JustToGetTo
.Utilities
.Reloaders
.PageReloaders
.EditorCommentsVector
.doSomething();
_
更新
ナキの答えの代わりに、オリジナルに基づいて実際に自分の名前を考えなければならない場合は、次のようにします。
_PageReloaders.VectorGraphicsPages.EditorComments
PageReloaders.VectorGraphicsPages.EditorDescriptions
_
または多分
_PageReloaders.EditorComments.WithVectorGraphics
PageReloaders.EditorDescriptions.WithVectorGraphics
_
しかし正直なところ、それはあなたが何をしているのかによって異なります。 editorCommentsとeditorDescriptionsに別のpageReloaderが本当に必要な場合、またはvectorGraphicsページと通常の別のpageReloaderが必要な場合は、 pages vs plainText pagesなら、あなたは自分がやらなければならないことをやらなければなりません。ページがベクターグラフィックスであるかどうかにかかわらず、それほど多くのものがない場合は、_PageReloaders.EditorComments
_を使用します。プロジェクトの成長に合わせて変数名を変更することを恐れないでください。また、_pgrldr.VGraph.EtrCmnt
_などを使用して、短い変数名を取得しないでください。しないでください。 目標は、あなたが初めて何をしたかを理解しようとするときに、将来の開発者(自分を含む)の頭痛の量を減らすことです。
更新の終了
ロバートC.マーティンが実際に言及していたのは次のことだと思います
_<!-- We actually had this in our codebase -->
<button class="btn-submit pers pers_cp"></btnbutton
<!-- What it meant, using the Clean Code standards -->
<button class="btn-submit btn-personnel_module btn-copy_action"></button>
_
このボタンは、すべてのモジュール間およびコピーされなかったアクションにコピー/貼り付けされました。 cssを書くとき、人々はクラスが何を意味するのかを知らなかったので、色だけでなく、それらのクラスをサイジングに使用しました。それを解くのは地獄でした。
これはforループにも当てはまります。何が良い...? (ここでも、実際にはコードベースからプルされています)
_for (let k=0; k < vehsAr.length; k++) {
let vehs = vehsAr[k];
}
/*---- OR -----*/
for (let vehicleIndex=0; vehicleIndex < vehiclesArray.length; vehicleIndex++) {
let vehicle = vehiclesArray[vehicleIndex];
}
_
for(i)
ループを使用して、入れ子のレベルを変更すると、i
を再利用して、すべてをk
にシフトする必要があります。代わりに説明変数を実際に使用した場合、実行する作業は少なくなります。少しの努力で長い道のりが進みます。
_for (let r = 0; r < width; r++) {
for (let c = 0; c < height; c++) {
grid[r][c].doSomething();
// I see immediately that rows is the first layer, and columns is the second layer.
// "row" and "column" is better than "r" and "c", but "r" and "c" still go a long ways.
invertedGrid[c][r].doSomething(); // If it goes in natural English reading order, I only have to check in one spot that r and c are backwards.
}
}
// Invert the nesting order
for (let c = 0; c < height; c++) {
for (let r = 0; r < width; r++) {
grid[r][c].doSomething();
invertedGrid[c][r].doSomething();
// Notice how the inner formulas don't change?
// If I used 'i' and 'k', convention is that 'i' is top layer, then 'j', then 'k', then 'l' which looks like '1'. It get messy.
// If I swapped height/width while using 'i' and 'k', I'd have to put in much more brain power to make sure height matched with the right letter and that letter matched with the right spot.
}
}
_
Updateforループでi
j
およびk
を使用することは完全に受け入れ可能であり、最も一般的ですループを書く方法。しかし、私がこれまで読んだことのほとんどに基づいたクリーンコード標準は、それを好きではありません。全然。 Prettier 1.0が末尾のコンマを嫌い、Prettier 2.0が末尾のコンマを好きなように。それは標準です。それには理由があります。それが唯一の方法ではありません。ただし、ここでは、より長い/より記述的な変数名を使用することを検討しています。
私がこれから取り上げるのは、次のようなアイテムがある場合です。
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions
次に、不足しているのはコンテキストです。論理的な方法でグループ化するに値するトップレベルのアイテムが多すぎ、そのグループ化によってコンテキストが提供されます。これは極端な例ですが、おそらく次のようにリファクタリングできます。
Comments.Editor.Page.Reloader
Descriptions.Editor.Page.Reloader
(または多分Page.Comments.Editor.Reloaderなど)ページがベクターグラフィックスを表示するかどうかに関する情報は、ページのtypeの一部、またはリローダーです。
変数名は単独では存在せず、他のオブジェクトのコンテキスト内にあり、型を持っています。これらはすべて理解に役立ちます。
名前が長くなりすぎている場合は、変数自体の負担が大きすぎるかどうかを検討してください。
その本の読者の一部は、非常に短い名前の長さの制限があった古いコンパイラーを試してみる古いプログラマーであることを忘れないでください。最初のC言語標準は、外部から見える識別子の最初のsix文字を重要なものとして扱うためにコンパイラーのみを必要としました(C89仕様 セクション3.1.2 )。 C標準ライブラリの関数と型には非常に簡潔な名前が付けられており、なじみのないものを混乱させることがあります。
私は常に、マーティンの助言を、画面の水平方向のスペースを考慮すべきものとして扱う古い習慣を非難するものとして解釈してきました。最近のコンパイラーは名前の長さを実際には気にしていません。プログラマー(ほとんどの場合)は、80列に制限されたコンソールでコードを作成していません。わかりやすい名前の利点は、短い(または長すぎる)名前から得られる利点をはるかに上回ります。
たとえば、C標準ライブラリにはmbstowcs()
という関数があります。その機能が何をするかわかりますか?私もダメ。マーティンは、そのような圧縮された名前はあまり価値がないと言っています。代わりに関数の名前がConvertMultibyteStringToWchar()
である場合は、ドキュメントを調べなくても、その関数を使用するコードを理解できるでしょう。
これは確かにコメントの代わりではありません。コメントは、呼び出し元が関数によって返されたメモリを解放する必要があるかどうか、関数がスローできる例外、関数がスレッドセーフかどうかなど、あらゆる種類の追加情報を記録します。コメントには、なぜ関数はそれがそうであるように実装されます。これは、どのくらい長く作成したかに関係なく、名前に合理的に詰め込むことができないすべての情報です。
より長い名前がコメントを置き換えることができる唯一のケースは、次のような場合です:
// tokenize a string
char *strtok(char *s1, const char *s2)
{
...
}
しかし、それが関数について文書化しているすべての情報である場合、名前はあなたの#1の問題ではありません。
// fixme
s私はプログラミングの地獄で最も深い層の1つである悪いコメントを考えています。
ただし、たとえば関数名は、その中で何かを変更しても不正確になる可能性は低く、機能が変更された場合は当然、名前も変更される可能性が高くなります。
これは、コメントよりも長い名前の方が望ましい理由の1つであり、コードをより簡潔にする重要な理由の1つです。
コメントクラスとデータ構造は無視します。これは問題ないと思います。通常、実際のコードでのコメントの方が重要です。
ボブおじさんがしていることの1つは、彼のコメントをひどく攻撃的な明るい赤にすることです。彼らが通常持っている素敵な心地よい色ではありません。これは、コードにコメントが必要な場合は、恐ろしい色の価値があると彼が感じているからです。攻撃に値する価値がある場合、彼はそれを削除します。
したがって、ボブおじさんはコメントを避けるべきだと信じていますが、私の心では、これはこのクリーンなコーディングルールの別のものと矛盾しています。変数名の長さはそのスコープに比例するという規則。したがって、グローバル変数には長い名前を付け、ローカル変数には小さな名前を付ける必要があります。
たとえば、私の関数の1つに、変数名ipがあり、コメントが変数名に押し込まれ、hostname_or_dotted_decimal_ip。したがって、これによりコメントが削除されましたが、変数が不必要に長くなりました。
私は以前ボブおじさんにローカルスコープの長い変数名について具体的に尋ねましたが、彼のコメントは次のとおりです。「小さなスコープの長い変数名は不愉快です。」個人的には、コメントを削除するためにやや長い変数名を使用しても、コードが不快にならない限り、犠牲は大丈夫だと思います。その変数が10回使用された場合、おそらく不愉快なことでしょう。
どうしても避けなければならないことの1つは、意味のある部分を行の最後に隠すことです。私は名前空間がゼロのC開発者であり、関数、データ構造、または変数をそれほど長く使用したことがありません。
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions
しかし、自然の力によって、コードにこれら2つのような嫌悪感を抱かなければならなかった場合。違いを前面に移動します。
CommentsOfPageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditor DescriptionsOfPageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditor
この原則は、ケルビンヘニーによって 多くのプログラマの7つの無効なコーディング習慣 でカバーされています。