コードの繰り返しと複数の責任がある方法


11

私は単一責任原則(SRP)に準拠し、コードの繰り返しを省略しようとします。しかし、少なくとも意味のある名前付きメソッドへの抽出に抵抗する呼び出しのコードブロックにすぎないコードの繰り返しがある場所がしばしばあります。

DoAction1();
DoAction2();

if (value)
    DoAction3();

DoAction4();

そのようなコードをメソッドに抽出する最良の方法とその命名方法は何ですか?


1
別の意味のある方法に抽出されることに抵抗するのはなぜですか?
Chandranshu

すべてのアクションは無関係なことをします。次のように書く必要がありますvoid MethodThatDoAction1ThenAction2AndAction3IfValueAndThenAction4()。私はむしろ、より意味を参照してくださいになりますCodeBlock1()
yBee

4
それは、抽出されたメソッドに適切に名前を付けるという問題に過ぎませんか?普遍的な解決策はないので、ケースバイケースでこれを行う必要があります。このまったく同じコードを複数の場所で繰り返している場合、アクションには意味があるはずです。その意味を見つけて名前を付けるには、一生懸命(議論するかもしれません)見る必要があります。
Chandranshu

1
それが慰めである場合、長いクラス名のSpringの勝者AbstractInterruptibleBatchPreparedStatementSetterはあなたのメソッドより少し小さいだけです。
Chandranshu

1
@Chandranshuあなたのコメントは、この質問に対する答えとしてうまくいくと思います。
サイモンフォースバーグ

回答:


13

これは、抽出されたメソッドに適切に名前を付けることの問題に過ぎないと思います。普遍的な解決策はないので、ケースバイケースでこれを行う必要があります。このまったく同じコードを複数の場所で繰り返している場合、アクションには意味があるはずです。その意味を見つけて名前を付けるには、一生懸命(議論するかもしれません)見る必要があります。

慰めの場合、長いクラス名のSpringの勝者AbstractInterruptibleBatchPreparedStatementSetterは49文字です。


11

実際にあなたが苦しんでいるプログラマが行うことを最も難しいトップタスク - 物事を命名します。そのような未熟な答えで申し訳ありませんが、私は抵抗できませんでした。あなたはそれを見つけることができる多くの人々は、この苦しむでもインターネットにあなたがすることができ、エッセイのこのタイプを見つけます

繰り返しコードがすべて1つの作業の結果であり、それらのメソッドが他のメソッドで使用されていない場合、それらは単にヘルパーメソッドであり、結果のメソッドの名前は... doXXXまたはmakeXXX...になると思います。

以下のようChandranshuは言った、「あなたが[...]これを繰り返すことを意味し、名前を付けている場合。」ポイントに適切です。

ここに画像の説明を入力してください

写真提供:CodeChef Facebookページの写真


2

あなたはコードの繰り返しの原則を取りすぎていると思います。コードの重複を避ける点を考えてください。ポイントは、ロジックに変更がある場合にチェックする必要のあるコードの量を減らし、明らかに同様に意図されているブロックを除外することで理解度を高めることです。

繰り返しを回避するためのファクタリングの欠点は、共有ブロックの1つを変更する必要がある場合、さらに複雑な継承または標準実装と非標準実装の切り替えが必要になることです。

したがって、これらのブロックの1つでも、他のブロックなしでロジック変化する可能性と、この共通性を除外することで得られる理解の利点を慎重に比較検討してください。ある実装が他の実装から分割される可能性がある場合は、単にコードを繰り返すだけの方が良いでしょう。

それはより複雑になり、あなたの問題領域は、より定義さになると、この繰り返しのコードを維持しながら、あなたは、今より複雑な、繰り返したが、要因にそれがより適切かもしれませんまた、より多くの定義されたセクションアウト。

私は通常、テキストエディタの同一性をしばらくの間、繰り返しているように見えるものがファクタリングする価値があるかどうかがわかるまで維持しようとします。私は繰り返しを繰り返しますが、後で一致させるためにテキストで簡単に保つことで、そのブロックの将来に目を光らせています。

多くの時間、同一性、可能性のあるファクタリングが、現実的で気まぐれなビジネスルールや、非常に依存性の高い、しばしば任意のロジックとして散逸し始めます。いくつかの一般的なデータベース実装(ANSI_NULLSまたはそのようなものが思い浮かぶ)の奇妙なことに対処するようなものが追加されます。純粋なロジックのように見えるものをねじれた混乱に押し込み、業界の混乱に直面したときに合理的で防御可能な決定ロジックを提供しようとします。

あなたがファクタリングしようとしているものを人々がファクタリングしようとすると、Do1Then2If2False Do1IfTrueDo2のような価値のない構成要素のライブラリ全体が得られるように思えます。

より複雑で明確にする必要があるのは、ブロックを変更することを保証するためにブロックが変更されないことです。

それはソフトウェアです。戻って、現在同じブロックを編集できます。5分かかります。そして、無駄なファクタリングの時間を節約し、それから、何時間も無駄な継承と切り替え開発を節約することができます。


コードの繰り返しの本質を抽出する部分が好きです。ロジックに変更がある場合にチェックする必要があるコードの量を減らすために
-yBee

1

単一責任原則を真に遵守している場合、このコードブロックには特定の目的が必要です。そうでなければ、これらのメソッドは別々のクラスになります。

それでは、このコードブロックの目的は何ですか?それを決めれば、あなたは名前を思い付くことができるはずです。

それでもこの名前がわからない場合は、これらのメソッドが実際にはまったく属していない可能性があります。つまり、このクラス/コードブロックには複数の責任があります。その場合、タスクを分割するためにリファクタリングを行うと、目的を明らかにするより適切な名前が明らかになる場合があります。


1

私はあなたのものに似ているかもしれない状況がありました:

表すオブジェクトの機能を定義するクラスがあります:

class Functionality
{
protected:
void functionA();
void functionB();
...
void functionZ();
}

次に、オブジェクトが実行する高レベルの操作のワークフローを定義するクラスがあります。

class Workflows: private Functionality
{
    void WorkflowA()
    {
        functionA();

        if (m_bValue) {
            functionB();
        }

        functionC();
    }
    ...
    void WorkflowB();
}

あなたが似たような状況にいる場合は、特定どのようなあなたのクラスは(この場合は機能/ワークフロー)を表し、それに応じてメソッドに名前を付けます。

免責事項:この例で使用されているクラス名は非常に不正確ですが、メソッド名からヒントが得られます。裁量をお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.