OOPのオブジェクトはエンティティを表す必要がありますか?


82

オブジェクトはエンティティを表す必要がありますか?

エンティティ私のような何かを意味ProductMotorParkingLotなど、物理的、あるいは明確な非物理的な概念オブジェクト-だけでなく、いくつかのコアデータは明らかにオブジェクトに属していると、定義されているもの、およびいくつかの関数/メソッドコアデータを明確に操作します。

たとえば、aのオブジェクトDemon、それ自体のエンティティ、想像上のオブジェクト、おそらく物理的ではなくエンティティを持つことができます

オブジェクトは、メソッドのコレクション、共通の目標に結び付く共通のプロシージャセットになりますか?

例:クラスを呼び出すことができるMotorOperationsか、MotorActionsそこには実体ではありませんが、クラス内のメソッドは次のようなことを行う場合には、

  • getMotorDataFromHTMLForm()
  • getMotorManufacturers()
  • selectMotorFromUserRequirements($ requirements)
  • canMotorCanHandleOperatingConditions($ conditions)
  • computePowerConsumptionForMotor($ id)

クラスは通常、オブジェクトの中心となるデータ+データの操作として定義されます。そのため、Motorモーターの仕様に関連するいくつかのモーター変数があり、それらのデータを組み合わせて何かを生成する操作があります。

私の場合、データを操作するクラスとクラスを通過するデータを持っているようなもので、一時的なクラススルーデータ以外に「モーター操作」を中心としたデータはありません。

質問

クラスはエンティティのないオブジェクトを表すことができますか?そうでない場合、なぜそれらは悪い/不完全/非OOP中心ですか?OOPに合わせて概念的に変更/改善する必要がある方法はありますか?


2
+1。しかし、「はい」は、エンティティを表す必要があることを意味しますか、それともエンティティのないオブジェクトを表すことができることを意味しますか?
パンツァークライシス

1
最初に思い浮かぶのは、java.awtとその「Op」クラス(例:docs.oracle.com/javase/7/docs/api/java/awt/image/…)です。操作を表します。今、それが良いプラクティスかどうかはわかりませんが(奇妙で見苦しいようですが)、Java標準ライブラリに含まれており、JavaはOOPです。ほとんどの場合。
ルーク

1
いいえ、そうではありませんが、MotorActionsそれMotorOperationsは良いアイデアを意味するものではありません。
user253751

1
この質問は、缶のさらなる仕様から利益を得ることができました
reinierpost

3
@Dennis本当に間違った質問をしているように感じます。1つはOOPの明確な定義がないため、2つ目はパラダイムが目的のための手段にすぎないためです。重要な唯一の質問は、「このようにコードを書くことで、その正確さについて推論しやすくなりますか?」です。「このようにコードを書くと、再利用しやすくなりますか?」
ドーバル

回答:


109

いいえ、オブジェクトはエンティティを表す必要はありません

実際、オブジェクトを物理的なエンティティとして考えるのをやめると、OOPが約束するメリットを最終的に得ることができると主張します。

これは最良の例ではありませんが、Coffee Makerのデザインはおそらく私にとって光が降り始めた場所です。

オブジェクトはメッセージに関するものです。彼らは責任についてです。車、ユーザー、注文に関するものではありません。

OOをこのように教えることは知っていますが、MVC、MVVM、またはMVWhateverを実行しようとすると、どこに行くのかを理解することがどれほど根本的にイライラするかを数回試してみると明らかになります。モデルが途方もなく肥大化するか、コントローラーが肥大化します。ナビゲーションのために、Vehiclesに触れるものはすべてVehicle.extファイルにあることを知っておくのは素晴らしいことですが、アプリケーションがVehiclesである場合、必然的にそのファイルに3000行のスパゲッティができてしまいます。

