web-dev-qa-db-ja.com

C#の部分クラスは悪いデザインですか?

なぜ「部分クラス」の概念がC#/ VB.NETにも存在するのか不思議に思っています。私はアプリケーションに取り組んでおり、私たちは職場で実装している開発プラットフォームに関連する(実際には非常に良い)本を読んでいます。この本では、著者はプラットフォームAPIの周りに大規模なコードベース/ラッパーを提供し、プラットフォーム開発に関するさまざまなトピックを教えながら、どのようにそれを開発したかを説明しています。

とにかく、話は短く、C#(IMO)で複数の継承を偽造する方法として、彼は部分クラスをあらゆる場所で使用しています。なぜ彼がクラスを複数のクラスに分割してコンポジションを使用しなかったのかは、私を超えています。彼は、基本クラスを構成する3つの「部分クラス」ファイルを持ち、それぞれ3〜500行のコードを使用します。そして、これを彼のAPIで数回行います。

これは正当だと思いますか?もし私だったら、私はS.R.Pに従っていたでしょう。そして、さまざまな必要な動作を処理するために複数のクラスを作成し、次にこれらのクラスのインスタンスをメンバーとして持つ基本クラスを作成しました(構成など)。なぜMSは部分クラスをフレームワークに組み込んだのですか? C#の各スコープレベルですべてのコードを展開/折りたたむ機能は削除されました(これはC++では許可されていました)。これは明らかに悪い習慣を許可するだけだったためです。部分クラスはIMOと同じです。 私の質問だと思います:部分クラスを使用する正当な理由がある場合に説明していただけますか?

編集:Web/WinFormsには他に選択肢がないことは承知していますが、これ以外に、MSがコード生成を接着するためにいくつかの異なるキーワードを設定しなかったのはなぜですか?クラスをまとめましたか?それとも、それに値する正当な設計シナリオがありますか?

私はこれが暴言/戦争の糸であることを意味しません。私はここで何かを学ぶことを正直に探しています。コード設計で部分クラスをいつ使用すべきですか?簡単な質問、いいえ閉じる必要があります

ありがとう

69
dferraro

部分クラスを使用する正当な理由があるとき、私に説明できますか?

最も正当で有用な理由の1つは、自動生成されたコードとそれに対する独自のカスタム拡張の分離を促進することです。たとえば、ある種のデザイナーから自動的に生成されたフォームコードを使用することは一般的ですが、通常は独自の特定の動作を追加する必要があります。このように、自動コード部分を再生成する場合、特定の拡張子を持つ部分には触れません。

とは言っても、良いことは多すぎる可能性があります。いくつかのヒント:

  • partialになるためにクラスをpartialにしないでください。

  • 部分的なクラスを互いに並べて配置しないでください。クラスの残りの半分を表示するためにプロジェクトの完全に無関係なセクションにジャンプする必要がある場合、おそらくそれは間違っています。

  • クラスのサイズを不明瞭にする手法としてpartialを使用しないでください。クラスが大きすぎるためにpartialでクラスを分割している場合は、単一の責任の原則

  • 同じクラスに3つ以上のpartialフラグメントがある場合、これは、パーシャルを乱用していることをほぼ保証しています。 2つは、合理性の典型的な上限であり、通常、手書きコードから自動生成されたコードをセグメント化するために使用されます。

とにかく、話は短く、C#(IMO)で複数の継承を偽造する方法として、彼は部分クラスをあらゆる場所で使用しています。なぜ彼がクラスを複数のクラスに分けて作曲しなかったのかは、私を超えています。彼は、基本クラスを構成する3つの「部分クラス」ファイルを持ち、それぞれ3〜500行のコードを使用します。そして、これを彼のAPIで数回行います。

はい、それは明らかにpartialの明らかな乱用です!

97
John Feminella

部分クラスを使用する(そして使用する)理由は2つあります。

  1. コードの自動生成部分(WinFormsデザイナーコードやT4出力など)を分離するため。
  2. ネストされたタイプに独自のファイルを許可しながら、設計に必要なカプセル化を実現します。

更新
2つ目の点について確信のない人もいるので、例を挙げましょう。フレームワークのListViewItemCollectionListViewでのみ使用されるため、ListViewの下に正しくネストされていますが、メンテナンスを簡単にするために、部分クラスを使用して独自のファイルを作成します。私はこれを悪いデザインやpartialキーワードの誤用とは見ていません。

