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

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

16
ソフトウェアの複雑さを管理するためにオブジェクト指向言語が本当に必要ですか?
これは非常に非技術的でソフトな質問になりますが、これが適切なプラットフォームかどうかはわかりません。しかし、私はCSの始まりの学生なので、皆さんがそれを許容することを願っています。 最初の学期では、JavaやUMLを介して、カプセル化、データ隠蔽、モジュール性、継承などのOOPの概念を紹介しました。(Javaは私の最初のプログラミング言語です) 私の理解では、OOPはソフトウェアの複雑さを管理する方法です。しかし、その原則は新しいものやユニークなものではなく、ある意味ではすべてのエンジニアリング分野に共通しています。 たとえば、車は非常に複雑な構造であり、その複雑さは、明確に定義された動作とインターフェイスを備えたモジュール化されカプセル化されたコンポーネントの階層によって管理されます。 しかし、新しいプログラミングパラダイムを導入した理由はわかりません。複雑さを管理するために使用されるすべての原則は、手続き型プログラミング言語によって実現できると思います。たとえば、モジュール性のために、プログラムを、コードが別々のファイルに含まれる明確に定義されたタスクを実行する多くの小さなプログラムに分割することができます。これらのプログラムは、明確に定義された入力と出力を介して互いに対話します。カプセル化を実現するために、ファイルを保護(暗号化?)することができます。コードを再利用するために、新しいプログラムで必要になったときにいつでもこれらのファイルを呼び出すことができます。これは、OOPが何であるかをすべてキャプチャしないのですか、それとも非常に明白な何かを見逃していますか? OOPが複雑さを管理しているという証拠を求めていません。私の意見では確かにそうです。しかし、モジュール性、カプセル化、データ隠蔽などの複雑さを管理するために使用されるすべての原則は、手続き型言語によって非常に簡単に実装できると思います。それでは、複雑さを管理せずに管理できるのに、なぜ本当にOOPなのでしょうか?

15
ブールパラメータを使用して動作を決定するのは間違っていますか?
私は時々「違和感を感じる」練習を見てきましたが、それについて何が悪いのかを明確に説明することはできません。または多分それはちょうど私の偏見です。ここに行く: 開発者は、パラメータの1つとしてブール値を使用してメソッドを定義し、そのメソッドは別のメソッドを呼び出すなど、最終的にそのブール値は、特定のアクションを実行するかどうかを決定するためだけに使用されます。これは、たとえば、ユーザーが特定の権限を持っている場合、またはテストモード、バッチモード、またはライブモードの場合(またはそうでない場合)にのみアクションを許可するために、またはシステムが特定の状態。 さて、それを行う別の方法が常にあります。(パラメータを渡すのではなく)アクションを実行するときを照会するか、メソッドの複数のバージョン、またはクラスの複数の実装などを使用します。私の質問はこれをどのように改善するかではなく、むしろそれが本当に間違っているかどうか(私が疑うように)、もしそうなら、何が悪いのか。

14
ギャングオブフォーは「パターンスペース」を徹底的に探索しましたか?
少なくとも10年前にギャングオブフォー(GoF)のデザインパターンを初めて知って以来、これらの23のパターンは、パターンスペースと呼ぶのが非常に大きなものの小さなサンプルにすぎないという印象を持っています。この架空のパターンスペースは、一般的なオブジェクト指向ソフトウェア設計の問題に対するすべての推奨ソリューション(既知または未知)で構成されています。 そのため、既知の文書化された設計パターンの数が大幅に増加すると予想しました。 それは起こりませんでした。GoFの本が出版されてから20年以上経っても、Wikipediaの記事には12個の追加パターンしかリストされていません。(特定のトピックを扱っているため、ここでは同時実行パターンを含めませんでした。) その理由は何ですか? GoFのパターンセットは、実際には私が考えているよりも包括的ですか? 新しいパターンを見つけることに興味がなくなったのは、おそらくそれらがソフトウェア設計にあまり役に立たないことがわかったからでしょうか? 他に何か?