送信する新しいメッセージがある場合、少なくとも1つの新しいオブジェクトと、おそらくそれらのペアがあります。したがって、メソッドのバンドルに関する質問では、メッセージのバンドルについて話している可能性があると主張します。そして、それぞれが独自のオブジェクトであり、独自の仕事をすることができます。そしてそれは大丈夫です。本当に、本当に本当に一緒にする必要があるものをバラバラにすると、それは明らかになります。そして、それらをまとめます。しかし、オブジェクト指向を楽しみたい場合は、便宜上、漠然と適切な引き出しにすべてのメソッドをすぐにドロップするわけではありません。

関数のバッグについて話しましょう

オブジェクトは単なるメソッドのコレクションであり、オブジェクト指向のままである場合がありますが、私の「ルール」はかなり厳密です。

  1. コレクションには単一の責任が必要であり、その責任は「モーターに負荷をかける」ほど一般的ではありません。私はサービス層のファサードのようなことをするかもしれませんが、私はオブジェクト指向コードを書き込もうとしているからではなく、ナビゲーション/発見の理由で怠け者であることを痛感しています。

  2. すべてのメソッドは、一貫した抽象化層にある必要があります。1つのメソッドがMotorオブジェクトを取得し、別のメソッドがHorsepowerを返す場合、おそらく離れすぎています。

  3. オブジェクトは同じ「種類」のデータで動作するはずです。このオブジェクトはモーター(開始/停止)にデータを送り、これはクランク長で処理を行い、これは点火シーケンスを処理し、これはhtml形式を取ります。このデータは、オブジェクト上のフィールドである可能性があり、まとまりがあります。

私は通常、変換、合成を行っているとき、または単に可変性を心配したくないときに、この種のオブジェクトを構築します。

オブジェクトの責任に焦点を当てることで、結束が促進されます。オブジェクトになるにはある程度の凝集性が必要ですが、オブジェクトであるためにフィールドや動作をする必要はありません。これらの5つのモーターメソッドを必要とするシステムを構築していた場合、それらのことを行う5つの異なるオブジェクトから始めます。共通点を見つけたので、物事を統合するか、共通の「ヘルパー」オブジェクトを使用します。それは私をオープン/クローズドの懸念に動かします-どのように私はこの特定のファイルを再び変更する必要はなく、必要な場所でそれを使用する必要がないようにこの機能のビットを抽出できますか?

オブジェクトはメッセージに関するものです

オブジェクトにとってフィールドはほとんど問題になりません。レジスタを取得および設定しても、プログラム外の世界は変わりません。他のオブジェクトとのコラボレーションにより、作業が完了します。ただし、OOの強みは、抽象化を作成できるため、個々の詳細すべてを一度に考慮する必要がないことです。リークしたり、意味をなさない抽象化には問題があるため、メンタルモデルに一致するオブジェクトを作成することについて(多すぎるかもしれませんが)深く考えます。

重要な質問:これらの2つのオブジェクトが互いに対話する必要があるのはなぜですか?

オブジェクトは人の臓器と考えてください。デフォルトの目的があり、関心のある特定のメッセージを受信したときにのみ動作を変更します。

あなたが横断歩道にいて、車が速く来ているシナリオを想像してください。脳のオブジェクトとして、ストレッサーを検出します。視床下部にコルチコトロフィン放出ホルモンを送るように言います。下垂体はそのメッセージを受け取り、副腎皮質刺激ホルモンを放出します。副腎はそのメッセージを受け取り、アドレナリンを作り出します。筋肉オブジェクトがそのアドレナリンメッセージを取得すると、収縮します。心臓が同じメッセージを受け取ると、心臓はより速く鼓動します。通りを横切って全速力で走るという複雑な行動を開始することに関与するプレーヤーのチェーン全体があり、それが重要なメッセージです。脳オブジェクトは視床下部にアラートを送信させる方法を知っていますが、最終的に行動を起こすオブジェクトのチェーンを知りません。同様に、心臓はアドレナリンがどこから来るのかわからない、

したがって、この(簡略化された)例では、副腎オブジェクトは、ACTHを摂取してアドレナリンを分泌する方法を知るだけで済みます。それを行うのにフィールドは必要ありませんが、それでも私にはオブジェクトのように見えます。

