コードの重複は、「しゃれ」の結果である場合があります。2つのことは同じに見えますが、同じではありません。
過剰な抽象化は、システムの真のモジュール性を損なう可能性があります。モジュール方式の下では、「何が変わる可能性があるのか」を判断する必要があります。そして「何が安定しているの?」。安定しているものはすべてインターフェースに入れられ、不安定なものはモジュールの実装にカプセル化されます。その後、物事が変わると、必要な変更はそのモジュールに分離されます。
リファクタリングは、安定していると思われるもの(たとえば、このAPI呼び出しは常に2つの引数を取る)を変更する必要がある場合に必要です。
したがって、これら2つの重複したコードフラグメントについて、一方に必要な変更は、必然的に他方も変更する必要があることを意味しますか?
その質問にどのように答えるかによって、優れた抽象化が何であるかについてのより良い洞察が得られるかもしれません。
デザインパターンも便利なツールです。おそらく、重複したコードが何らかの形式のトラバーサルを行っているため、反復子パターンを適用する必要があります。
複製されたコードに複数の戻り値がある場合(そして、それが単純な抽出メソッドを実行できない理由です)、おそらく戻り値を保持するクラスを作成する必要があります。クラスは、2つのコードフラグメント間で異なる各ポイントに対して抽象メソッドを呼び出すことができます。次に、クラスの具体的な実装を2つ作成します。各フラグメントに1つです。[これは事実上、テンプレートメソッドのデザインパターンであり、C ++のテンプレートの概念と混同しないでください。あるいは、あなたが見ているものは、Strategyパターンでより良く解決されるかもしれません。]
それについて考える別の自然で便利な方法は、高階関数を使用することです。たとえば、ラムダを作成するか、コードが抽象化に渡す匿名内部クラスを使用します。一般に、重複を削除することはできますが、実際にそれらの間に関係がない限り(一方が変更され、他方が変更される必要がある場合)、モジュール性を損なう可能性があります。