17
戻り値が存在しない関数/メソッドからNULLまたは空の値を返す方が良いですか?
ここで推奨事項を探しています。戻り値が存在しないか判断できない場合に、メソッドからNULLまたは空の値を返す方が良いかどうかに苦労しています。 例として、次の2つの方法を使用します。 string ReverseString(string stringToReverse) // takes a string and reverses it. Person FindPerson(int personID) // finds a Person with a matching personID. ではReverseString()、戻り値の型が文字列であるため、呼び出し側はそれを期待しているため、空の文字列を返します。また、この方法では、呼び出し元はNULLが返されたかどうかを確認する必要がありません。 でFindPerson()、NULLを返す方が適切なようです。NULLまたは空のPersonオブジェクト(new Person())が返されるかどうかに関係なく、呼び出し側は、何かを行う前に(呼び出しなどUpdateName())PersonオブジェクトがNULLまたは空であるかどうかを確認する必要があります。ここでNULLを返すだけで、呼び出し側はNULLをチェックするだけでよいのはなぜですか。 他の誰かがこれに苦労していますか?どんな助けや洞察も大歓迎です。

10
これは、リスコフ代替原則の違反ですか?
TaskエンティティのリストとProjectTaskサブタイプがあるとします。タスクはいつでも閉じることができますが、タスクのProjectTasksステータスが[開始済み]になると閉じることができません。UIは、開始済みを閉じるオプションがProjectTask使用できないことを確認する必要がありますが、ドメインにはいくつかの保護手段があります。 public class Task { public Status Status { get; set; } public virtual void Close() { Status = Status.Closed; } } public class ProjectTask : Task { public override void Close() { if (Status == Status.Started) throw new Exception("Cannot close a started Project Task"); base.Close(); } } これClose()で、タスクを呼び出すときに、開始タスクのProjectTask状態の場合は呼び出しが失敗する可能性がありますが、ベースのタスクの場合は失敗しません。しかし、これはビジネス要件です。失敗するはずです。これは、リスコフ代替原理の違反とみなすことができますか?

6
本当に「ビジネスロジック」とは何ですか?
私はPHPを始めた2009年からWeb開発に取り組んでいます。ASP.NETに移行したとき、この「ビジネスロジック」と「ビジネスルール」に多くの焦点が当てられているDDDとOOADについてよく耳にしました。要点は、これまでに開発したアプリはすべてCRUD操作に関するものであり、実際にこれらのことを見たことがないということです。 それらが実際に実際にどのようなものになるのか、私には想像できません。それでは、このビジネスロジックとはどのようなもので、アプリにどのように適合するのでしょうか?私はこれらがドメインモデルのメソッドとして実装されていることを知っていますが、それらのメソッドは何である可能性があり、アプリケーションのどこで使用される可能性がありますか?

