2011-10-25 9 views
3

既存の機能に遭遇した場合はほとんどあなたはそれがベストプラクティスです必要なものないこと、既存のシステムに新しい機能を追加する場合:既存の機能が再利用、既存の機能

  • コピーして変更を行います(コードをコピーするとあなたの仲間が泣くのを知っている)。

- または -

  • 編集します(QAチームの叫びを作る)システムの既存の部分に新しいバグを導入することができることを危険にさらす既存のケースとあなたの新しいケースの両方を処理するための既存の機能
    • (コピーに基づいて)新しい独立した関数を作成する前に、既存の関数を編集する場合は、次のようにします。関数の10%、関数の50%?
+2

関数が複雑で、関数の10%しか変更できない場合は、それをリファクタリングする必要があります。 –

+1

理想的には、既存の機能を壊さずに自信を持って修正できる十分なテストがあることです。だから、ここで質問することさえあるという事実は、テストが本当に十分ではないと前提しています。答えは、「私たちはテストをしています。私たちが好きなこと全てをやる時間がない "、"ぞっとする "。 –

答えて

2

私は、既存の関数に余分なパラメータ(または新しい有効な値)を追加することで新しい動作をカバーすることができますが、コードを多かれ少なかれ "明らかに同じ"既存のケースでは、関数を変更することにそれほど大きな危険はありません。例えば

、古いコード:

def utf8len(s): 
    return len(s.encode('utf8')) # or maybe something more memory-efficient 

新しいユースケース - 私はnullオブジェクトパターンを使用したスタイルでいくつかのコードを書いているので、私はutf8len(None)が例外をスローするのではなくNoneを返すようにしたいです。そう、私は新しい機能utf8len_nullobjectpatternを定義することができ、それは非常に迅速非常に迷惑を得るために起こっている:

def utf8len(s): 
    if s != None: 
     return len(s.encode('utf8')) # old code path is untouched 
    else: 
     return None # new code path introduced 

を次にutf8lenためのユニットテストが不完全であったとしても、私は私がのために行動を変更していないことを賭けることができますNone以外の入力。また、誰もutf8lenに頼ってNone入力の例外をスローしていないことを確認する必要があります。これは、(1)ドキュメンテーションやテストの質の問題です。 (2)人々が実際に定義されたインターフェースに注意を払うのか、それとも単にソースを使うのか。後者の場合、私はサイトを呼び出す必要がありますが、物事がうまくいけば、私はほとんどしません。

許可された古い入力が「明らかに同じ」と扱われるかどうかは、修正されるコードの割合は実際には問題ではありません。古い関数本体の全体が表示されているので、私は意図的に簡単な例を選んだが、それを見たときに知っていると思う。もう1つの例は、固定の値を提供するだけのデフォルトのパラメータを使用して設定可能なものを作成する(おそらく、値を取得するために使用された値または依存関係を渡すことによって)ものです。古い固定されたもののすべてのインスタンスは、新しいパラメータに置き換えられます(そのため、変更が何を意味するのかをdiffで確認するのはかなり簡単です)。少なくとものテストでは、あなたが愚かな誤植で古い入力を壊していないことを確信しているので、テストカバレッジに全面的な信頼を置かなくても前進することができます。

もちろん、包括的なテストが必要ですが、必ずしもそうであるとは限りません。また、2つの競合するメンテナンス命令があります。1 - コードを重複しないでください。バグがある場合、または将来変更する必要がある場合、バグ/現在の動作が重複しているためです。 2 - オープン/クローズドの原則は、少し高めですが、基本的には「働くものを書いてそれに触れないでください」と言います。 1は、これら2つの同様の操作の間でコードを共有するようにリファクタリングする必要があると言います.2はいいえ、あなたは古いものを出荷しました。この新しいものに使用可能かどうか、 。

1

あなたは常にコードの重複を避けるために努力すべきです。したがって、あなたは、あなたの新しい機能を実装するために既に存在する関数の戻り値を変更する新しい関数を書くことをお勧めします。

私は、それを行うことができない場合があることを認識しています。そのような場合は、インターフェイスを変更せずに既存の関数を書き直すことを検討する必要があります。そして、とすることによって、新しい機能のバグを導入するには、の前に、変更された関数で実行できる単体テストを防ぐ必要があります。

既存の関数の一部だけが必要な場合は、既存の関数から新しい関数を抽出し、既存の関数と新しい関数でこの新しい "ヘルパー"関数を使用することを検討してください。再びすべてを確認することは、単体テストを介して意図したとおりに動作しています。

3

これはいつでも行うことはできませんが、既存の機能を他の小さな部分に分割して、すべてのコードを編集せずに必要な部分を使用できるようにし、小さな部分を編集しやすくしますコードの

システムの既存の部分に気づかずに新しいバグを導入できると思うなら、おそらくユニットテストの使用を考えるべきです。

関連する問題