小さな繰り返しコードセグメントの関数/メソッドを作成するときの適切なコードプラクティスは何ですか?


12

大規模なプログラムの作成中に何度も、コピーまたは貼り付けの回数を関数またはメソッドにコードを入れるのが理にかなっていて、良い経験則は何かを疑問視しています。私は4行以上の経験則を使用しており、2回以上表示され、そのコードを含む単純な関数/メソッドを作成します。より良いプラクティスを考えたり、何か指針を提供できますか?これは、言語固有の質問というよりも、一般的なデザインパターンの質問です。

回答:


29

コードを文書化する方法として、関数を部分的に使用します。意味のある名前で関数を呼び出すと、コードを理解しやすくなります。場合によっては、1行の関数でさえ理にかなっています。

たとえば、「クリーンコード」では、Robert C. Martinが次の例を示しています。この:

// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
    (employee.age > 65))

それともこれ?

if (employee.isEligibleForFullBenefits())

私はいつも彼に同意するとは限りませんが、この場合は同意します。コードは、それを書いてすべての詳細を知っているときだけでなく、他の人のコードのバグを修正する必要がある午後9時にも読み取り可能であるべきです。長い状態をじっと見つめ、二重のネガをすべて理解しようとすることはお勧めしません。名前を付けるだけでよい場合(条件だけでなく、作成するすべてのコードも)、より簡単になります。

関数に何かを置くことを後悔したことはありません。パフォーマンスが心配な場合は、最初にプロファイルを作成してください。


2
この簡単なプラクティスに従うことで、最終的には比較的高いレベルでアプリケーションコードを記述できるようになります。小さな関数は小さなクラスに集められ、すぐに機能仕様をほぼ単語ごとのコードに変換しています。
ケビンクライン

11
私はこの例を気に入りました。突然、そのコメントはもう必要ありません。これは経験則です。コメントを変数または関数名に変換できる場合は、実行してください!
カロリーHorvath

私はここでomribに同意します。多くの場合、コードをクリーンアップすることです-他の経験則よりも読みやすくします。最終的に何かを再利用することになった場合は、メソッドに抽出します。しかし、私のIDEとツールはしばしばそれを助けてくれるので、それは簡単で迅速です。
トラビス

+1この種のコードは、少なくともJITで処理する必要がある場合は、さらに高速になる可能性があります。使用した分に対してのみ支払います。
仕事

1
Intention Revealing Namesとしても知られています。
-rwong

13

関数呼び出しは、コードセグメントの繰り返しを避けるためにのみ行うべきであるという誤解が広まっています。私の経験則では、1つの場所でしか使用されない場合でも、論理的な作業単位は関数にする必要があります。これにより、通常、読みやすさが向上し、自己文書化コードを記述できます。この場合、関数名がコメントに置き換わり、実行内容を説明する追加のコメントを記述する必要がなくなります。


1
コメントを書くことを避けるためにプログラマーがどのくらいの長さになるのか見てみましょう。
アルガー

1
@Alger彼らがすべき
MatrixFrog

6

それは以上で使われている場合は1位、および

  • 変更される可能性が高い、または
  • 正しくするのは難しい

それを関数またはメソッドにします。私の経験では、繰り返されるコードの長い断片は、これらのカテゴリのいずれかに自然に分類されます(通常は最初のカテゴリですが、カテゴリはかなり重なっています;)。もちろん、インターフェイスにある必要があるものはすべて、それ自体が関数/メソッドでもあります。


3
問題は、正しく取得するのが難しい場合や、変更する可能性が低い場合でも、よく繰り返されるコードの一部の関数を作成しないのはなぜですか?(私の経験則:繰り返し、関数を呼び出すよりも長い場合は、それを関数にします)
ウィンストンエワート

さらに先に進みます。プログラマーとして、あらゆる種類の繰り返しを排除する必要があります。データベースにあるか(正規化)、いくつかの手動テスト(単体テストに置き換える)、または展開(自動化)です。
カロリーHorvath

@Winston:それは使用されている言語に依存します。すべてのコンストラクトが関数として自然にキャプチャできるわけではありません。関数は元のコードよりも多くのスペースを使用する可能性があり(Cを考え、ポインターで返す)、関数呼び出しにオーバーヘッドが発生する場合があります。
フレッドフー

