4

いくつかのことを行うクラスのパブリックメンバー関数を書くとき..

void Level::RunLogic(...);

その関数では、いくつかのプライベート メンバー関数に分割していることに気付きました。パブリックメンバー関数をいくつかの関数に分割しても意味がありません。なぜなら、あることを別のことなしに行うことはできず、ユーザーが何をどの順序で行うかなどを心配したくないからです。むしろ、RunLogic() 関数はこのようなものに見えます...

void Level::RunLogic(...) {
 DoFirstThing();
 DoSecondThing();
 DoThirdThing();
}

DoThing 関数はプライベート メンバー関数です。Code Complete で、Steve McConnel は、クラスに含める関数の数を減らすことを推奨していますが、私はむしろ、すべてのコードを 1 つの関数に入れることはしたくありません。彼の本当の意味についての私の仮定は、クラスはあまり機能的であってはならないということですが、これに関して他のプログラマーがどう考えているのか気になります。

さらに、パブリック メンバー関数で公開する実装の詳細を徐々に減らし、ほとんどの作業を小さなプライベート メンバー関数に移す方向に進んでいます。明らかに、これによりより多くの機能が作成されます...しかし、問題はそこにあります。

4

7 に答える 7

2

パブリック メソッドをシンプルに保ち、その機能を複数のプライベート メソッドに分割したいのは当然です。

クラスに保持するメソッドの数を減らすべきだという McConnell の意見は正しいです。

これらの 2 つの目標は実際には相反するものではありません。McConnell が、関数の数を減らすために関数を長くすることを主張するとは思いません。むしろ、これらのプライベート メソッドの一部を、パブリック クラスで使用できる 1 つ以上のユーティリティ クラスにプッシュすることを検討する必要があります。

もちろん、これを達成するための最良の方法は、コードの詳細によって異なります。

于 2009-12-17T02:23:07.310 に答える
1

これらを個別のメソッドに分割することをお勧めします。各メソッドは 1 つの小さなタスクを処理し、プライベート メソッドごとに説明を付けます。メソッドとメソッド名を分割すると、ロジック コードが読みやすくなります。比較:

double average(double[] numbers) {
  double sum = 0;
  for (double n : numbers) {
    sum += n;
  }
  return sum / numbers.length;
}

に:

double sum(double[] numbers) {
  double sum = 0;
  for (double n : numbers) sum += n;
  return sum;
}

double average(double[] numbers) {
    return sum(numbers) / numbers.length;
}

Code Complete は、実装ではなく、各クラスが公開するインターフェイスに対処します。

複雑な RunLogic のみをテストできる代わりに、これらの小さなメソッドをパッケージで保護して簡単に単体テストできるようにする方が理にかなっている場合があります。

于 2009-12-17T02:16:45.950 に答える
1

機能を分割することに同意します。

私は常に、関数は単一のカプセル化されたタスクを実行するように定義されているという知識に固執してきました。複数のことを実行しているように見える場合は、それをリファクタリングすることが可能かもしれません。次に、類似または関連する機能をまとめてカプセル化するクラス。

私の意見では、これらのタスクを分割し、単一の public メンバーを使用することで、クラスはその重要なタスクを意図したとおりに実行できると同時に、保守が容易になります。また、同じ複雑なメソッド内に複数の同様のコード セクションがあり、それらをパラメーターを使用して単一の汎用関数にリファクタリングできることもよくあります。これにより、読みやすさと保守性の両方が向上します。コード量も削減できます。

于 2009-12-17T02:26:05.490 に答える
0

特にパブリックメンバー関数をできるだけ小さくすることの利点はわかりません(コード行で測定)。一般に、長い関数は読みにくくなる傾向があるため、ほとんどの場合、大きな関数の実装を広めると、クラスの一部であるかどうかに関係なく、読みやすさが向上します。

クラスをできるだけ小さく保つという良いアドバイスについて言えば、これはインターフェイスの公開部分とカプセル化されたデータの量にとって特に重要です。その理由は、多くのデータ メンバーとパブリック関数を持つクラスは、データ カプセル化の利点を台無しにするためです。

于 2009-12-17T08:07:57.880 に答える
0

私が使用するルールの 1 つは、3 つのルールです。同じことを別の場所で 3 回行っている場合は、その共有動作をカプセル化する別の (おそらくプライベートな) メンバー関数を用意する価値があります。

この状況で私が一般的に使用する唯一の他のルールは、読みやすさです。IDE で全画面表示以上のメンバー関数を見ていると、すべてのコード パスと間違った方向を追跡するのが難しくなります。その場合、1 つのモノリシック メンバー関数を 2 つ以上のプライベート ヘルパー関数に分割することは完全に合理的です。

クラス内の関数の数に関する Code Complete のコメントについては、関数の数に関連する最大のリスクは、主に外部から使用できるインターフェイスの複雑さに関連していることを思い出してください。他の人が作業するためのエントリ ポイントを多く提供すればするほど、何か問題が発生する可能性が高くなります (たとえば、パブリック メンバーの 1 つのバグ、間違った入力などが原因で)。プライベート メンバー関数を追加しても、パブリック API の複雑さは増しません。

于 2009-12-17T02:15:38.227 に答える
0

私が使用する「経験則」は、一度に 1 つの機能が画面全体のスペースを超えることはないということです。かなり単純な考え方ですが、一度に 1 つの画面で「すべてを取得」できると役立ちます。また、(定義により) 1 つのメソッドの複雑さも制限されます。さらなるメンテナンス、アップグレード、およびバグ修正 (!) のために作業を同僚に引き渡すことが期待される場合、作業をシンプルに保つことは良いことです。それを念頭に置いて、パブリック メソッドをシンプルに保つことがほとんどの場合正しい選択であることに同意します。

于 2010-01-19T13:07:35.977 に答える
0

あなたは意図せずに ff ルールに従っています:

A class should have only one reason to change / Single responsibility principle

これは良いことです。責任を適切に分離することで、アプリが簡単に壊れないようにすることができます。change

于 2009-12-17T02:22:56.653 に答える