タグ付けされた質問 「object-oriented-design」

オブジェクト指向設計とは、ソフトウェアの問題を解決するために、相互作用するオブジェクトのシステムを計画するプロセスです。

4
私が書くすべてのクラスはインターフェースに準拠すべきですか?
私はTypescriptでゲームを作成しており、オブジェクトの実装ではなく、インターフェイスに基づいてコードを作成する「インターフェイスベースのプログラミング」のアイデアに固執しようと決心しました。 私は十分な数のインターフェースとそれらを実装するクラスを作成し、一歩下がって、クラスが単純であることを認識しました。実装を変更する必要はおそらくないでしょう。クラスは(Phaser.Spriteタンクのように動作するように制限された方法でを移動します)。 次に、YAGNIのアイデアについて数年前に読んだことを覚えています。これは基本的に、コードを過度に設計して、決して使用しない可能性があるものを含めるべきではないということです。 ベストプラクティスに従って、すべてのクラスがインターフェイスを実装する必要がありますか、それとも将来的にスワップアウトされる可能性があると予想されるクラスに限定する必要がありますか?

3
多対多の深い関係を管理するための設計パターンはありますか?
複数のアプリケーションで作業しているこのデータパターンを定義するのに問題があります。 それはで構成されています: 多くのオブジェクト自体で構成されるオブジェクトタイプ 2番目のオブジェクトタイプ。各インスタンスは最初のオブジェクトの「多く」を持っています また、最初のオブジェクトの各サブオブジェクトは、2番目のオブジェクトタイプへの関連付けごとに変更できます。 簡単な例は次のとおりです。 一連のレッスンで構成されるプログラミングコース レッスンはセットの割り当てで構成されています。 コースを学生に割り当てることができます。 ただし、コースが生徒に割り当てられると、各レッスンや課題は、削除や追加を行って、元のコースが認識できなくなる可能性があるまで、その生徒に合わせてカスタマイズできます。 私の解決策では、これにより次のような結果になります。 コースを生徒に割り当てると、コースはメモリにロードされます。次に、各サブオブジェクトについて、適切なメタデータを使用して生徒/サブオブジェクト関係オブジェクトが生成されます。基本的に、元のオブジェクトをテンプレートとして使用して、必要なカスタマイズ可能なオブジェクトを生成しています。 これにより、サブオブジェクトがより複雑になり、番号が付けられるため、大量のデータが生成されます。このデータパターンを操作するために必要なロジック/複雑さの量を減らすための最適化またはパターンがあるかどうかと思います。

1
Pythonで例外をサブクラス化する必要があるのはいつですか?
私のコードでは、例外を発生させる場所が約7箇所あります。これらの例外はすべて同じように扱われます。エラーをログファイルに出力し、ソフトウェアの状態をデフォルトに戻して終了します。 コードのレビュー中に、私が高く評価している上級エンジニアは、これらの例外をすべてサブクラス化する必要があると述べました。彼の主張は、将来的には例外を別の方法で処理したいと思うかもしれず、それはより簡単になるでしょう。 私の主張は、現時点ではコードが雑然としているだけであり、例外を別の方法で処理するかどうかがわからないため、コードを簡潔にしておきます。 。 いずれの場合も議論はありますか。

3
クリーンなコードとハイブリッドオブジェクトおよび機能羨望
そのため、最近、コードにいくつかの主要なリファクタリングを行いました。私がしようとした主なことの1つは、クラスをデータオブジェクトとワーカーオブジェクトに分割することでした。これは、とりわけ、Clean Codeの次のセクションに触発されました。 ハイブリッド この混乱は、半分のオブジェクトと半分のデータ構造である不幸なハイブリッドデータ構造につながることがあります。それらには重要な機能を果たす関数があり、パブリック変数またはパブリックアクセサーとミューテーターのいずれかがあり、すべての目的と目的のためにプライベート変数をパブリックにして、他の外部関数がそれらの変数を手続き型プログラムが使用する方法で使用するように誘惑しますデータ構造。 そのようなハイブリッドは、新しい関数を追加することを難しくしますが、新しいデータ構造を追加することも難しくします。彼らは両方の世界で最悪です。それらを作成しないでください。それらは、作者が関数や型からの保護を必要としているかどうか、またはさらに悪いことに無知である混乱した設計を示しています。 最近、私はワーカーオブジェクトの1つ(たまたま、Visitorパターンを実装する)のコードを見て、これを確認しました。 @Override public void visit(MarketTrade trade) { this.data.handleTrade(trade); updateRun(trade); } private void updateRun(MarketTrade newTrade) { if(this.data.getLastAggressor() != newTrade.getAggressor()) { this.data.setRunLength(0); this.data.setLastAggressor(newTrade.getAggressor()); } this.data.setRunLength(this.data.getRunLength() + newTrade.getLots()); } 私はすぐに「!このロジックがであるべき機能の羨望自分自身に言ったData-特に、クラスhandleTradeメソッド。handleTradeとupdateRunする必要があり、常に一緒に起こります」。しかし、「データクラスは単なるpublicデータ構造です。それを始めれば、ハイブリッドオブジェクトになるでしょう!」 何が良いのか、そしてその理由は?どちらを行うかをどのように決定しますか?