詳細については、これが重複しているという質問をチェックしてください: C#の部分クラス

12
Jeff Yates

部分クラスのもう1つの正当な使用法は、WCFの「モノリシックWebサービス」の混乱を減らすのを助けることです。それを機能の論理グループに分解したいが、個々のサービスインスタンス/エンドポイントの連を作成する必要はありません(おそらく、状態やリソースなどを共有しているため)。

ソリューション?サービスに複数のインターフェースを実装させ、各インターフェースを独自の部分クラスに実装させます。次に、構成内の異なるエンドポイントを同じ物理実装にマップします。プロジェクトの保守性が大幅に向上しますが、物理的なエンドポイントは1つだけです。

場合によっては、このタイプのアプローチをSRPのために不適切な方法として指摘しますが、WCFサービスまたはWebサービス全般を扱う場合、それほど単純ではありません。内部設計要件と外部消費要件のバランスをとる必要があります。

11
Aaronaught

あまり一般的ではない使用法の1つとして、巨大なクラスを個別の物理ファイルに分割して、ソース管理の観点から見た生活を楽にすることが挙げられます。私は、数千行のコードを実行し、いくつかの異なるビジネス機能に関連するメソッドを使用して実行している、非常に肥大化したWebサービスクラスを含むプロジェクトに参加しました。

異なるチームが同じファイルに無関係な変更を同時に行うため、さまざまな機能ブランチからのマージは悪夢です。重大な変更を加えずにWebサービスを分割することはできませんが、クラスを部分的なクラスに分割すると、動作が正確に維持され、マージの問題の束全体が削除されます。

私は上記を設計上の選択として奨励していませんが、それは私たちにとって素晴らしく素早い勝利であり、パーシャルは悪ではないall時間...

7
Jon M

これまで、部分クラスをさまざまな方法で使用してきました。プログラミングについて、特に「継承よりも構成を優先する」という概念について学ぶと、垂直継承と部分クラスの過剰使用の両方の必要性が減るのが簡単にわかります。

自動生成されたコード以外には、部分クラスの適切な使用は考えられません。 EFを使用していて、異なるメタデータが必要な場合でも、メタデータにパーシャルを使用することはお勧めしません。実際、(メタデータを追加するためだけに)別のパーシャルでプロパティを複製しようとすると、コンパイラエラーが発生します。

リファクタリングとSOC(Separation of Concerns)について学べば学ぶほど、クラスは小さくて集中的になります。それらはデフォルトで再利用され、時間がたつと完全に防護され、簡単にテストされます。巨大なプログラムにはNOとだけ言ってください。ヘンリー・フォードは、1900年代初頭にこの概念を学び、プログラマーは100年後にそれを学び始めました。

できれば作文を使う...

4
John Peters

部分クラスを使用する正当な理由がある場合に説明していただけますか?

Visual Studioの最近のバージョンでは、部分クラスを使用して、自動生成されたデザイナーコードを独自のコードから分離しています。

ASP.NETの例:

  • Page.aspx
  • Page.aspx.cs <-あなたのコード
  • Page.aspx.Designer.cs <-自動生成コードを含む部分クラス。

WinFormsの例:

  • Form1.resx
  • Form1.cs <-あなたのコード
  • Form1.Designer.cs <-自動生成されたコードを含む部分クラス
2
Simon Bartlett

John's の回答に完全に同意します。しかし、私はそれをさらに一歩進めます。

  • クラスを部分的にしないでください。