ここで、アプリケーションが通りを横切るようにのみ設計されている場合、下垂体と副腎のオブジェクトは必要ないかもしれません。または、概念的に「下垂体モデル」と見なされるもののほんの一部を実行する下垂体オブジェクトのみが必要です。これらの概念はすべて概念的なエンティティとして存在しますが、それはソフトウェアであり、AdrenalineSenderまたはMuscleContractorなどを作成でき、モデルの「不完全性」についてあまり心配する必要はありません。


4
この答えの実際の内容には同意しますが、質問を誤解しているように感じます。具体的には、この質問には、「または概念、明確に定義された何か」というエンティティが含まれます。これに対する反例は「MotorOperationsまたはMotorActions」です。このことから、CoffeeMakerの例の元のクラス最終クラスの両方のデザインが、OPの「エンティティを表す」という定義に当てはまる確信しています
ベンアーロンソン

1
ポストモダンシステムアーキテクチャDCIは、構造を愛するエンジニアによって作成された極端な抽象化なしにこれを処理します。コンピューター、ユーザーが考えていること考えるべきであり、その逆ではありません。fulloo.info/doku.php?id=what_is_dci
ciscoheat

@BenAaronson私はあなたが十分な協調的な努力でまとまりのある概念としてそのオブジェクトに進化することができると思いますが、私はエンティティフォーカスが離れるべきものを一緒に強制する傾向があることを発見しました。エンティティは私たちの名前の境界線を奨励しますが、これは良いことですが、正確性/完全性というこの概念をもたらします。最もばかげた言葉で言えば、私はFirstNameValidatorオブジェクトであり、名前と姓の検証も行うNameオブジェクトに対してです。
スティーブジャクソン


2
オブジェクトはメッセージに関するものです -スティーブジャクソンの答え-これは絶対に正しいです。MOPは、大きなアイデアがメッセージングであると言っ OO Alan Kayの父によって考案された「メッセージング」が意味するものではありません。さらに、私がずっと前にこのトピックの「オブジェクト」という用語を作り出したことを残念に思います。なぜなら、多くの人々がより小さなアイデアに集中するようになるからです。
レーダーボブ

21

クラスはエンティティのないオブジェクトを表すことができますか?そうでない場合、なぜそれらは悪い/不完全/非OOP中心ですか?変更/改善する必要がある方法はありますか?

要するに、あなたは何でもできますが、この特定のシナリオはOOPの原則に反するでしょう:)

あなたが説明しているものは、「ユーティリティ」クラスと呼ばれることもあります-通常、コード臭の兆候 いくつかのメソッドをまとめるために、クラスの作成を避けたいと思います。

アプリケーション内のすべてのオブジェクトを、モーターや自動車などの実際のエンティティにリンクする必要はありません。これらはビジネスオブジェクトです。アプリケーションでは、多くのビジネスオブジェクトを使用する可能性がありますが、リストしたようなビジネスエンティティの一部ではない他の操作についても、さらに分離する必要があります。

一般的なアーキテクチャパターンを確認する必要があります。その1つがMVC(Model-View-Controller)です。

MVCを使用してリストしたメソッドを配布する場合、次のようにします。

クラスを見る:

  • GetMotorDataFromHTMLForm()

モデルクラス(基本的にモーター):

  • GetMotorManufacturer()
  • CanMotorHandleOperationConditions()
  • CalculatePowerConsumption()

コントローラークラス(MotorsController):

  • GetAllMotors()
  • GetMotorById()
  • GetMotorByUserRequirements()

PHPを使用しているようです。見るべき良いMVCフレームワークはLaravelです。それらの例では、どのメソッドがどこに属しているかをよく示しています。

メソッドがどこに属するかを決定する方法のもう1つのより一般的な情報源は、GRASPおよびSOLIDの原則です。


ありがとう。本質的に、私が持っているのは、いくつかの不純物が混合されたコントローラークラス(モデル、ビューなど)であるように見えます。それは私が名前を変更した場合という意味ではないMotorOperationsMotorsControllerして少しそれをクリーンアップ、私の機能のコレクションは OOPに沿ったものになりますか?
デニス