2
SRPに従う場合、エンティティの検証と保存にはどのように対処すればよいですか?
私は最近、クリーンコードやSOLIDに関するさまざまなオンライン記事を読んでいますが、それについて読むほど、何も知らないように感じます。 ASP.NET MVC 3を使用してWebアプリケーションを構築しているUsersControllerとしましょう。たとえば、次のCreateようなアクションがあるとします。 public class UsersController : Controller { public ActionResult Create(CreateUserViewModel viewModel) { } } そのアクションメソッドでは、入力したデータが有効な場合、ユーザーをデータベースに保存します。 さて、単一の責任の原則に従って、オブジェクトは単一の責任を持つべきであり、その責任はクラスによって完全にカプセル化されるべきです。そのすべてのサービスは、その責任と厳密に一致している必要があります。検証とデータベースへの保存は2つの別々の責任であるため、次のようにそれらを処理するために別々のクラスを作成する必要があると思います。 public class UsersController : Controller { private ICreateUserValidator validator; private IUserService service; public UsersController(ICreateUserValidator validator, IUserService service) { this.validator = validator; this.service= service; } public ActionResult Create(CreateUserViewModel viewModel) { ValidationResult result …

3
長いパラメーターリストと長い状態変数リスト
C ++の本では、ほとんどのパラメーターはクラスの状態変数にリファクタリングできるため、長いパラメーターリストを持つ関数は必要なくなったと著者は述べています。一方、関数型プログラミングの本は、状態変数はバグが発生しやすくコードの並列化が困難な副作用を引き起こすため、悪であると述べています。私は困惑しています。コードは、状態変数を関数パラメーターリストに移動することにより、可能な限り状態変数に依存しないようにする必要がありますか?

5
実世界の値を表す定数を更新することは、開閉原理の違反ですか?
私は労働者の純年収を計算するクラスを持っています。税率を表す定数があります。しかし、ある日、税率が変更されたため、コードを修正する必要があります。 この定数を修正する行為は、クラスを変更して閉じる必要があると仮定しているため、Open-Closed Principleの違反を示していますか?

3
複数のスイッチケースを持つアプリケーションをリファクタリングするにはどうすればよいですか?
整数を入力として受け取り、その入力に基づいて異なるクラスの静的メソッドを呼び出すアプリケーションがあります。新しい番号が追加されるたびに、別のケースを追加して、異なるクラスの異なる静的メソッドを呼び出す必要があります。現在、スイッチには50のケースがあり、別のケースを追加する必要があるたびに、震えます。これを行うより良い方法はありますか? 私はいくつか考えて、このアイデアを思いつきました。私は戦略パターンを使います。スイッチケースを持つ代わりに、キーが入力整数である戦略オブジェクトのマップがあります。メソッドが呼び出されると、オブジェクトが検索され、オブジェクトのジェネリックメソッドが呼び出されます。このようにして、switch case構文の使用を回避できます。 どう思いますか?

2
ゲッターのみのインターフェースはコードの匂いですか?
(私はこの質問を見ましたが、最初の答えはデザインよりも自動プロパティに関するもので、2番目の答えは、データストレージコードをコンシューマから隠すことです。これは、自分のコードが何をしたいのかわからないのですが、他の意見も聞きたいです) 私には2つの非常に類似したエンティティがHolidayDiscountありRentalDiscount、「それが少なくとも続く場合numberOfDays、percent割引が適用される」として長さ割引を表します。テーブルにはさまざまな親エンティティへのアクセス権があり、さまざまな場所で使用されますが、それらが使用される場所には、適用可能な最大の割引を取得するための共通のロジックがあります。たとえば、aにHolidayOfferはの数がありHolidayDiscounts、そのコストを計算するときは、該当する割引を計算する必要があります。レンタルと同じですRentalDiscounts。 ロジックは同じなので一箇所に留めておきたい。これが、次のメソッド、述語、およびコンパレータが行うことです。 Optional<LengthDiscount> getMaxApplicableLengthDiscount(List<LengthDiscount> discounts, int daysToStay) { if (discounts.isEmpty()) { return Optional.empty(); } return discounts.stream() .filter(new DiscountIsApplicablePredicate(daysToStay)) .max(new DiscountMinDaysComparator()); } public class DiscountIsApplicablePredicate implements Predicate<LengthDiscount> { private final long daysToStay; public DiscountIsApplicablePredicate(long daysToStay) { this.daysToStay = daysToStay; } @Override public boolean test(LengthDiscount discount) { return daysToStay >= discount.getNumberOfDays(); …

3
「ファクトリーメソッドはテンプレートメソッドの特殊化」です。どうやって?
2つの間の類似点と相違点: テンプレートメソッド 継承に依存します。 アルゴリズムのステップを定義し、それらを実装するタスクをサブクラスに任せます。 ファクトリーメソッド 継承に依存します。 スーパークラスは、オブジェクトを作成するためのインターフェースを定義します。サブクラスは、インスタンス化する具象クラスを決定します。 2つ並べて: 「ファクトリーメソッドはテンプレートメソッドの特殊化」というフレーズの意味がわかりません(Head First Design Patternsブックにあります)。ではBeverage、私たちの方法持ってprepareいるfinalと一連の手順を定義します。にPizzaStoreあるメソッドがありabstract、サブクラスがそれを再定義します。後者は前者を特化したものですか?

5
抽象化が多すぎてコードの拡張が困難
コードベースの抽象化が多すぎる(または少なくともそれを処理している)と感じている問題に直面しています。コードベースのほとんどのメソッドは、コードベースの最上位の親Aを取り込むように抽象化されていますが、この親の子Bには、これらのメソッドの一部のロジックに影響を与える新しい属性があります。問題は、入力がAに抽象化されているため、これらのメソッドでこれらの属性をチェックできないことです。もちろん、Aにはこの属性がありません。Bを異なる方法で処理する新しいメソッドを作成しようとすると、コードの重複のために呼び出されます。私の技術リーダーによる提案は、ブール型パラメーターを受け取る共有メソッドを作成することですが、これの問題は、これを「隠された制御フロー」と見なす人がいることです。 、また、この共有メソッドは、小さな属性に分割されたとしても、将来の属性を追加する必要がある場合、一度複雑になりすぎたり複雑になったりします。これはまた、カップリングを増やし、結束を減らし、チームの誰かが指摘した単一責任の原則に違反します。 基本的に、このコードベースの抽象化の多くはコードの重複を減らすのに役立ちますが、メソッドの拡張/変更が最高の抽象化を行うようになっている場合は難しくなります。このような状況ではどうすればよいですか?私は非難の中心にいますが、他の誰もが彼らが良いと思うことに同意することはできませんが、それは結局私を傷つけています。

4
複雑なドメイン中心のアプリケーションでの基本的なCRUD操作へのDDDアプローチ
私の会社はWebアプリケーションをゼロから書き直しています。これは、金融業界で複雑なドメインを持つ大規模なエンタープライズレベルのアプリケーションです。 永続化のためにORM(エンティティフレームワーク)を使用しています。 本質的に、アプリケーションの半分はユーザーから生データを収集して保存することに集中しており、実際のドメインロジックのほとんどを含むアプリケーションの残りの半分はその生データを使用して、元のデータとは大きく異なるドメイン画像を作成します生の入力、およびそれを計算エンジンに渡し、計算を実行し、結果を吐き出し、ユーザーに表示します。 レイヤーを使用したDDDアプローチでは、CRUD操作がドメインレイヤーを通過するように見えます。しかし、少なくとも私たちの場合、これは意味をなさないようです。 たとえば、ユーザーが編集画面に移動して投資口座を変更した場合、画面のフィールドはデータベースに保存されているフィールドそのものであり、後で計算に使用されるドメイン表現ではありません。では、編集画面でデータベース表現(生の入力)が必要なときに、なぜ投資口座のドメイン表現を読み込むのでしょうか。 ユーザーが投資口座画面で[完了]をクリックし、コントローラーに対してPOSTが実行されると、コントローラーには、保存する必要のある投資口座のほぼ正確なデータベース表現が表示されます。しかし、何らかの理由で、コントローラーのモデルをデータベースモデル(エンティティフレームワークモデル)に直接マッピングするのではなく、ドメイン表現をロードして変更を加えることになっていますか? つまり、本質的には、データモデルをドメインモデルにマッピングします。これにより、永続化するためにデータモデルにマッピングし直すことができます。それはどういう意味ですか?

1
ビジネスロジックとサービスレイヤー
私はこの答えを読みます:https : //softwareengineering.stackexchange.com/a/234254/173318私の理解を訂正してください。 ビジネスルールとは、現実の世界でのビジネスのステップのリストを指します(コードなし)。 ビジネスロジックは、ビジネスルールをコードに変換するプロセスと、「ビジネスロジック」と呼ばれるこれらのコードの束/種類を指します。 また、サービス層は何に使用されますか?私がこの答えを読んだ場合、それはビジネスロジックと同じように聞こえますhttps://stackoverflow.com/a/4817935/4190539 サービスレイヤーは、ビジネスロジックとリポジトリが出会う場所ですか?

2
イテレーターをデザインパターンにする理由
他の同様の構成と比較してIteratorが特別になるのは何だろうと思っていました。そのため、Gang of Fourがデザインパターンとしてリストされています。 イテレーターは、ポリモーフィズム(共通のインターフェースを持つコレクションの階層)と懸念の分離(コレクションの反復は、データの構造化方法から独立している必要があります)に基づいています。 しかし、コレクションの階層を、たとえば数学オブジェクト(整数、浮動小数点数、複素数、行列など)の階層と反復子を、これらのオブジェクトの関連するいくつかの操作を表すクラス(例えば、指数関数)で置き換えるとどうなるでしょうか。クラス図も同じです。 同じように機能する、Writer、Painter、Encoderなどのより多くの類似の例、おそらくより優れた例を見つけることができます。しかし、これらがデザインパターンと呼ばれるのを聞いたことがありません。 では、イテレータが特別な理由は何ですか? コレクション内の現在の位置を格納するために変更可能な状態を必要とするため、より複雑になるのは事実ですか?しかし、その場合、変更可能な状態は通常望ましいとは見なされません。 私のポイントを明確にするために、より詳細な例を挙げましょう。 ここに私たちの設計問題があります: クラスの階層と、これらのクラスのオブジェクトに対して定義された操作があるとします。この操作のインターフェースは各クラスで同じですが、実装は完全に異なる場合があります。同じオブジェクトに複数の操作を適用すること、たとえば異なるパラメーターを使用することが理にかなっていることも想定されています。 これが私たちの設計問題(実際には反復子パターンの一般化)の賢明な解決策です: 懸念を分離するために、操作の実装を関数として元のクラス階層(オペランドオブジェクト)に追加しないでください。同じオペランドに操作を複数回適用する必要があるため、関数だけでなく、オペランドへの参照を保持するオブジェクトで表す必要があります。したがって、オペランドオブジェクトは、演算を表すオブジェクトを返す関数を提供する必要があります。このオブジェクトは、実際の操作を実行する関数を提供します。 例: MathObject派生クラスMyIntegerとを備えた基本クラスまたはインターフェイス(愚かな名前です。たぶん誰かがより良いアイデアを持っています。)がありMyMatrixます。それぞれについて、正方形、立方体などの計算を可能にMathObjectする操作Powerを定義する必要があります。だから私たちは(Javaで)書くことができました: MathObject i = new MyInteger(5); Power powerOfFive = i.getPower(); MyInteger square = powerOfFive.calculate(2); // should return 25 MyInteger cube = powerOfFive.calculate(3); // should return 125

4
境界付きコンテキストの境界を明確に定義する方法
1か月ほどDDDを読んで調査した後、私は自分のプロジェクトを開始することを決め、これらの制限されたコンテキストでDDDを作成しました> クライアント 製品 注文 課金 各境界付きコンテキストには、プレゼンテーション層、ドメイン層、永続層としてREST APIがあります。 これまでのところ、コードはスムーズに実行されていますが、モノリシックな世界から来ているので、私はまだ次のことを理解しようとしています: 新しいクライアントを作成したい場合、新しい請求書を発行したい場合、たとえば、国のアクセスリストなど、新しい注文を作成したい場合。私は: a)各BCの国のリストを作成する b)国BC-> APIを作成し、それを使用して利用可能な国のリストを取得する c)サードパーティのAPIを使用し、各BCの腐敗防止層を介してデータをプルする 破損防止レイヤーまたはアダプターレイヤーを使用してサードパーティAPIと統合する場合、ドメインモデルにどのデータを含める必要がありますか?たとえば、zendesk APIをクライアントBCと統合したい場合。ドメインにticketIDのみが必要ですか、それともクライアントBCでアクセスして使用するすべてのデータをZendeskから抽出する必要がありますか? MVCアプリが実際にAPI(境界コンテキストのプレゼンテーションレイヤー)からデータを取得している場合、各BCの境界を明確に定義することは非常に困難です。それは、適切に設計されたBCが、追加のAPIを消費する必要なしに単一のMVCコントローラーを提供することを意味しますか?

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