質問

私は長年の開発者(私は49歳)ですが、オブジェクト指向の開発は初めてです。バートランド・マイヤーのエッフェル以来、私はOOについて読んでいますが、OOプログラミングはほとんどありませんでした。

ポイントは、OOデザインに関するすべての本が、ボート、車、または私たちが非常に頻繁に使用するあらゆる一般的なオブジェクトの例から始まり、属性と方法を追加し、オブジェクトの状態をどのようにモデル化し、何ができるかを説明し始めます。それ。

したがって、彼らは通常、「モデルがより良いほど、アプリケーションのオブジェクトをより良く表し、すべてが出てくる」ようなものになります。

これまでのところ良いことですが、一方で、「クラスは単一のページに適合する必要がある」などのレシピを提供する著者を見つけました(「モニターサイズに」を追加します。コードを印刷するために!)。

たとえば、 PurchaseOrder クラス、それはその動作とのコレクションを制御する有限状態マシンを持っています PurchaseOrderItem, 、ここで働いている議論の1つは、 PurchaseOrder いくつかの方法(データクラス以外)を備えた単純なクラス、そして PurchaseOrderFSM のための有限状態マシンを処理する「エキスパートクラス」 PurchaseOrder.

ジェフ・アトウッドの「特徴のvy望」または「不適切な親密さ」の分類に落ちると思います コードの匂い コーディングホラーに投稿してください。私はそれを常識と呼んでいます。実際の発注書を発行、承認、またはキャンセルできる場合は、 PurchaseOrder クラスが必要です issuePO, approvePOcancelPO 方法。

それは、私がOOの礎石として理解している「結束を最大化」し、「結合を最小化する」年齢の原則にも当てはまりませんか?

その上、それはクラスの保守性に役立ちませんか?

役に立ちましたか?

解決

クラスは、単一の責任原則を使用する必要があります。私が見たほとんどの非常に大きなクラスは、多くのことをしているので、それらが大きすぎます。各メソッドを見て、コードはこのクラスまたは個別の重複コードがヒントである場合に決定します。 ISSUEPOメソッドがあるかもしれませんが、たとえば10行のデータアクセスコードが含まれていますか?そのコードはおそらくそこにあるべきではありません。

他のヒント

私の意見では、変数、関数、および方法が問題のクラスに関連している限り、クラスのサイズは重要ではありません。

大規模なクラスの最大の問題は、それらのクラスをテストすること、または他のクラスとの相互作用をテストすることです。クラスのサイズが大きいだけではありませんが、すべての匂いのように、 潜在的な 問題。一般的に言えば、クラスが大きい場合、それはクラスが単一のクラスを超えていることを示していることを示しています。

あなたの車のアナロジーのために、クラスの場合 car 大きすぎる、それはおそらくそれがクラスに分割する必要があることを示していることです engine, 、 クラス doorS、およびクラス windshieldSなど

クラスが大きすぎるという特定の定義はないと思います。ただし、次のガイドラインを使用して、クラスをリファクタリングするか、クラスの範囲を再定義する必要があるかを判断します。

  1. 互いに独立した多くの変数はありますか? (ほとんどの場合、私の個人的な寛容は約10〜20です)
  2. コーナーケース用に設計された多くの方法はありますか? (私の個人的な寛容は...まあ、それは私の気分に大きく依存します)

1に関しては、クラス内のフロントガラスのサイズ、ホイールサイズ、テール電球モデル、その他100の詳細を定義することを想像してください car 。それらはすべて車に「関連性がある」ものですが、そのようなクラスの動作を追跡することは非常に困難です car. 。そして、いつかあなたの同僚が誤って(または、場合によっては意図的に)テール電球モデルに基づいてフロントガラスのサイズを変更するとき、フロントガラスがあなたの車にもはや適合しない理由を知るには永遠にあなたが必要です。

2に関しては、車がクラスで持っている可能性のあるすべての動作を定義しようとすることを想像してください car, 、 しかし car::open_roof() コンバーチブルでのみ利用できます car::open_rear_door() これらの2ドア車には適用されません。コンバーチブルと2ドア車は定義上「車」ですが、クラスでそれらを実装しています car クラスを複雑にします。クラスは使用が難しく、維持が難しくなります。

これら2つのガイドライン以外に、クラスの範囲の明確な定義を提案します。スコープを定義したら、定義に基づいて厳密にクラスを実装します。ほとんどの場合、人々は範囲の定義が悪いため、またはクラスに追加された任意の機能のために「大きすぎる」クラスを取得します

300行で必要なものを言います

注:この経験則は、あなたがそれ自体が良い保守性のアイデアである「ファイルごとの1つのクラス」アプローチに従っていると仮定しています

それは絶対的なルールではありませんが、1つのクラスに200以上のコードが表示されている場合、疑わしいです。 300ラインと警告ベルが点灯します。他の誰かのコードを開いて2000行を見つけると、最初のページを読むことなく時間を取り戻すことができます。

主にこれは保守性に帰着します。オブジェクトが非常に複雑で、300行で動作を表現できない場合、他の誰かが理解することは非常に困難になります。

このルールをモデルで曲げていることがわかっています - > viewmodel-> view> view where uiページの「動作オブジェクト」を作成しているのは、多くの場合、完全な一連の動作を記述するのに300行以上が必要なためページ。しかし、私はまだこのプログラミングモデルに慣れておらず、ページ/ビューモデル間で動作をリファクタリング/再利用する適切な方法を見つけて、ビューモデルのサイズを徐々に減らしています。