@Dennisは、必ずしもそうではありませんが、各クラスの下にあるメソッドのコレクションを見てください。コントローラはすべてを含むクラスではありません:)それはあなたのモデルで動作するクラスであり、それ以上のものはありません。通常、コントローラーの唯一の依存関係は、直接DAL(データアクセスレイヤー)、またはDALへのアクセスを提供するサービスです。コントローラーからViewにアクセスしたいことは決してありません(例:getMotorDataFromHTMLForm)。代わりに、Viewはコントローラーに依存するものでなければなりません。
アレクサス

2
Utilsクラスがコードの匂いの例になる理由について詳しく説明していただけますか?好奇心が強いのUtilsですが、スタンドアロン関数であるのではなく、クラスでラップされたランダムなユーティリティ関数を楽しんでいるので...私の経験では、コードが少し読みやすくなりますが、私の経験は限られています。
HC_

3
@HC_ Utilsクラスを持つことは、画像コレクションに「Misc」フォルダーを持つことと同じです。それはあなたがあなたのオブジェクトに適切に/潜在的に欠落しているオブジェクトに責任を割り当て、それを補うためにUtilsを使用するのが面倒だったことを示します。特に静的関数や他のクラスの拡張機能を備えたUtilクラスの余地がありますが、そのようなコレクションを作成する前に、それらを適切なOOPクラスに組み込むことができるかどうかを確認してください:)一つの方法。しかし、今後はさらに追加する必要があり、Utilsクラスはより大きな混乱になります。
アレクサス

私はしばしばUtils LIBRARYになりますが、通常はutilsクラスをもう少しわかりやすくグループ化して名前を付けようとします。最近では、多くのオープンソースの「共通ユーティリティ」ライブラリがあり、ほとんどの人が必要とする汎用ユーティリティが既に存在するため、独自のライブラリを作成する前に少し調べてみます。
ガイシャルナット

15

クラスはエンティティのないオブジェクトを表すことができますか?

できる?はい。すべき?おそらくない-または少なくとも、あなたが物事をフレージングしている方法ではない。

現実は物理オブジェクトを直接表現しない場合が実際に最適です。なぜなら現実はコードにうまくマッピングされることはめったにないからです。ただし、まとまりのある概念またはコードオブジェクトを表す必要があります。彼らは単一のまとまった責任を表す必要があります。

一連の接線方向に関連する関数を1つにまとめるのは、名前空間またはモジュールであり、OOP用語ではオブジェクトではありません。これらは有用な場合がありますが、同じではなく、効果的に作業するには異なる種類の使用法/思考が必要です。


3
bundling a bunch of tangentially related functions together is a namespace:オブジェクト指向ではなく、手続き型パラダイムのように聞こえます。
デニス

@dennis-正確(またはモジュールと呼ぶ場合は機能的)。パラダイムの混合は強力です。または、ひどく乱雑な場合もあります。
テラスティン

または両方:) - - - - -
Alexus

@Dennis:またはどちらでもない-接線方向に関連する関数のみをまとめることは、どのようなパラダイムでも疑わしい習慣です。
sdenham

私は手続き型コードベースとして始まったコードを扱っています。ある時点でそれをOODに変換する努力がなされましたが、ほとんどのクラスは実際のオブジェクト指向設計なしで「関数とメソッドを保持する」ために作成されました。私はパラダイム間のギャップを埋めようとするが、一方にも他方にもないこのような多くのことを発見してきました
デニス

11

クラスは何かをモデル化する必要があります -そうでなければ意味がありません。ただし、モデル化されているものは物理的な「もの」ではない場合があります。代わりに、「リアル」ではないが、モデル化されているシステムを制御するために必要な何かの表現である場合があります。たとえば、交通信号制御システムでは、何らかのアクションを実行する必要があることを示すためにシステムのある部分から別の部分に送信される信号を表す、ある種のControlSignalクラスを持つことができます。「現実の世界」では、これらの信号は、あるボックスから別のボックスにワイヤを介して送信される電気的インパルスで構成される場合があります。具体的なオブジェクトとして「現実」ではない何かをモデリングするプロセスは、「具体化」と呼ばれます。

