Cコードのリファクタリング


どのくらいの頻度でコードをクリーンアップしますか?コードのリファクタリングとは何か分からない場合は、既存のコードを変更して、既存の機能を変更することなく、柔軟で、保守性があり、拡張可能にするためのプロセスです.

リファクタリングのコードはなぜですか?


コードのリファクタリングを必要とする理由を説明するのは簡単です.以下の例はAnimal 機能を持つクラスAnimalType パラメータとして.あなたが通るならばAnimalType.Cat , それはあなたを返しますMiao そして、犬に同じ.
public class Animal {
    public string Sound(AnimalType animalType) {
        if (animalType == AnimalType.Cat) {
            return "Miao";
        } else if (animalType == AnimalType.Dog) {
            return "Woof";
        }
        return "";
    }
}
それで、この問題は何ですかclass ?
私がこのクラスに10以上の動物の音を加える必要があるならば、私は10 if文を書く必要があります.下記の例のように.
public class Animal {
    public string Sound(AnimalType animalType) {
        if (animalType == AnimalType.Cat) {
            return "Miao";
        } else if (animalType == AnimalType.Dog) {
            return "Woof";
        } else if (animalType == AnimalType.Bird) {
            return "Chick";
        } // else if () x 7 more...
        return "";
    }
}
あなたは、機能が膨らまれるようになるか、一部の人々がそれを呼ぶと理解しますfat function . あなたは考えるかもしれません:OK、それはちょうど機能です、そして、私はそれを広げている問題を見つけません.私は、ちょうど加え続けなければなりませんelse-if ステートメントと魅力のように動作します.
この関数が小さいときは、おそらく正しいでしょう.関数が音の上に100を加えられたあと、何をすれば、別の関数を実装するように言われますFly ? どのように新しい機能を処理するつもりですか?書くif 声明どのようにして、別の動物のための実装も正しく実行されている別の方法を実行している動物の種類を欠場しないことを確認ですか?
public class Animal {
    public string Sound(AnimalType animalType) {
        // sound implementation
    }

    public void Fly(AnimalType animalType) {
        if (animalType == AnimalType.Cat || animalType == AnimalType.Dog) { 
            // this if statement might go wrong, because not every animal can fly.
            throw new InvalidOperationException("This animal cannot fly!!");
        } else if (animalType == AnimalType.Bird) {
            // fly implementation
        } 
    }
}
だから、上記の実装は持続可能ではない.まず、上記の実装は読みにくいです.私が方法を変えるために動物タイプを見つけることになっているならばsound , 私は、あまりにも多くのため、単に検索するより多くの時間を取る必要がありますif 文.新しい動物の種類を削除または追加するために行く.
上記の実装については、抽象を作成することによってより良い操作を行うことができますanimal オーバーライドしなければならないクラスSound 関数.追加abstract を防ぐクラスにAnimal インスタンス化されたクラスです.同時に、あなたは動物のクラスをSound 関数は、まだ実装していない任意の動物の種類を見逃すことはありませんSound 関数.そうすることによって、あなたのクラスは、スリッカー、シンナー、読みやすくなります.
public abstract class Animal {
    public abstract string Sound();
}

public class Cat: Animal {
    public override string Sound() {
        return "Miao";
    }
}

public class Dog: Animal {
    public override string Sound() {
        return "Woof";
    }
}

// same for the rest of the animals

このような質問があるかもしれませんが、動物の種類を使用して動物の音を取得したいと思います.そうでなければ、if 再び宣言して、動物クラスをコード化してください、そして、コードは至る所で複製されます.
あなたは正しい、我々はまだ使用する必要がありますif クラスをインスタンス化するステートメント.しかし、我々はsimple factory design pattern 実装をカプセル化する.
public class AnimalFactory {
    public static Create(AnimalType animalType) {
        if (animalType = AnimalType.Cat) return new Cat();
        if (animalType = AnimalType.Dog) return new Dog();
        // implementation for other animals...
        throw new InvalidOperationException("Invalid animal type!");
    }
}

// usage
Animal cat = AnimalFactory.Create(AnimalType.Cat);
cat.Sound(); // Miao
あなたはおそらく尋ねるでしょうFly 関数.すべての動物は、右飛ぶことができますか?
すべての動物が飛ぶことができないので、あなたは正しいですFly すべての動物への機能.それ以外の場合は、100種類の動物を持っている場合は、100倍の機能を実装する必要があります.あなたはおそらくIFlyableAnimal . このアイデアはSOLID principle - Interface Segregation Principle . 以下の例を参照ください.
public interface IFlyableAnimal {
    void Fly();
}

public class Bird: Animal, IFlyableAnimal {
    public override string Sound() {
        return "Chick";
    }

    public void Fly() {
        // some fly implementation
    }
}

// usage
Animal bird = AnimalFactory.Create(AnimalType.Bird);
bird.Sound(); // Chick
if (bird is IFlyableAnimal) {
    bird.Fly();
}
上の例を見て、クラスは薄くなり、拡張可能になります.我々が作成する必要があるときはいつでもAnimalType , 我々は抽象を拡張しなければならないAnimal クラスと動物がflableであるならば、我々はちょうどIFlyableAnimall インターフェイス.開発者が関数を実装していない場合、コンパイラはエラーを表示します.このデザインでは、我々はSOLID principle - open-close concept .

いつあなたのコードをリファクタリングするべきですか?


あなたのコードをリファクタリングする最良の時間は、おそらく機能を書くことを終えた直後です.あなたのピアとコードのレビューセッションを持って、あなたのコードを構造化するための最良の方法を議論する.
ただし、常にコードのリファクタリングを行うには、適切な実装の後にする必要はありません.QAはあなたの実装を待っています、そして、製品オーナーはあなたがあなたのコードをリファクタリングするために余分な時間を得るのを許しません、なぜならば、あなたは与えられた時間であなたの実現を提供する必要があるので.
でも大丈夫.コードの同じ部分に再び機能を強化するように言われたときに、コードリファクタリングを行うことができます.そこから、現在のコードベースにコードリファクタリングを必要とすることを伝えることによって、製品の所有者からより多くの時間を要求することができます、したがって、より多くの時間が必要です.

結論


コードのリファクタリングの練習は、あなたやあなたのチームの利点のカップルをもたらします.それらのうちの1つはコードがきれいで、読みやすくなるでしょう.次の開発者は、コードの同じ部分で華麗な機能を強化するように言われている場合、それが拡張可能であるため、開発は容易になります.同時に、開発速度がはるかに速くなります.
一方、コードが必要なときにリファクタリングされていない場合は、次の開発者は、コードを読んで苦しんでいる、より多くの時間を読んで、単純な強化を強化する結果になります.悪いことになると、コードが持続可能でないので、あなたはそこで、そして、そこで誤りを見つけるでしょう.

言い方がある

The true professional knows that delivering function at the expense of structure is a fool’s errand. It is the structure of your code that allows it to be flexible.

If you compromise the structure, you compromise the future.
The fundamental assumption underlying all software projects is that software is easy to change. If you violate this assumption by creating inflexible structures, then you undercut the economic model that the entire industry is based on.

In short: You must be able to make changes without exorbitant costs.

~ The clean coder by Robert C. Martin


幸せなコーディングと幸せな学習😆