後方に進みましょう:

それは、私がOOの礎石として理解している「結束を最大化」し、「結合を最小化する」年齢の原則にも当てはまりませんか?

実際、それはプログラミングの基礎であり、OOは1つのパラダイムにすぎません。

させます アントワーヌ・ド・サン・エクスペリー あなたの質問に答えます(私は怠け者だからです;)):

追加するものが何もないときではなく、奪うものが残っていないときに完璧が達成されます。

クラスが簡単になればなるほど、自信があるほど正しいほど簡単になります 完全に 試して。

私は機能Envy分類のOPを使用しています。他のクラスの内部で機能する多くの方法で、たくさんのクラスを持っていることほど私を苛立たせるものはありません。 OOは、データとそのデータの操作をモデル化することを提案します。それは、データとは別の場所に操作を置くという意味ではありません!それはあなたにデータとそれらの方法を置くようにしようとしています 一緒.

とともに carperson 非常に一般的なモデルは、電気接続を作成したり、スターターを回転させたりするためのコードを配置するようなものです。 person クラス。これがそうなることを願っています 明らかに間違っています 経験豊富なプログラマーに。

私は本当に理想的なクラスやメソッドサイズを持っていませんが、1つの場所で全体を見ることができるように、1つの画面にメソッドと機能をフィットさせることを好みます。 (60行のウィンドウを開くように構成されているVIMがありますが、これはたまたま印刷されたページ上の行の数の周りにあります。)これがあまり意味がない場所がありますが、私にとっては機能します。クラスの定義についても同じガイドラインに従い、ファイルをいくつかの「ページ」の長さの下に保つようにします。 300、400ラインを超えるものは、扱いにくいと感じ始めます(主に、クラスがあまりにも多くの直接的な責任を負い始めたためです)。

クラスの定義に数百の方法がある場合、大きすぎます。

私はの使用に完全に同意します 単一の責任の原則 クラスの場合でも、それが続いて大規模なクラスにつながる場合はそうです。本当の焦点は、個々の方法とプロパティが大きすぎないことです。 環状複雑さ そこにガイドである必要があり、その後、クラス全体のサイズを増やすが、読みやすく、粒状レベルまでテスト可能な多くのプライベート方法をもたらす可能性があります。コードが読み取り可能なままである場合、サイズは無関係です。

多くの場合、注文書を発行することは、発注書だけではなく、複雑なプロセスです。この場合、ビジネスロジックを別のクラスに維持し、発注書をより簡単にすることは、おそらく正しいことです。しかし、一般的に、あなたは正しいです - あなたは「データ構造」クラスを望んでいません。たとえば、あなたの「ポマーガー」ビジネスクラス」 issue() メソッドはおそらくPOを呼び出す必要があります issue() 方法。その後、POはステータスを「発行」に設定して発行日を記録できますが、Pomanagerは請求書を期待するために支払うべきアカウントに通知を送信できます。予想日。

方法/クラスのサイズに「ルール」をプッシュする人は誰でも、明らかに現実の世界で十分な時間を費やしていません。他の人が述べたように、それは多くの場合リファクタリングインジケーターですが、時には(特に「データ処理」タイプの作業では)、500本以上の線にまたがる単一の方法でクラスを書く必要があります。それに電話を切らないでください。

「クラスはたった1つのページに収まるべきだ」などのレシピを提供する著者を見つけました。

クラスの物理的なサイズのみに関しては、大きなクラスを見ることはコードの匂いを示していますが、必ずしも常に臭いがあることを意味するわけではありません。 (通常はそうです)カリブ海の海賊の海賊が言うように、これはあなたが実際の規則よりも「ガイドライン」と呼ぶものです。私は一度「クラス内の100個以下のLoc」を厳密に追いかけようとしましたが、結果は多くの不必要な過剰エンジニアリングでした。

したがって、彼らは通常、「モデルがより良いほど、アプリケーションのオブジェクトをより良く表し、すべてが出てくる」ようなものになります。

私は通常、これでデザインを始めます。このクラスは現実の世界で何をしていますか?私のクラスは、その要件に記載されているように、このオブジェクトをどのように反映すべきですか?ここに少し州、そこにあるフィールド、それらのフィールドで作業する方法、さらにいくつか追加して、出来上がりを追加します!労働者階級があります。署名を適切な実装で記入してください。これで、必要なすべての機能を備えた素晴らしい大きなクラスがあります。しかし、これの問題は、現実の世界が考慮に入れる方法を考慮していないことです。そして、それはそれが「変化」を考慮していないことを意味します。

クラスが望ましくなることが好ましくなる理由は、既存のロジックに影響を与えたり、意図せずに新しいバグを導入したり、すべてを再利用したりすることなく、後で大きなクラスを変更するのが難しいからです。これは、リファクタリング、デザインパターン、ソリッドなどがプレイする場所であり、最終結果は通常、他の小規模でより詳細なサブクラスで作業する小さなクラスです。

また、例では、IssuePOを追加し、POを承認し、POを購入注文クラスにキャンセルすることは非論理的なようです。発注書は、自分で発行、承認、キャンセルしないでください。 POにメソッドが必要な場合、メソッドはクラス全体ではなく、その状態で作業する必要があります。彼らは本当に他のクラスが取り組んでいる単なるデータ/レコードクラスです。

ジョブを実行するために必要なすべてのロジックを含めるのに十分な大きさ。

保守可能であり、従うほど小さい 単一の責任の原則.

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top