幸運を祈ります。


うん、それは私が言ったことにほぼ正確です。クラスは名詞のモデルにすぎません。それでおしまい。これ以上でもそれ以下でもありません。クラスは名詞であり、メソッドは動詞(または必要に応じてメッセージ)です。これらの単純な用語で考えるジュニアエンジニアは、それらのアナロジーが崩壊するまでに長い道のりを歩むことができます(クラスが物理的なオブジェクトの記述であるふりをしようとするのとは異なり、アナロジーはほとんど最初のプロジェクトで崩壊し始めます)。
カルフール

7

いいえ(反対の質問をするためにタイトルを編集しました!)

例えば:

Public class MyRepository
{
    public MyObject GetObject(string id)
    {
        //get data from the DB and build an object
    }
}

または

Public class MyService
{
    public MyObject3 ProcessData(MyObject1 obj1, MyObject2 obj2)
    {
         //perform a process which is not a sole responsiblity of obj1 or obj2
    }
}

ただし、一般に、OOPの背後にある理想は、

public struct Car
{
    public Wheel[] Wheels;
}

public int CountWheelsOnCar(MyCarStruct car)
{
   return car.Wheels.Length;
}

public class Car
{
    private Wheel[] wheels;
    Public int CountWheels()
    {
        return this.wheels.Length;
    }
}

エンティティのないオブジェクトを表すことができるということですか?(質問に残したコメントを参照してください。)
パンツァークライシス

3
私はOOをあまりにも長くプログラミングしてきました-MyRepositoryを見ると、すぐにドレッサーのガラスのボウルにたくさんのコインとがらくたが入っているのを想像しました。....に達するとペニーをつかむ、またはボタン
ビルK

@panはい、私の例のサービスとレポのように
ユアン

@bill you crazy old fool !!! MyButtonAndOrPennyBowlクラスです!クリーンコーディングftw
ユアン

1
あなたの2番目の例は、オブジェクトとしてドレスアップされた関数のように見えますが、それは(私の意見では)正当化されていませんが、他の正当化があるかもしれません(たとえば、関数が言語のファーストクラスのエンティティではない場合) )
sdenham

5

現実の世界で何かを視覚化することは、クラスをコーディングするときに役立ちますが、必要ではないと思います。

実際、どのようにリテラルになりたいかにもよりますが、私たちが扱う多くのオブジェクトには物理的な表現がまったくありません。たとえば、MVCアーキテクチャを検討してください。現実の世界では、一般にクラスで表されているモデルやコントローラーはありません。3つは一緒に何かを表すことがよくありますが、常にではありません-しかし、私が言ったように、あなたが本当にしたい場合はおそらく何かに合わせることができます(そして何かを想像することができます!あなたは現実の世界で見たことがあるでしょう)。

OOについて学ぶこれらの「ルール」の大部分は、OOでの思考に向かわせるための単なるガイドラインであり、日常的にコーディングする際に心配することは必ずしもありません。

ちなみに、OO自体は万能薬ではなく、ソリューションをコーディングする最初の段階ではあまり役に立ちませんが、正しく処理すれば、コードを整理するための本当に素晴らしい方法だと思います後で容易に理解できます。保守可能なコードの作成は、おそらくソフトウェア開発で最も困難なタスクの1つであり、多くの場合(進行中のデバッグ/保守を必要とするもの)、それは断然最も重要です。


5

オブジェクトはエンティティを表す必要がありますか?

質問:どのエンティティがLogger代表しますか?

比meta的ではない-文字通り。

OOPを学生に説明するとき、物理的な世界に類似したオブジェクトを説明することは役に立ちます。

アラン・ケイ -の父の1 OOPは -次を書きました:

