悪いOOPデザインから良いOOPデザインに移行する方法は?
-
22-07-2019 - |
質問
OOP設計の良い習慣と悪い習慣についてたくさん読んでいます。デザインが悪い、または良いことを知ってうれしいです。しかし、悪いデザインから良いデザインにどのように移行しますか? メインのビジネスロジッククラスからインターフェイス(xaml)と分離コードを分割しました。その最後のクラスは大きく成長しています。私はそれをより小さなクラスに分割しようとしましたが、今は行き詰まっています。大規模なクラスを分割する方法に関するアイデアはありますか?メインクラスには、さまざまなタイプのデータのリストが1つあります。合計だけでなく、個々のタイプについても計算しています。コードビハインドで処理されるイベントから呼び出されるこれらの計算を実行するメソッドがあります。ここからどこに行くべきですか?
追加情報:
このプロジェクトはすでに約6か月間です。私は何年もの間、オブジェクト指向言語(最初のC ++、Java、そして今ではC#)を扱ってきましたが、このような大規模なプロジェクトには一度も取り組みませんでした。最初は間違った方向に進んでいたと思うので、これらを修正する必要があると思います。現時点では、このプロジェクトの詳細を指定することはできません。デザインに関する本を1つか2つ注文します。すべてのクラスを分離した場合、どうすれば元に戻すことができますか?たぶん、最初のリリースまでこの方法を継続し、その後、2番目のリリースのためにパーツを再構築する方が良いでしょうか?
解決
メインクラスには、 他の種類。私がやっている 合計の計算だけでなく、 個々のタイプ。メソッドがあります これらの計算を実行するには で処理されるイベントから呼び出されます 分離コード。どこからのアイデア ここですか?
リストの内容に基づいて多くの計算がある場合、カスタマイズされたリストクラスに操作を移動することを検討しましたか?特定のタイプの操作についても同じことが言えます。おそらく、それらはタイプ内に存在する可能性がありますか?
異なる種類で同様の異なる操作を実行するという観点から、状態パターン(これをswitchステートメントの代わりとして参照してください)。これにより、エンティティを統一的な方法で処理できます。
OOPの多くは、「トップダウン」/マイクロ管理アプローチを捨て、「ボトムアップ」/自給自足のアプローチを検討することです。どちらのアプローチも「正しい」ことを忘れないでください。孤立して。保守可能なコードを作成することは、多くの思考を必要とし、通常は経験を通じて発展する賢明なバランスを見つけることです。
他のヒント
実践して読んでください。繰り返し:)
おすすめの本:
- ロバートCマーティンによるクリーンコード
- GoFのデザインパターン
- Martin Fowlerによるリファクタリング
個人的に私もヘッドファーストデザインパターンが好きでしたが、スタイルはすべての人に適しているわけではありません。 C#3.0 Design Patternsと呼ばれる同様の本があります(ora.comを参照)。同じものがたくさんありますが、より伝統的な方法です。
コード完了を選択することを強くお勧めします。あなたのような質問についてたくさんの良いアドバイスを提供する素晴らしい本です。
大規模なクラスを分割する方法についての質問に簡単に答えるために、良い経験則があります。クラスを1つのことだけに責任を持つようにします。そのように考え始めると、所属していないコードをすばやく特定できます。何かが属していない場合は、それを新しいクラスに分解し、元のクラスから使用します。
編集:その考え方を" method"に落とし込みます。レベルも-メソッドを1つのことだけに責任を持つようにします。大規模な(> 50行)メソッドを非常に迅速に再利用可能なコードの塊に分解するのに役立ちます。
オブジェクトに関する考え方を変更します。すべてのオブジェクトには、1つの非常に具体的な責任が必要です。 " MainBusinessLogic"のような一般的な名前のクラスがある場合おそらく何か間違ったことをしているのでしょう。
始めるのに最適な場所:David Westの Object Thinking を読んでください。
これは、ここでいくつかの素晴らしい本の提案への補遺です。
オブジェクト指向でうまくいけば行くほど、オブジェクトのサイズを小さくしていくようです。小さなオブジェクトサイズなどを求めているわけではありませんが、起こっているようです。
それらを小さく、単一の責任を持ち、使いやすく理解しやすいものにします。すべてが重要です。各オブジェクトは可能な限り防弾に近く、パラメータを確認し、オブジェクトを無効な状態にしないでください。ドキュメントですべての有効な状態を明確に定義します。
クラスを作成するたびに、そのクラスのテストを作成します。コードをテストするだけでなく、独自のデザインを強制的に使用します。常に「外部ビュー」からクラスを考えてください。クラスを使用している人にあまり質問していないことを確認し、あなたが彼に尋ねていることはすべてインターフェースに文書化する必要があります。多くの場合、テストフレームワークが利用できない場合、クラスにクイックメインをスローします。コードを使用する方法の例を同じファイルに配置します。
コーディングでは、ほとんどすべての時間が、他の誰かが何をしたかを把握しようとして費やされます。既知のAPIまたは十分に文書化されたAPIを使用してコードを出力できた場合、私の仕事は簡単で、スケジュールは大幅に短縮されます。
デザインファーストは難しい場合があります。スポーツ能力と同様のコーディング能力を検討してください。私たちのほとんどは私道でプレーし、地元のスポーツチームでプレーする人もいます。複雑なプロジェクトで適切な先行設計を行うことは、ナショナルリーグプレーヤーの仕事であり、100万人に1人です。これを受け入れて変更を計画します。反復はあなたの友達です。 (ところで、私たちのほとんどは簡単に州レベルにいると思います。そうではありません。)
ロバートCマーティンによる Clean Code のブライアンの推奨に加えて、「ボブおじさん」の記事を読むこともできます。 SOLID Principles of Object Oriented Design 。
Hanselminutes Podcast 145 で、彼が固い原則について話しているのを聞くことができます。 .NET Rocksのコード! #388 を表示します。また、 .NET Rocksにも彼と一緒にいます。 #410 を表示しますが、彼が話していることはあなたの質問とはあまり関係ありません。最初の2つを楽しんだ場合に備えて、それを含めました。
3つのポッドキャストのうち、私はHanselminutesを好みました。
リファクタリングは、ソフトウェアを破壊することなく設計します。
デザインパターンは、アルゴリズムと同様に機能しますが、オブジェクトの結合方法を示しますさまざまな便利なタスクを実行します。
最後に Martin Fowler には、アプリケーションに役立つさまざまなデザインパターンがあります。たとえば、パッシブビュー
Michael Feathersの"レガシーコードの効果的な使用" は、非常に良いが、私はそれを自分で読んでいないことを告白します。
" パターンのリファクタリング"
助けを借りずに複雑な「割り当て」に取り組み、他の誰かがそれをどのように行ったかを見ることが、私にとって大きな学習経験であることがわかりました。
特に課題の1つは、トランザクションを追跡し、獲得した利息などを計算できるようにする銀行のようなプログラムを作成することでした。それは本当に私の最初のOOPプログラムであり、その複雑さゆえに本当に素晴らしいプログラムでした。 (初心者にとって)間違いを犯さずに直線的なスタイルでそれを行うには、あまりにも混乱します。
私には何が効果的かしか言えず、同じように機能する人を実際に見つけていないので、それがあなたに非常に役立つかどうかはわかりません。
基本的に、私のアプローチは可能な限り少ないクラスを使用することですが、それより少ないクラスはありません。
まず、情報を保存する必要があるのは、時間Aに受け取って後で必要になる場合だけです。保存します。
第二に、あなたはそれで何をしますか?特定の簡略化された方法で繰り返し処理する場合、それを命令セットと見なし、それを操作するプログラムを命令セットのインタープリターと考えることができます。その場合、インタープリターを使用してバイトコード命令セットを実際に設計し、その命令セットで情報をエンコードすることができます。
第三に、情報はどのくらいの頻度で変更されますか?情報の一部が非常にまれにしか変更されない場合、部分評価(つまり、コード生成)を使用できる場合があります。つまり、頻繁に変更されない情報を取得し、それを使用して、プログラム全体でその情報を処理するが、はるかに高速なアドホックプログラムを生成します。コードジェネレーターは、入力情報の一部、つまりゆっくりと変化する部分のみを処理するため、簡単に記述できます。
最近見たデータ構造の多くは、UIをサポートするためのものです。これは明らかに、ユーザーが気にするオブジェクトを保持していないため、理想的にはどちらも気にする必要はありません。それで、私はUIのDSLを作成し、そのフーをすべて隠しています。
イベントや通知はできる限り避けてください。それらはある時点で発生するため、状態の増分的な変化を表しているためです。落としたり、複製したり、順序を間違えたりする可能性があることを心配する必要があります。多くの場合、単純なポーリングスタイルは「効率が悪い」という理論で使用されます。実際にはしばしば逆のことが起こります。
だから、人々がクラスなどの技術に包まれているのを見ると、それは通常、彼らがあまりにも多くのデータ構造を作っているからです。
ちょうど私のダウン投票ベイト...
Safariで利用可能および検索可能なFeatherのレガシーコードを効果的に使用するをお勧めします、リファクタリング。 あまり時間がないので変更する必要があるやアプリケーションに構造がありません
のような便利で共感的な章がたくさんあります。考慮すべき視点:
- 設計品質テストの自動化-設計決定のクロスチェックとして、設計品質に関するメトリックを提供するツールを探します。
- コードのテスト容易性-リファクタリングは、テスト駆動開発、単体テストの作成、または機能テストの作成を支援または妨害しますか?統合されたアーキテクチャの大部分をテストするのはどれくらい難しいですか?
- ジャスティフィケーション-シニカルなCYAから経営陣まで、さらに重要なことには、チームが再設計を信じるように、これらの決定をどのように守りますか。変更が行われた理由を簡単かつ一貫して説明できますか?また、その説明は6か月後に簡単に見つかりますか?
デザインの個人的な好み、特にリファクタリング:
- 概念のクラス-疑わしい場合、明確な概念が1つしかない場合は、1つまたは複数のメソッドの動作として暗示されるのではなく、クラスでラップする必要があります。
- 小さなことを責任を持って伝えることは、考えて監査するのが簡単です。デザインが現実の世界にどのようにマッピングされるか疑問がある場合は、古い責任主導型に戻る各クラスの責任を書き留める設計アプローチ。これが難しいと思う場合、各クラスが何をしているのかという概念が混乱したり、やりすぎている可能性があります。
- 物事が規則的であれば、物事が大きくても怖がらないでください。たとえば、GUIのイベントハンドラーの多くは、合法的に、メトリックが推奨するよりもはるかに多くのメソッドまたはプロパティを持つクラスを持つことになります。
よりテスト可能なコードを書いてみてください。これだけで、改善されたOOPプラクティス/設計コンセプトを調査して実装することを余儀なくされました。