プログラマーの自己修養について——再構築(1)


私と再構築
       
リビルドを書きたいのは、先月リビルドに関する本を読んだからで、十数種類の異なるリビルド方法を紹介しました.本当にハンドグリップ形式でいろいろな再構築方法を教えてくれます.本名は「再構築:既存のコードの設計を改善する」です.http://book.douban.com/subject/1229923/).この本が私にどれだけの啓発を与えるかは言えませんが、中で紹介されているコード設計の大部分の方法は、私が学んだことや知っていることですが、これは私が本当に系統的に再構築に接触したのは初めてです.以前は自分のコードを最適化する習慣があったが,システムの方法論でコードを再構築することはこの本を読んだ後のことである.
        そしてリビルドは徐々に慣れてきて、WeiboSpiderを書く過程でも、仕事のプロジェクトでも、コードを削除することは私にとって普通のことになりました.新しい機能が追加される前に再構築される場合があり、ユニットテストのために再構築される場合があります.もちろん黙ってやることが多いのは、再構築の動機が情熱のためだからだ.ご飯を混ぜて食べるプログラマーに対して、私は機能を実現すればいいだけで、コードの「臭い」を排除するのに時間をかける必要はありません.給料も加算されません.ボスにとって、彼がもっと関心を持っているのはプロジェクトの収益とコストで、プログラムの機能を再構築しなくても実現することができて、目的はすでに達成しました.私のテーマで言ったように、再構築はプログラマーの自己修養であり、プログラミングに情熱を持ってこそ、再構築の原動力がある.しかし、私もこのような教養を身近な人に広めたいので、再構築のテーマをチーム内で一度共有したことがありますが、効果はどうなのか、楽しみにしています.
再構築と最適化
        再構築の概念は複雑ではなく,プログラムの動作を変えずにプログラムを改善することである.しかし、再構築は最適化に等しくないことに注意してください.プログラムの入力コンテキストと出力結果を変更することはできないが、再構築の重点はプログラムの可読性、拡張性、プログラム構造の改善にある.最適化の側面は、プログラムのパフォーマンスの改善にあります.この点の違いは,再構成と最適化が同時に行われないことが多い.例えば,再構成の理念では,分割関数が提唱されており,小関数はプログラムの可読性と再利用性を向上させるのに役立つ.しかし、これは最適化において提唱されていない.関数呼び出し時のコンテキスト切替はプログラムの性能に影響を与えるからである(もちろん、現代のコンピュータや現代のコンパイラでは、この性能の影響は無視できる).そのため、コードを修正するときは、今やっていることが再構築なのか最適化なのかを頭の中ではっきり知るべきで、プログラムがどのように変更されるべきかを直接決定します.
再構築とユニットテスト
        再構築は永遠の話題だと言われていますが、私にとってユニットテストこそ永遠の話題です.はい、再構築は依然としてユニットテストに付着しています.再構築には,プログラム入力のコンテキストを変えることも,プログラムの出力結果を変えることもできないことが重要な前提である.多くの場合、再構築ができないのは、私たちがこのプログラムがうまく書けないことを知らないからではなく、怠け者でもないからではなく、コードを修正して新しいバグを導入することを恐れているからです.誰が自分が苦労してバグを修復した後のプログラムを望んでいますか.自分の小さな変更で、実行できませんか.
        そのため、この場合はユニットテストが必要です.1つのテスト例が修正されていない前提で、再構築前に実行でき、再構築後に実行に失敗した場合、この被験プログラムの動作が変更されたことを肯定し、今回の再構築に失敗したことを証明することができる.ユニットテストを実行するコストが低く、ボタンを押すかコマンドを入力すると、プログラムが設定された動作で実行されたかどうかを全方位的に検出できます.速度も速く、プログラムが特に複雑でない限り、数秒か数十秒後に今回の再構築が新しいバグを導入したかどうかを知ることができます.
        ユニットテストは私たちが大胆にプログラムを修正する保証です.プログラマーがしなければならない最も重要なことの一つは、コンピュータで人のエラーを防止し、包容することであり、ユニットテストは私たちが再構築中にミスを犯すことを防止することです.