[...]

それの最初の概念は次の部分を持っていました。

  • オブジェクトは、生物学的細胞やネットワーク上の個々のコンピューターのようなものであり、メッセージとのみ通信できると考えました
  • データを取り除きたかった。

[...]

私にとってのOOPとは、メッセージング、ローカルの保持および保護のみを意味し、

状態プロセスの隠蔽、およびすべてのものの極端な遅延バインディング。

ほとんど信じられないほどのHWアーキテクチャ。私は

セル/コンピューター全体のメタファーはデータを取り除きます

ソース

このことから、オブジェクトは次のように最もよく理解されます

  • データをカプセル化/非表示にする外生のオブジェクト

  • メッセージを介して他のオブジェクトと通信する

クラスはエンティティのないオブジェクトを表すことができますか?

間違いなく:考えて Math


あなたの例について:

例:クラスはMotorOperationsまたはMotorActionsと呼ばれます。エンティティはありませんが、クラス内のメソッドは次のようなことを行います

  • getMotorDataFromHTMLForm()

  • getMotorManufacturers()

  • selectMotorFromUserRequirements($ requirements)

  • canMotorCanHandleOperatingConditions($ conditions)

  • computePowerConsumptionForMotor($ id)

これらのメソッドを置く場所、あなたが見て取らなければならない、決定するresponsibilities何のためrespnsibleです

getMotorDataFromHTMLForm()

このようなメソッドのコンテキストは、モーターオブジェクトの構築です。フォームを介して取得したデータから自身を作成することは、モーターの責任ではありません。少なくとも2つのオブジェクトが関係しています。1つはモーターで、もう1つはモーターの作成者です

getMotorManufacturers()

そのようなメソッドを記述する典型的なコンテキストはserviceです。

selectMotorFromUserRequirements($ requirements)

これは、service-context でも使用されます

canMotorCanHandleOperatingConditions($ conditions)

これは、motorオブジェクトへの質問です

computePowerConsumptionForMotor($ id)

これも、モーター自体に最もよく尋ねられる質問です。


tl; dr

物理的なオブジェクトobjectsとしてのメタファーは、役に立つというよりもいらいらさせるものです。


あなたの答えがOOPに命を吹き込みます!物理的なことを意味するものではなかったと言わざるを得ません。私の質問の意図は、「オブジェクトはthing、データに明確に属するデータと、その事に属するデータに対して明確に作用する機能を持つデータでなければならない」ということでした。したがって、この場合のロガーは、物理的なものではありませんが、「物理的なログブック」に似た概念です。それはその状態にあるコアのデータを持っており、実装や解釈に依存してもよいこと、それへの単なる一過性ではない..ですし、私の質問を行っていたところよりそうであるかどうか...
デニス・

しかし、はい、答えは私の物理的偏見に対処しなければなりませんでした
デニス

3

はい、これを行うことができます。ただし、基本的には、手続き型ライブラリと同じ機能を提供するクラスを作成しています。これを行う唯一の理由は、言語に手続き型モジュール(JavaやRubyなど)がない場合です。

手続き型モジュールを持つ言語(PHPには手続き型モジュールがあると思います)では、手続き型モジュールの使用を検討することもできます。

クラスのインスタンスが一貫したオブジェクトを表すように、クラスの再設計を検討することもできます。

しかし、オブジェクト指向であるためだけでなく、オブジェクトに余分な力を与えている場合にのみオブジェクト指向表記法を使用してください!


3

素人の言葉で

  • あなたが説明するものはユーティリティクラスと呼ばれます。
  • 状態はありません。つまり、複数のインスタンスを持つ必要はありません。
  • すべてのメソッドは静的です。つまり、すべてをパラメーターとして渡す必要があります。

このようなクラスは存在します。たとえば、Java SDKには、コレクションを操作するかコレクションを返す静的メソッドのみで構成されるCollectionsクラスがあります。

したがって、答えはノーになります。すべてのクラスをドメインエンティティからモデル化する必要はありません。