「良い設計」と私が考えると思われる部分クラスの唯一の使用法は、自動生成されたコードを使用することです。その他の使用は、ほぼ確実にクラスを不必要に分割しています。 (実際、私は Jeff's ネストされたクラスの2番目の点がおそらく有効な用途であることを確認できます)

個人的にはあなたが読んでいるこの本は悪いデザインのように聞こえると思いますが、彼は部分クラスを使用している可能性があるので、一度にクラス全体を提示するのではなく、コードの一部を少しずつデモできることを考慮してください。

2
Simon P Stevens

私は部分クラスを使用して、静的データアクセスメソッドを、アクティブレコードアーキテクチャのビジネスクラスプロパティおよびメソッドから「物理的に」分離しました。たとえば、CompanyとCompanyDataの部分クラスを並べて配置しました。利点は、1つのファイルがPOCOであり、もう1つのファイルにデータアクセスメソッドしか含まれていないことです。これは、レガシーアプリケーションでリポジトリクラスへのデータアクセスを削除するための足がかりとなりました。これは合法的な使用だったと思いますが、それは確かにリファクタリングプロセスをより公正にしました。

2
Jamie Ide

部分クラスの利点をグーグルで調べながら、このスレッドを偶然見つけました。 Java EEアプリケーションをSilverlightベースの.NETアプリケーションに変換しています。ビューレイヤーで次のコードに遭遇しました:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.225
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

...

 public partial class Wwcusts04d : System.Windows.Controls.Page {

さて、部分ページ自体が自動生成された場合、それを維持するための使用は何ですか?また、内部のコードは、さまざまなコントロールをそれらの名前にリンクするだけです。私はSilverlightの知識を持っていることを告白しませんが、これはxamlに適していますか?

2
sumit bisht

抽象ファクトリパターン を実装する場合、部分クラスのもう1つの有効な使用法があります。ルートファクトリオブジェクトをパーシャルにして、ファクトリがインスタンス化するクラスと同じファイルに実際のファクトリメソッドを配置します。

EDIT:部分クラスは、構成ファイルとやり取りするクラスでもうまく機能します。構成パラメーターを実際に使用するコードの近くに、構成パラメーターを含むコードを配置します。

2
Robert Davis

生成されたコードをカスタムコードから分離することについて述べた以前の回答に追加するために、強く型付けされたデータセットを拡張するのに役立つ部分クラスを見つけました。

1
Scott Lawrence

Visual Studioデザイナー(Asp.NetデザイナーやWindowsフォームデザイナーなど)がコード/混乱を生成できるように、部分的なクラスが.Netフレームワークだけに存在します生成されたコードを別のファイルに保持しながら、クラスで。

。NET部分クラスと継承 を参照)

同様のことを行う場合(ユーザー作成のコードと共存する必要があるコードを生成する場合)は、部分クラスも役立つかもしれませんが、Microsoftが部分クラスをVisual Studioチーム以外の人にも役立つ言語の概念

Partialクラスを使用するのは悪い設計であるほど多くはありません-おそらく、それらの使用法を見つけられないだけです。

1
Justin

このトピックについては多くの議論があり、1)部分クラスを使用するのは悪い設計である、2)自動生成されたコードで使用される、3)継承に代わるべきではない、と多くの人が言っています。

ただし、部分クラスが非常に役立つように見える状況があります。私は、最終的にスイートに統合される一連のアプリケーションを構築しています。それらはすべて、いくつかの機能を提供するメインフォームといくつかの共有コンポーネント(レポートを表示するフォームなど)を持ちます。私は たぶん......だろう 基本クラスを定義し、それから継承することは、すべてのアプリケーションを「エンタープライズ」バージョンの製品に組み合わせるときになると、多くのやり直しを意味します。

したがって、部分クラスは非常に便利です。これは、さまざまな部分クラスを結合バージョンに単純に含めることができると同時に、製品の個別のスタンドアロンバージョンをビルドできるためです。継承を使用してこれを達成しようとすると、単にReportsViewerを呼び出してVisual Studioが統合されていることを知るのではなく、各コンポーネントが独自のバージョンの共通コンポーネント(InvoiceReportViewer、PurchasingReportsViewerなど)を呼び出すことになります。私のためのすべてのビット。

1

私はVB.Netで部分クラスを2回使用しましたが、どちらの場合も、遅延バインディングが必要になるまれな機会でした。単に部分クラスを作成し、上部でOption Strictをオフにします。

1
Jules

考慮すべきもう1つのことは、部分クラスでは、同じクラス名を含む異なるファイル名を作成する必要があることです。たとえば、FactoryClassがあり、そのような部分バージョンを作成しているとします。 Factory.designer.cs、Factory.data.cs、およびこれらすべてのファイルには、FactoryClassという名前のクラスがあります。

this 質問に移動すると、次のように定義された ベストプラクティス があります。

ただし、ベストプラクティスは、ファイルごとに1つのクラスを定義し、定義するクラス(または構造体など)と同じ名前をファイルに付けることです。

0
Teoman shipahi