2.3節で述べたように、それは2つの主な理由あいまいな複雑さの一つです。重要な新しい情報システムは、開発者には自明でない場合は、ブレがあるでしょう。ソリューションの曖昧さの問題は、書き込みコードにシンプルで理解しやすい方法を使用することです。この章では、コードは、多かれ少なかれになるよう、いくつかの簡単な要因について説明します。
コードはシンプルで使いやすいソリューションであれば、人はすぐにあまり考えず、コードを読むことができ、そして初めて、彼らは行動やコードの意味を推測することをその手段が正しいだろう。読者は、プロセスコードに必要な全ての情報を収集するためにあまりにも多くの時間や労力を費やす必要はありませんので、コードは、シンプルで簡単な解決策である場合。コードはシンプルで簡単な解決策ではない場合、読者はそれを理解するために多くの時間と労力を費やす必要があります。これは彼らの効率が低下するだけでなく、エラーや誤解の可能性を増加させるだけでなく、。クリアコードは、コードのコメントよりもあまり目立たないが必要です。
「シンプルで簡単な解決策は、」読み手の考えである:他の人のコードのテイク・ノートでは、問題の解決策は、独自のコードを見ることよりも簡単でシンプルで簡単ではありません。このように、コードレビューにより、コードの可視性を決定するための最良の方法。誰かがあなたのコードを読めば、それは明らかではない、それは、それはあなたの意見であるかは明らかに関係なく明らかにされていません。コードが明らかになりますかを理解しようとすることで、将来的にはより良いコードを書く方法を学びます。
18.1は、コードより簡単なものを作ります
前の章では、コードが最も重要な技術の2にシンプルで簡単なソリューションです議論してきました。最初は、良い名前を選択する(第14章)。文書の必要性を減らす、コードの動作を明確にする正確で意味のある名前。名前があいまいな場合には、読者が意味指定されたエンティティを推測するためのコードを読み込みます。この時間がかかり、エラーが発生しやすいが。第二のトリックは、一貫性(第17章)。同様のことは、常に同様の方法で行われている場合、読者は、彼らが前に見てきたパターンを識別することができ、そしてすぐにコードの詳細な分析をせずに、(安全な)結論に来ます。
ここでは、コードよりシンプルかつ簡単な解決策を作るために、いくつかの他の一般的な技術です。
白の賢明な使用。道をフォーマットすると、コードは、コードの理解のしやすさに影響を与えます。押し出された空白となっている以下のパラメータ文書を、考えてみましょう:
/**
* ...
* @param numThreads The number of threads that this manager should
* spin up in order to manage ongoing connections. The MessageManager
* spins up at least one thread for every open connection, so this
* should be at least equal to the number of connections you expect
* to be open at once. This should be a multiple of that number if
* you expect to send a lot of messages in a short amount of time.
* @param handler Used as a callback in order to handle incoming
* messages on this MessageManager's open connections. See
* {@code MessageHandler} and {@code handleMessage} for details.
*/
引数の最後に、文書、次の引数は、その後、どこから始めれば場所を確認することが難しいです。どのように多くのパラメータであっても、またはそれらの名前はい明確ものではありません。あなたには、いくつかの空白を追加する場合は、構造が突然、文書のスキャンに簡単に、明らかになるだろう。
/**
* @param numThreads
* The number of threads that this manager should spin up in
* order to manage ongoing connections. The MessageManager spins
* up at least one thread for every open connection, so this
* should be at least equal to the number of connections you
* expect to be open at once. This should be a multiple of that
* number if you expect to send a lot of messages in a short
* amount of time.
* @param handler
* Used as a callback in order to handle incoming messages on
* this MessageManager's open connections. See
* {@code MessageHandler} and {@code handleMessage} for details.
*/
コードブロック内のメイン分離プロセスのための空白行は、次の例にも有用です。
void* Buffer::allocAux(size_t numBytes)
{
// Round up the length to a multiple of 8 bytes, to ensure alignment.
uint32_t numBytes32 = (downCast<uint32_t>(numBytes) + 7) & ~0x7;
assert(numBytes32 != 0);
// If there is enough memory at firstAvailable, use that. Work down
// from the top, because this memory is guaranteed to be aligned
// (memory at the bottom may have been used for variable-size chunks).
if (availableLength >= numBytes32) {
availableLength -= numBytes32;
return firstAvailable + availableLength;
}
// Next, see if there is extra space at the end of the last chunk.
if (extraAppendBytes >= numBytes32) {
extraAppendBytes -= numBytes32;
return lastChunk->data + lastChunk->length + extraAppendBytes;
}
// Must create a new space allocation; allocate space within it.
uint32_t allocatedLength;
firstAvailable = getNewAllocation(numBytes32, &allocatedLength);
availableLength = allocatedLength numBytes32;
return firstAvailable + availableLength;
}
コメント後の各空白行の最初の行は、コードの次のブロックで説明されている場合、この方法は特に有効である:空白運動コメントより目立ちます。
声明では、ブランクの文の構造を解明するのに役立ちます。他にはない、次の2つのステートメント、スペースの1つを比較します。
for(int pass=1;pass>=0&&!empty;pass--) {
for (int pass = 1; pass >= 0 && !empty; pass--) {
注:明白なコードを避けるために、時には不可能。これが発生した場合、不足している情報を提供することによって補償されるようにコメントを使用することは非常に重要です。これを行うには、あなたがそれらを混同感じさせる可能性があるかを把握するために、リーダーの位置に立たなければならない、どのような情報は、このような混乱を排除するであろう。次のセクションでは、いくつかの例を示しています。
コードあまり目立たないものを作るために18.2
コードを目立たなく多くのものがありますが、このセクションでは、いくつかの例を提供します。
あなたがそれらを使用して終わる可能性がありますので、(このようなイベント駆動型プログラミングなど)これらの方法のいくつかは、いくつかの状況で有用です。これが発生した場合、追加の書類は混乱の読者を減らすことができます。
イベント駆動型プログラミング。イベント駆動型プログラミングでは、そのようなまたはマウスボタンの到着などの外部イベントに応答して、アプリケーション・プログラムは、ネットワークパケットを押します。着信イベントを報告する責任のモジュール。イベントが発生したときに、モジュールコールイベント所与の関数またはメソッドを要求することによって、特定のイベントを登録するアプリケーションの他の部分。
イベント駆動型プログラミングトラッキング制御レオロジーは非常に難しいです。イベントハンドラは直接呼び出されることはありません。彼らは間接的にイベントモジュールによって呼び出され、インタフェースは、一般的に使用されるか、または関数ポインタれます。これは、実行時にハンドラを登録しているに依存します:あなたはイベントモジュールで呼び出すためのスポットを見つけたとしても、まだその特定の関数呼び出しを決定することはできません。したがって、それが有効であることを自分自身を納得させることは困難であり、イベント駆動型コード推論することは困難です。
この曖昧さを補償するために、インターフェースは、以下の例にあるときを示すために呼び出されたハンドラ各注釈に使用することができます。
/**
* This method is invoked in the dispatch thread by a transport if a
* transport-level error prevents an RPC from completing.
*/
void
Transport::RpcNotifier::failed() {
...
}
危険信号:目立たないコード
あなたはすぐに読んで意味や行動コードを理解することができない場合は、これは危険信号です。通常、いくつかの重要な情報があることを、この手段は、コードを読む人のための非常に明確ではありません。
ユニバーサルコンテナ:多くの言語は、STDのJavaやC ++のペアで、例えば、一般的なオブジェクトのクラスにグループ分け2つの以上のアイテムを提供::ペア。彼らは、単一の段変速機と、複数のオブジェクトが非常に容易になることができので、これらのクラスは魅力的です。最も一般的な使用方法の一つは、Javaでのこの例のように、メソッドから複数の値を返すことです。
return new Pair<Integer, Boolean>(currentTerm, false);
従って、それらの意味をぼかし、総称名を持つ要素のグループ化残念ながら、一般的なコンテナが明らかにコードにつながります。上記の例では、発呼者は、二つの基準値、これらの値の値の実際の意味のない表示を返さ()result.getKey()とresult.getValueを使用しなければなりません。
したがって、それは一般的なコンテナを使用しないことをお勧めです。コンテナ必要に応じて、特定の目的専用の新しいクラスや構造を定義します。また、ジェネリックコンテナのことはできません声明で追加の文書を提供することができますが、その後、要素のために意味のある名前を使用することができます。
この例では、一般的なルールを示しています。ソフトウェアは、読みやすいように設計され、容易ではない書き込みにする必要があります。コードを書く人のために、汎用コンテナは、その場しのぎの対策であるが、彼らは戻って混沌の読者をもたらすでしょう。ライト・コードへの最良の人々は、特定のコンテナの構造を定義するために数分を過ごすために、このコードはより顕著になります。
宣言と異なる種類の分布。次のJavaの例を考えてみましょう。
private List<Message> incomingMessageList;
...
incomingMessageList = new ArrayList<Message>();
変数がリストとして宣言されていますが、実際の値は、ArrayListのです。一覧はスーパークラスのArrayListであるため、このコードは有効ですが、それだけで文を参照してくださいが、実際の分布を見ていない読者を誤解されます。それは宣言と分布を一致させるのがベストですので、実際の型は、(リストの他のサブクラスに比べて、ArrayListの異なる特性を有し、スレッドセーフ属性)変数の使用に影響を与える可能性があります。
読者は、コードの違反を期待しています。メインのJavaアプリケーションで次のコードを、考えてみましょう:
public static void main(String[] args) {
...
new RaftClient(myAddress, serverAddresses);
}
読者はそれがここで起こるだろうと思うかもしれませんので、彼らは、メインの出口によって返されるほとんどのアプリケーション。しかし、そうではありません。RaftClientコンストラクタは、アプリケーションのメインスレッドが終了した場合でも、これらのスレッドを実行し続け、追加のスレッドが作成されます。この動作は、インタフェースのコメントRaftClientコンストラクタに記録しなければならないが、この挙動は十分に明らかに、メインプラス短いコメントの最後に価値がされていません。コメントは、アプリケーションが他のスレッドで実行し続けることを示す必要があります。コードは読者の期待に沿った合意であれば、それは最も明白である、そうでない場合は、この動作を記録することは、読者が混乱しないことが重要そうです。
18.3まとめ
解決すべき、シンプルで使いやすいと思いますするもうひとつの方法は、方法の情報です。コードが明らかにされていない場合、これは通常、コードリーダに関する重要な情報を取得しないことを意味しますRaftClientの例では、読者がRaftClientコンストラクタは、新しいスレッドを作成し、知らないかもしれない。例えば、双晶では、読者が(result.getKeyを知らないかもしれません)現在の項目の数を返します。
理解するために、コードを簡単にするためには、読者が常に彼らが必要とする情報を持っていることを確認する必要があります。これを行うための3つの方法があります。
- 最良の方法は、使用すると、抽象設計技術などの特別な例除去が必要とされる情報の量を低減することです。
- 第二に、あなたは他のコンテキストで情報の読者を使用することができます(規則およびコンプライアンスの期待に従うことによって、例えば)が得られているので、読者はあなたのコードのための新しい情報を学習する必要はありません。
- 第三に、あなたは、このような技術として良い名前とコメントの戦略を使用するコードでそれらに重要な情報を表示することができます。