一方、OOPの真の力は多態性とカプセル化にあるため、OOP言語で作成されたプログラムでは、このようなクラスはごくわずかであるか、またはごく少数である必要があります。

それは飛行機を使って、飛行ではなく高速道路を走り回って、ある場所から別の場所に行くようなものです。飛行機には車のように車輪がありますが、飛ぶことを目的としています。


2

いいえ、クラスは単にインスタンス化でき、メンバーを持ち、継承できるものを表すだけです。

実際、言語には静的クラスがあり、複数回インスタンス化されることさえありません。

.NETMathは、(数学とは何かを哲学的に知りたい場合を除いて)エンティティを表さない「プロフェッショナル」クラスの優れた例であり、そのようなクラスの正当な使用例を示しています。メソッドと2つのフィールド(両方とも個別の定数を表す)のみがあります。

同様のライブラリのクラス階層、は、Math.Net数学/数値メソッドをタイプごとにクラスにグループ化します。ここで、クラスはエンティティではなく、論理的なカテゴリを表します。

私自身は、関連する(静的な)関数の集まり、または便利な1つの場所にグループ化された定数の集まりにすぎない(静的)クラスを作成することがよくあります。これは良い設計だとは言いませんが、時にはそれが最も簡単な解決策だと思います。


1
数学関連のメソッドが.NET / BCLで静的メソッドとして別のクラスに配置されるという事実は、必要性や設計上の考慮事項ではなく、C#に独立したメソッドがないという事実の結果です。C ++では、このような関数は名前空間にグループ化することができます。
Vlad

1

あなたの質問に対する答えは、最終的に「クラス」や「エンティティ」などの用語をどれだけ正確に定義するかにかかっています。物理エンティティと概念エンティティの両方を許可して、後者を適切に定義しました。しかし、純粋主義者に対する「クラス」という用語は、常に「特定の内部表現でオブジェクトをインスタンス化するための工場」であり、実用主義者にとっては、この用語は純粋主義者によって軽deされたJavaまたはC ++のものを含みます。実用主義者はJavaとC ++を言うかもしれないが、純粋主義者はアラン・ケイが彼の発言の意味を意味すると考えるだろう用語「OOP」についても同じです。 C ++を念頭に置いてください」]( それでは、「オブジェクト指向」という用語でアランケイが本当に意味したことは何ですか?)。

プラグマティストビューを使用すると、インスタンスなしのユーティリティクラスを受け入れることができます。しかし、純粋主義的な見方はもっと興味深いです。Kayによると、OOPは常にクラスよりもメッセージに関するものでした。あなたの質問に:

クラスはエンティティのないオブジェクトを表すことができますか?

いいえ。クラスオブジェクトを分類します。クラスは、定義上new、オブジェクトを生成するなど、メッセージを送信するエンティティです。オブジェクトは、クラスから作成されたエンティティです。オブジェクトを製造し、実際に分類するクラスが存在します。それがクラスの役割です。クラスはオブジェクトを作成します。クラスを使用してオブジェクトを分類します。したがって、Cがインスタンス化またはサブクラス化を許可しないメソッドのバンドルである場合、C によって分類されるオブジェクトは存在できないため、Cはクラスではありません。

そうでない場合、なぜそれらは悪い/不完全/非OOP中心ですか?

彼らは悪くありません。クラスとは呼ばないでください。メソッドのバンドル OOP可能です。メソッドを呼び出すためにメッセージを送信できますが、オブジェクトをインスタンス化できない限り、クラスではありません。Rubyを知っていますか?Rubyでは、モジュールはメソッドのバンドルです。クラスは、オブジェクトをインスタンス化することができますモジュールです。モジュールについて悪いことは何もありません。しかし、クラスをモジュールとは異なるものにする(純粋なOOP用語で)ことは、クラスがインスタンスを持つことができるということです。モジュールはいくつかのメソッドにすぎません。混乱は、C ++とJavaおよび他の言語がクラスとモジュールの両方に「クラス」という用語を使用していることです