再構築とコードの読み取り可能性
        コードの可読性は、プログラム設計で繰り返し強調されているが、解決しにくい問題である.可読性はプログラマーレベルだけでなく、プログラマーのビジネス理解にも影響されるからです.例えば変数のネーミングは、人によってネーミングに対する理解が異なるだけでなく、同じ人でもビジネスに対する理解が深まるにつれて、ネーミングスタイルが変化する可能性があります.コードの命名を規範化するために、辞書のような命名規範を指定し、様々なcode reviewやツールでコードを検証するなど、力を入れている会社もありますが、効果はあります.
        再構築は、コードの可読性を向上させるためのツールを提供します.再構築の目的の1つは、コードの可読性を向上させることです.あるいは最初は変数や関数に良い名前をつけることができるとは限らないし、ビジネスに対する理解が深まるにつれて、本当に変数の名前を修正する必要があると思っているのかもしれません.大丈夫です.勇敢に変更してください.コンパイルが必要な言語については、一般的なコンパイラは名前の変更によるエラーを発見するのに役立ちます.解析的な言語では、現代のIDEまたはテキストエディタを使用すると、変数や関数が参照されている場所をすぐに見つけることができます.ユニットテストと組み合わせて、ネーミングを変更しても、追加の作業量は発生しません.
        コード可読性のもう一つの重要な側面は、短いコードブロックである.考えてみてください.百行以上の関数は、書くときは確かに爽やかですが、デバッグやユニットテストを書くときは、キーボードを壊したい衝動に駆られます.1つの長い関数に対して、必ず大小の小さい論理を含んで、これらの小さい論理を小さい関数に分解して、迅速に問題のデバッグを位置決めすることを助けることができるだけではなくて、ユニットのテストの時も比較的簡単な論理に対してユニットのテストを書くことができて、設計の例もそんなに気が狂っていません.
        例を見てみましょう.次のコードは、再構築前のコードです.
void PrintOWing()
{
    double outstanding = 0;

    //print banner
    System.Console.WriteLine("***********************");
    System.Console.WriteLine("*******Custom Owe******");
    System.Console.WriteLine("***********************");

    //calculate outstanding
    foreach (Order item in this.Orders)
    {
        outstanding += item.Amount;
    }

    //print details
    System.Console.WriteLine("name:" + this.Name);
    System.Console.WriteLine("amount" + outstanding);
}
        以上のコードも複雑な長関数とは言えませんが、3つの小さな論理(注釈で区切られた)も含まれています.次に、このコードがどのように再構築されているかを見てみましょう.
void PrintOWing()
{
    PrintBanner();
    PrintDetails(CalculateOutstanding());
}

void PrintBanner()
{
    System.Console.WriteLine("***********************");
    System.Console.WriteLine("*******Custom Owe******");
    System.Console.WriteLine("***********************");
}

void PrintDetails(double outstanding)
{
    System.Console.WriteLine("name:" + this.Name);
    System.Console.WriteLine("amount" + outstanding);
}

double CalculateOutstanding()
{
    double outstanding = 0;
    foreach (Order item in this.Orders)
    {
        outstanding += item.Amount;
    }
    return outstanding;
}
        各小さな論理が小さな関数に分割されていることがわかります.ここでの再構築は,注釈の代わりに関数名を用いるコードを記述するスタイルも体現している.論理が複雑で注釈でその役割を説明する必要がある場合、この論理を関数に抽出し、関数名でこの論理を説明します.小関数を分割するもう一つの明らかな利点は、コードの再利用性を高め、後でいつ、これらの小関数が再利用されるか分からないことです.
        プログラマーにとって基本的なスキルは、大きな問題を小さな問題に分解することです.初めてこのコードを書くときは、長すぎるかもしれませんが、再構築することで、長いコードブロックを短いコードブロックに分割しましょう.