@larsman、「(Cを考えてポインターで戻る)」という言葉に興味があります。しかし、あなたが言っているのは、私の経験則で私がやろうとしていたことです。関数の呼び出しは、関数のコンテンツを実装するよりも簡単でなければなりません(つまり、自然にキャプチャしてスペースを取りません)。
ウィンストンユワート

コードの一部が複数の値、たとえばfloat xint yおよびを計算する場合、double densityこれらの計算をC関数として設定することは、3つの値すべてを取得する方法を考案する必要があるため、単にコードを繰り返すより難しい場合があります。繰り返し計算自体が簡単な場合は、インラインのままにしておく方が良い場合があります。
フレッドフー

4

ほとんどの場合、特に各重複が概念的な観点から同じ操作を表す場合。同じ方法で、ただしタイプが異なる場合は、一般的な実装を行います。

私が考えることができない唯一の理由は、メンテナンスの1つです:時には、いくつかの複製を犠牲にしても、別々のものの間で依存関係を作成することを避ける方が便利かもしれません。


のところ実装が似ているが機能が事実上異なる場合、アヒルのタイピングに注意してください。2つをマージすると、元に戻すのが面倒になります。特にIDEのサポートが不十分な言語では(ちょっと、私はC ++で作業しています...)
Matthieu M.

一方、それらを別々に保つことにより、テストする同じことを行う2つの関数、コードが実行される可能性の半分、同じバグが忍び寄る2つの場所があり、その中の1つを修正することを忘れないでくださいバグはまだ検出されていません。私はまだC ++で仕事をしたいと思っていますが、IDEのサポートは貧弱ですが;
ニコラムサッティ

1

リファクタリング」を検索すると、この非常に一般的なプロセスの業界の「ベストプラクティス」に関する多くのリソースにアクセスできます。幾分有名な記事、Once and Only Onceは、あなたの質問によって提起された懸念に対する「ベストプラクティス」と考えるものを説明する素晴らしい歴史的参考資料です。また、さらに一般的な概念は、Do n't Repeat Yourself(DRY)として知られています。あなたの質問への回答の実際の深いセットの場合は、読みMartin Fowler氏の偉大な古典的、リファクタリング:既存のコードのデザインの向上のために最もよく知られているアドバイスのいくつかをカバーし、リファクタリングあなたが直感的に達成しようとしているものであるが、 !


0

コードが複数回正確に繰り返され、近い将来に繰り返されるセクションが変更されない場合は、関数に分割します。


1
変更される場合は、リファクタリングするさらに多くの理由があります。その後、変更する必要があるのは一度だけです
11

0

それは、繰り返されるコードの凝集度の性質に依存します。コードの繰り返し区間が特定の機能を実行している場合、それは一部のための、方法になされているため優れた候補であるDRY原則機能が最適化または修正する必要がある場合、1つだけのセクションがあり、部分的にので、対処するコードの。

関連付けが偶然の場合は、コードをメソッドにするよりも、コードを繰り返す方が適切です。そのスニペットの使用の1つを満たすためにコードシーケンスの1つに何かを追加する必要がある場合、それがメソッド内にある場合、変更はそのメソッドの他の使用に影響する可能性があります。

コード結合の概念に関するウィキペディアの記事を参照してください。


関連付けが偶然に見える場合、2つのプロセスが共通のアイデアを共有している可能性が高いため、2つのプロセスが実際に同じものの2つの側面であるかどうかを検討する必要があります。多くの場合、そうです。
ライライアン

0

構造化プログラミングの意味での関数とクラスのメソッドを区別する必要があります。

あなたの例では、インラインでコーディングすべきではないメソッドが示されています。

文字列が数値であるかどうかを確認するために文字列を検証する必要がある場合があります。この場合、関数を使用すると、前述の回答のほとんどが適用されます。

この区別は、特に大規模プロジェクトでは重要です。

できる限り、コンピューティングアルゴリズム(純粋なプログラミング関数)からビジネスルール(メソッド)を分離するよう努めてください。

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