ここで、特定の例を確認MotorOperationsするために、computePowerConsumptionForMotor引数を使用してメッセージを送信できるクラスについて質問しますid。それは悪いですか?少なくとも、Tell Do n't Ask Principleに違反することはありません。我々は、DO 持つモータークラスを作成し、それを送信するためにpowerConsumptionメッセージを?おそらく100%の時間ではありませんが、そのようなことをしようとすると、コードに関する優れた洞察につながる可能性があります。または、それは悪いことになる小さなクラスの爆発につながる可能性があります。

OOPに合わせて概念的に変更/改善する必要がある方法はありますか?

「OOPを実行する」ことが重要な場合は、相互にメッセージを送信することで通信するコンポーネントにシステムを設計する方法を探す必要があります。それがまさにOOP とは何か、または少なくともこの用語の造語者が念頭に置いていたものです。このビューでは、ユーティリティクラスはOOPではありません。しかし、一部の人にとってはそうかもしれません。

すべてのクラスからインスタンス化された数百万の生活、呼吸、オブジェクトから大規模なシステム全体を作成しようとすると、一部のプロジェクトで機能する場合があります。ただし、人為的で誤った発音のクラスを作成している場合は、モジュールを導入する必要があります。クラスを強調し、インスタンス化可能なクラスがばかげている場合はモジュールを使用してください。

TL; DR-メソッドバンドルが常に悪いわけではありません。最初にインスタンス化可能なクラスを使用してみてください。必要な場合にのみ「モジュール」にフォールバックします。


0

与えられた例を取り上げます:

getMotorDataFromHTMLForm()
selectMotorFromUserRequirements($requirements)

これらはMotorオブジェクトを返す「ファクトリ」メソッドのように見えます。2番目は、要件を満たすために新しいオブジェクトを作成するか、データベースまたはモーターのメモリ内コレクションを調べていることを意味します。その場合、それはメソッドでなければなりません。または、要件オブジェクトのメソッドである可能性があります。

getMotorManufacturers()

どこから入手していますか?これが方法のはずです。

canMotorCanHandleOperatingConditions($conditions)
computePowerConsumptionForMotor($id)

これらは上のメソッドであるように見えますMotor


はい。これは「おそらく無関係なメソッドの束」です(略してBOPUM)。工場とモーターのコメントに同意します。 getMotorManufacturersデータベースからすべてのモーター製造元を返すことです。どこに行くのかわかりません。このBOPUMを解いて、必要な場所に物を置くには時間がかかります。-
デニス

getMotorManufacturersデータベースから取得しています。データベースにメソッドを含めることはできません...現在、データベースを照会し、配列を初期化し、モーターオブジェクト(製造元情報も含む)を設定して、その配列を呼び出し元に返すDataMapperパターンがあります。呼び出し元は私のMotorOperationsクラスであり、クラスから順番に呼び出されProductSelectionます(モーターを選択するために使用されるアルゴリズムを含み、読み込まれたモーター情報はそのアルゴリズムのデータです)
デニス

0

オブジェクトは、凝集度の高いメソッドとデータのコレクションです。これらは相互に関連性が高く、状態が保持されるため、クラスに属します。

これは、前もって大きなデザインを使用してすべてをモデル化しようとする場合でも、オブジェクトを繰り返してシステムのニーズに合わせて進化させるエマージェンシーデザインでも同じです。

状態を保持する理由がない場合は、おそらくオブジェクトをインスタンス化する理由がないので、おそらくクラスを持つ理由はないでしょう。そうでない限り、使用している言語には、クラスを使用する以外の名前空間を定義する機能がありません。どのクラスを使用するのがイディオムだからいいでしょう。

この方法でクラスを使用することに対する典型的なもの以外の否定的な側面は考えられません。「名前空間」をインスタンス化することで、不要なコストと複雑さを招きます。このコードをサポートする人はだれでも、データが追加の認知的負荷を負担しているのではないかと思うでしょう(1人につき1回限りの費用)。付加価値のない珍しい使い方です。

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