13
クリーンなコードプラクティスに従うことで、より多くのコードが記述されていることをどのように正当化しますか?
モデレーターノート この質問には、すでに17の回答が投稿されています。新しい回答を投稿する前に、既存の回答を読んで、あなたの視点が十分にカバーされていないことを確認してください。 私はRobert Martinの「Clean Code」の本で推奨されているプラ​​クティスのいくつか、特に私が扱うソフトウェアのタイプに当てはまるものと私にとって意味のあるものに従っています(ドグマとしては従いません) 。 しかし、私が気づいた副作用の1つは、私が書いた「クリーンな」コードは、いくつかのプラクティスに従わなかった場合よりも多くのコードであるということです。これにつながる具体的なプラクティスは次のとおりです。 条件のカプセル化 の代わりに if(contact.email != null && contact.emails.contains('@') このような小さなメソッドを書くことができます private Boolean isEmailValid(String email){...} インラインコメントを別のプライベートメソッドに置き換え、メソッド名がその上にインラインコメントを持たずにそれ自体を説明するようにする クラスに変更する理由は1つだけです 他にもいくつかあります。ポイントは、コメントを置換し、条件をカプセル化する小さなメソッドなどのために、30行のメソッドになる可能性があるものがクラスになることです。あなたが非常に多くのメソッドを持っていることに気付いたとき、それは「理にかなっています」本当にメソッドでなければならないのに、すべての機能を1つのクラスに入れます。 私は、極度に行われたいかなる行為も有害である可能性があることを知っています。 私が答えを探している具体的な質問は次のとおりです。 これは、クリーンなコードを書くことの許容可能な副産物ですか?もしそうなら、より多くのLOCが書かれているという事実を正当化するために使用できるいくつかの引数は何ですか? 組織はLOCの増加を特に懸念していませんが、LOCを増やすとクラスが非常に大きくなる可能性があります(これも読みやすいように、1回限りのヘルパー関数を使用せずに長いメソッドに置き換えることができます)。 十分な大きさのクラスを見ると、クラスが十分に忙しく、その責任が終了したという印象を与えます。したがって、他の機能を実現するために、さらにクラスを作成することになります。その結果、多数のクラスが作成され、すべてが多くの小さなヘルパーメソッドを使用して「1つのこと」を実行します。 これは特定の懸念事項です...これらのクラスは、多くの小さなメソッドの助けを借りずに、「1つのこと」を達成する単一のクラスである可能性があります。おそらく3つまたは4つのメソッドといくつかのコメントを持つ単一のクラスである可能性があります。

12
SetWidthメソッドとSetHeightメソッドをオーバーライドすると、Rectangleから継承するSquareに問題があるのはなぜですか?
SquareがRectangleのタイプである場合、なぜSquareはRectangleを継承できないのですか?それとも、なぜそれが悪いデザインですか? 私は人々が言うのを聞いたことがあります: SquareをRectangleから派生させた場合、Squareは予想される任意の場所で使用できるはずです。 ここで問題は何ですか?そして、なぜSquareはあなたが長方形を期待するどこでも使えるのでしょうか?Squareオブジェクトを作成し、SquareのSetWidthメソッドとSetHeightメソッドをオーバーライドする場合にのみ使用できるのは、なぜ問題があるのでしょうか? Rectangle基本クラスにSetWidthメソッドとSetHeightメソッドがあり、Rectangle参照がSquareを指している場合、SetWidthとSetHeightは、一方を設定するともう一方がそれに合わせて変更されるため、意味がありません。この場合、SquareはRectangleによるLiskov Substitution Testに失敗し、RectangleからSquareを継承させるという抽象化は悪いものです。 誰かが上記の議論を説明できますか?繰り返しますが、SquareでSetWidthおよびSetHeightメソッドをオーバーライドすると、この問題は解決しませんか? 私も聞いた/読んだ: 実際の問題は、長方形をモデリングするのではなく、「再整形可能な長方形」、つまり作成後に幅または高さを変更できる長方形をモデリングすることです(それでも同じオブジェクトと見なします)。このように長方形クラスを見ると、正方形は「再成形可能な長方形」ではないことが明らかです。なぜなら、正方形は形を変えられず、依然として正方形であるためです(一般的に)。数学的には、数学的文脈では可変性は意味をなさないため、問題は見られません。 ここでは、「サイズ変更可能」が正しい用語だと思います。長方形は「サイズ変更可能」であり、正方形も同様です。上記の議論に何か欠けていますか?正方形は、任意の長方形と同様にサイズ変更できます。

9
なぜ依存性注入を使用する必要があるのですか?
依存性注入を使用する理由についてリソースを探すのに苦労しています。私が見るほとんどのリソースは、オブジェクトのインスタンスをオブジェクトの別のインスタンスに渡すだけであると説明していますが、なぜですか?これはアーキテクチャ/コードをきれいにするためだけですか、それとも全体としてパフォーマンスに影響しますか? なぜ次のことを行う必要があるのですか? class Profile { public function deactivateProfile(Setting $setting) { $setting->isActive = false; } } 次の代わりに? class Profile { public function deactivateProfile() { $setting = new Setting(); $setting->isActive = false; } }

4
リッチドメインモデル—正確に、動作はどのように適合しますか?
リッチドメインモデルと貧血ドメインモデルの議論では、インターネットは哲学的なアドバイスに満ちていますが、権威のある例は不足しています。この質問の目的は、適切なドメイン駆動設計モデルの決定的なガイドラインと具体例を見つけることです。(理想的にはC#で。) 実際の例では、このDDDの実装は間違っているようです。 以下のWorkItemドメインモデルは、Entity Frameworkがコードファーストデータベースに使用するプロパティバッグに他なりません。ファウラーごとに、それは貧血です。 WorkItemService層は、明らかにドメインサービスの一般的な誤解です。WorkItemのすべての動作/ビジネスロジックが含まれています。イェメリャノフなどによると、手続き型です。(ページ6) 以下が間違っている場合、どうすれば正しくできますか?AddStatusUpdateまたはCheckoutなど の動作はWorkItemクラスに属している必要がありますか? WorkItemモデルにはどのような依存関係が必要ですか? public class WorkItemService : IWorkItemService { private IUnitOfWorkFactory _unitOfWorkFactory; //using Unity for dependency injection public WorkItemService(IUnitOfWorkFactory unitOfWorkFactory) { _unitOfWorkFactory = unitOfWorkFactory; } public void AddStatusUpdate(int workItemId, int statusId) { using (var unitOfWork = _unitOfWorkFactory.GetUnitOfWork<IWorkItemUnitOfWork>()) { var workItemRepo = unitOfWork.WorkItemRepository; var workItemStatusRepo = …

11
C ++ですべてのオブジェクトに対応するベースが推奨されない理由
Stroustrup氏は、「すべてのクラス(Objectクラス)に一意のベースをすぐに発明しないでください。通常、多くの/ほとんどのクラスでそれを使用せずに改善できます。」(C ++プログラミング言語Fourth Edition、Sec 1.3.4) 一般に、すべてを対象とする基本クラスが悪い考えであるのはなぜですか?また、いつ作成するのが理にかなっていますか?

10
提案された設計は通常、同僚の設計よりも悪いです-どうすれば良くなりますか?[閉まっている]
私は数年プログラミングしており、問題の修正や中小規模のスクリプトの作成に関しては一般的には優れていますが、オブジェクト指向の方法で大規模なプログラムを設計することは一般的に得意ではありません。いくつかの質問 最近、私と同じ年数の経験を持つ同僚と私は問題に取り組んでいた。私は彼よりも長い間問題に取り組んでいましたが、彼はより良い解決策を思いついたので、最終的には彼のデザインを使用します。これは本当に私に影響を与えました。私は彼のデザインが優れていると認めていますが、彼と同じくらい良いデザインを思いつきました。私も仕事を辞めることを考えています。理由は定かではありませんが、突然、プレッシャーを感じています。たとえば、後輩が私についてどう思うかなどです。普通ですか?それとも、これについて少し考えすぎていますか? 私の仕事は、Pythonでのプログラミングです。ソースコードを読み込もうとしていますが、デザインスキルをどのように向上できると思いますか?勉強すべき良い本やソフトウェアはありますか? 教えてください あなたの助けに本当に感謝します。

12
エラーをスローすべきかどうかを示すフラグを持っている
私は最近、かなり古い開発者(50歳以上)がいる場所で働き始めました。彼らは、システムがダウンすることができなかった航空を扱う重要なアプリケーションに取り組んできました。その結果、古いプログラマーはこの方法でコーディングする傾向があります。 彼は、オブジェクトにブール値を入れて、例外をスローすべきかどうかを示す傾向があります。 例 public class AreaCalculator { AreaCalculator(bool shouldThrowExceptions) { ... } CalculateArea(int x, int y) { if(x < 0 || y < 0) { if(shouldThrowExceptions) throwException; else return 0; } } } (このプロジェクトでは、その時点では存在できないネットワークデバイスを使用しようとしているため、メソッドは失敗する可能性があります。エリアの例は、例外フラグの例にすぎません) 私にはこれはコードの匂いのようです。毎回例外フラグをテストする必要があるため、単体テストの作成は少し複雑になります。また、何か問題が発生した場合、すぐに知りたいと思いませんか?続行方法を決定するのは呼び出し側の責任ではないでしょうか? 彼の論理/推論は、プログラムがユーザーにデータを表示するという1つのことをする必要があるということです。それを妨げないその他の例外は無視する必要があります。私はそれらが無視されるべきではないことに同意しますが、バブルアップして適切な人によって処理されるべきであり、そのためのフラグを処理する必要はありません。 これは例外を処理する良い方法ですか? 編集:設計上の決定についてより多くのコンテキストを与えるために、このコンポーネントが失敗した場合でも、プログラムは引き続き動作し、メインタスクを実行できるためだと思います。したがって、例外をスローしたくない(そして、それを処理しない?)ので、ユーザーが正常に動作しているときにプログラムを停止させます 編集2:より多くのコンテキストを与えるために、この場合、メソッドはネットワークカードをリセットするために呼び出されます。ネットワークカードが切断および再接続され、異なるIPアドレスが割り当てられると問題が発生します。したがって、古いIPでハードウェアをリセットしようとするため、リセットは例外をスローします。

10
「ユーザーは管理者かどうかを判断すべきではありません。特権またはセキュリティシステムが必要です。」
質問で使用されている例では、最小限のデータを関数に渡し、ユーザーが管理者であるかどうかを判断するための最良の方法に触れています。一般的な答えは次のとおりです。 user.isAdmin() これにより、コメントが何度か繰り返され、何度も投票されました。 ユーザーは、管理者であるかどうかを決定するべきではありません。特権またはセキュリティシステムが必要です。クラスに密接に結合されているからといって、それをそのクラスの一部にすることは良い考えではありません。 私は答えた、 ユーザーは何も決定していません。ユーザーオブジェクト/テーブルには、各ユーザーに関するデータが格納されます。実際のユーザーは、自分に関するすべてを変更することはできません。 しかし、これは生産的ではありませんでした。明らかに、遠近法には根本的な違いがあり、それがコミュニケーションを難しくしています。誰かがuser.isAdmin()が悪い理由を説明し、それが「正しく」行われたように見えるものの簡単なスケッチを描くことができますか? 本当に、私はそれが保護するシステムからセキュリティを分離することの利点を見ることはできません。セキュリティに関するテキストには、セキュリティを最初からシステムに組み込む必要があり、開発、展開、保守、さらには寿命のあらゆる段階で考慮する必要があると書かれています。側面にボルトで固定できるものではありません。しかし、このコメントに対するこれまでの17の賛成票は、私が重要な何かを見逃していると言っています。

9
単一の(パブリック)メソッドのみを持つクラスは問題ですか?
現在、ビデオ監視映像の圧縮とインデックス作成を実行するソフトウェアプロジェクトに取り組んでいます。圧縮は、背景オブジェクトと前景オブジェクトを分割し、背景を静的画像として保存し、前景をスプライトとして保存することで機能します。 最近、私はプロジェクトのために設計したいくつかのクラスのレビューに着手しました。 パブリックメソッドが1つしかないクラスがたくさんあることに気付きました。これらのクラスの一部は次のとおりです。 VideoCompressor(compressタイプの入力ビデオを取り込み、タイプRawVideoの出力ビデオを返すメソッドを使用CompressedVideo)。 VideoSplitter(splitタイプの入力ビデオを取り込みRawVideo、それぞれタイプの2つの出力ビデオのベクトルを返すメソッドを使用RawVideo)。 VideoIndexer(indexタイプの入力ビデオを取り込み、タイプRawVideoのビデオインデックスを返すメソッドを使用VideoIndex)。 私は自分自身だけのような呼び出しを行うために、各クラスをインスタンス化見つけますVideoCompressor.compress(...)、VideoSplitter.split(...)、VideoIndexer.index(...)。 表面的には、クラス名は意図する機能を十分に説明していると思います。実際には名詞です。同様に、それらのメソッドも動詞です。 これは実際に問題ですか?

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