タグ付けされた質問 「solid」

一連の設計原則のニーモニック:単一責任、オープンクローズ、リスコフ置換、インターフェース分離、依存関係逆転

8
何も表さないクラス-それは正しいですか?
アプリケーションを設計しているだけで、SOLIDとOOPを正しく理解しているかどうかはわかりません。クラスは1つのことを実行し、適切に実行する必要がありますが、一方で、クラスは実際のオブジェクトを表します。 私の場合、データセットで特徴抽出を行い、機械学習分析を行います。私は3つのクラスを作成できると思います FeatureExtractor データセット アナライザ しかし、FeatureExtractorクラスは何も表さず、クラスというよりもルーチンのようなものにします。使用される関数はextract_features()1つだけです。 一つのことではなく一つのことを表すクラスを作成するのは正しいですか? 編集:それが重要かどうかはわかりませんが、私はPythonを使用しています そして、extract_features()がそのように見える場合:そのメソッドを保持する特別なクラスを作成する価値はありますか? def extract_features(df): extr = PhrasesExtractor() extr.build_vocabulary(df["Text"].tolist()) sent = SentimentAnalyser() sent.load() df = add_features(df, extr.features) df = mark_features(df, extr.extract_features) df = drop_infrequent_features(df) df = another_processing1(df) df = another_processing2(df) df = another_processing3(df) df = set_sentiment(df, sent.get_sentiment) return df

8
クラスの本当の責任は何ですか?
私は、OOPの名詞に基づいた動詞を使用することが合法かどうか疑問に思っています。 私はこの素晴らしい記事に出くわしましたが、それが主張する点にはまだ賛成しません。 この問題をもう少し説明するために、この記事では、たとえばFileWriterクラスが存在するべきではないと述べていますが、書き込みはアクションなので、クラスのメソッドである必要がありFileます。RubyプログラマーはFileWriterクラスの使用に反対する可能性が高い(RubyはメソッドFile.openにファイルへのアクセスを使用する)のに対し、Javaプログラマーはそうではないため、多くの場合言語に依存していることに気付くでしょう。 私個人の(そしてもちろん、非常に謙虚な)視点は、そうすることは単一責任の原則を破ることだということです。PHPでプログラミングしたとき(PHPは明らかにOOPに最適な言語だからです)、この種のフレームワークをよく使用します。 <?php // This is just an example that I just made on the fly, may contain errors class User extends Record { protected $name; public function __construct($name) { $this->name = $name; } } class UserDataHandler extends DataHandler /* knows the pdo object */ { public function …

5
依存関係の逆転は、高階関数とどのように関連していますか?
今日、F#開発におけるSOLID原則の関連性を説明したこの記事を見ました。 F#および設計原則–ソリッド そして最後の1つである「依存性反転の原理」に取り組んでいる間、著者は次のように述べています。 機能的な観点から、これらのコンテナとインジェクションの概念は、単純な高次関数、または言語に直接組み込まれている中間者型パターンで解決できます。 しかし、彼はそれをさらに説明しませんでした。だから、私の質問は、依存関係の逆転は高階関数にどのように関連していますか?

11
各クラスの責任が1つだけであることを確認してください、なぜですか?
Microsoftのドキュメント、WikipediaのSOLIDプリンシペ記事、またはほとんどのITアーキテクトによると、各クラスに1つの責任のみを持たせる必要があります。誰もがこの規則に同意するように見える場合、誰もこの規則の理由について同意するように思われないので、私はその理由を知りたいです。 メンテナンスの改善を挙げている人もいれば、簡単なテストを提供したり、クラスをより堅牢にしたり、セキュリティを強化したりする人もいます。何が正しいのか、実際にはどういう意味ですか?なぜメンテナンスが改善され、テストが簡単になり、コードがより堅牢になるのですか?


5
定数をどこに置くべきか、そしてその理由は?
私たちの大部分が大規模なアプリケーションでは、通常、「定数」の場所はわずかしかありません。 GUIおよび内部定数(タブページのタイトル、グループボックスのタイトル、計算係数、列挙)の1つのクラス データベースのテーブルと列用の1つのクラス(この部分は生成されたコードです)およびそれらの読み取り可能な名前(手動で割り当てられた) アプリケーションメッセージ(ロギング、メッセージボックスなど)の1つのクラス 定数は通常、これらのクラスの異なる構造体に分けられます。C ++アプリケーションでは、定数は.hファイルでのみ定義され、値は.cppファイルで割り当てられます。 利点の1つは、すべての文字列などが1つの中央の場所にあり、何かを変更する必要があるときに誰もがどこにあるかを知っていることです。 これは特に、プロジェクトマネージャーが人々が行き来する際に好むように思われるものであり、このようにして誰もがアプリケーションの構造を掘り下げることなく、このような些細なことを変更できます。 また、同様のグループボックス/タブページなどのタイトルを一度に簡単に変更できます。別の側面は、そのクラスを印刷して、キャプションが直感的であるか、ユーザーへのメッセージが詳細すぎるか、混乱しすぎていないかなどを確認できる非プログラマーに渡すことができることです。 ただし、いくつかの欠点があります。 すべての単一クラスは、定数クラスに密接に結合されています 定数の追加/削除/名前の変更/移動には、アプリケーションの少なくとも90%の再コンパイルが必要です(注:少なくともC ++の場合、値の変更は行われません)。1500クラスのC ++プロジェクトの1つでは、これは約7分間のコンパイル時間(プリコンパイル済みヘッダーを使用し、ヘッダーなしでは約50分)に加えて、特定の静的ライブラリに対する約10分間のリンクを意味します。 Visual Studio Compilerを使用して速度が最適化されたリリースをビルドするには、最大3時間かかります。膨大なクラス関係がソースであるかどうかはわかりませんが、そうであるかもしれません。 何かを非常に迅速にテストしたいので、そのテスト(そしておそらくその後のすべてのテスト)だけで15分待ちたくないので、一時的に直接コードに文字列をハードコーディングすることになります。「後で修正します」という考え方に何が起こるかは誰もが知っています。 別のプロジェクトでクラスを再利用するのは必ずしも簡単ではありません(主に他の密結合によるものですが、定数の処理はそれを容易にするものではありません)。 そのような定数をどこに保存しますか?また、プロジェクトマネージャーに、上記の利点に適合するより優れた概念があることを納得させるために、どのような議論を提起しますか? C ++固有の回答または独立した回答をお気軽にお寄せください。 PS:私はこの質問が一種の主観的なものであることを知っていますが、正直に言って、この種の質問についてこのサイトよりも良い場所を知りません。 このプロジェクトの更新 コンパイル時間に関するニュースがあります 。Calebとgbjbaanbの投稿に続いて、時間があるときに定数ファイルをいくつかの他のファイルに分割しました。私は最終的にプロジェクトをいくつかのライブラリに分割しましたが、これは今でははるかに簡単になりました。これをリリースモードでコンパイルすると、データベース定義(テーブル、列名など-8000を超えるシンボル)を含む自動生成ファイルと特定のハッシュを構築することにより、リリースモードで膨大なコンパイル時間が発生することがわかりました。 DB定数を含むライブラリのMSVCオプティマイザーを非アクティブ化すると、リリースモードでのプロジェクト(複数のアプリケーション)の合計コンパイル時間を最大8時間から1時間未満に短縮できるようになりました。 MSVCがこれらのファイルを最適化するのにこれほど苦労する理由はまだわかりませんが、今のところ、ナイトリービルドのみに依存する必要がないため、この変更により大きなプレッシャーが軽減されます。 その事実、およびより緊密でない結合、より良い再利用性などのその他の利点も、「定数」の分割に時間を費やすことは、結局のところそれほど悪い考えではないことを示しました;-) Update2 この質問にはまだ注目が集まっ ているので、ここ数年私がやってきたことは次のとおりです。 関連するスコープにすべての定数、変数などを正確に配置します。単一のメソッドでのみ定数を使用する場合、そのメソッドで定義することは問題ありません。単一のクラスに興味がある場合は、そのクラスのプライベート実装の詳細として残します。同じことが名前空間、モジュール、プロジェクト、会社の範囲にも当てはまります。ヘルパー関数などにも同じパターンを使用します。(パブリックフレームワークを開発する場合、これは100%適用されない場合があります。) これにより、再利用性、テスト容易性、および保守性が向上し、コンパイル時間(少なくともC ++)が少なくなるだけでなく、バ​​グ修正にかかる時間が短縮され、新しい機能を実際に開発する時間が増えます。同時に、より多くのコードをより簡単に再利用できるため、これらの機能の開発は高速になります。これは、中央定数ファイルが持つ利点よりも重要です。 詳細を知りたい場合は、特にインターフェイス分離の原則と単一責任の原則をご覧ください。 あなたが同意する場合、この更新は基本的に彼が言ったことに対するより一般的な見解なので、カレブの答えに賛成です。

6
ブロック内の追加行とクリーンコード内の追加パラメーター
コンテキスト できれいなコード、35ページ、それは言います これは、ifステートメント、elseステートメント、whileステートメントなど内のブロックが1行の長さであることを意味します。おそらくその行は関数呼び出しであるべきです。これにより、囲んでいる関数が小さく保たれるだけでなく、ブロック内で呼び出される関数にわかりやすい名前を付けることができるため、ドキュメントの価値も高まります。 私は完全に同意します、それはとても理にかなっています。 後で40ページで、関数の引数について説明します 関数の理想的な引数の数はゼロ(niladic)です。次に1つ(単項)、2つ(2項)が続きます。可能な場合は、3つの引数(3項)を避ける必要があります。3つ以上(ポリアディック)には非常に特別な正当化が必要です。引数は難しいです。彼らは多くの概念的な力を取ります。 私は完全に同意します、それはとても理にかなっています。 問題 しかし、しばしば私は別のリストからリストを作成していることに気づき、2つの悪の1つと一緒に暮らさなければなりません。 ブロック内で2つの行を使用します。1つは物を作成するため、もう1つは結果に追加するためです。 public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms) { List<Flurp> flurps = new List<Flurp>(); foreach (BadaBoom badaBoom in badaBooms) { Flurp flurp = CreateFlurp(badaBoom); flurps.Add(flurp); } return flurps; } または、事物が追加されるリストの関数に引数を追加し、「1つの引数が悪化する」ようにします。 public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms) { List<Flurp> flurps = new List<Flurp>(); foreach (BadaBoom badaBoom in …
33 clean-code  solid 

9
クラスを設計して、個々のプロパティではなくクラス全体をパラメータとして取得する
たとえば、広く共有されているクラスと呼ばれるアプリケーションがあるとしUserます。このクラスは、ユーザー、ID、名前、各モジュールへのアクセスレベル、タイムゾーンなどに関するすべての情報を公開します。 ユーザーデータは明らかにシステム全体で広く参照されていますが、何らかの理由で、このユーザーオブジェクトをそれに依存するクラスに渡すのではなく、個々のプロパティを単に渡すようにシステムが設定されています。 ユーザーIDを必要とするクラスは、userIdパラメーターとしてGUID を必要としますが、ユーザー名も必要な場合があります。そのため、別のパラメーターとして渡されます。場合によっては、これは個々のメソッドに渡されるため、値はクラスレベルでまったく保持されません。 Userクラスから別の情報にアクセスする必要があるたびに、パラメーターを追加して変更する必要があり、新しいオーバーロードの追加が適切でない場合は、メソッドまたはクラスコンストラクターへのすべての参照も変更する必要があります。 ユーザーはほんの一例です。これは、コードで広く実践されています。 これはオープン/クローズの原則に違反していると思うのは正しいですか?既存のクラスを変更するだけでなく、そもそもクラスを設定して、将来的に広範囲の変更が必要になる可能性が非常に高くなりますか? Userオブジェクトを渡したばかりの場合は、作業しているクラスに少し変更を加えることができます。パラメータを追加する必要がある場合は、クラスへの参照に数十の変更を加える必要があります。 この慣行によって他の原則が破られていますか?おそらく依存関係の逆転?抽象化を参照しているわけではありませんが、ユーザーは1種類しかないため、ユーザーインターフェイスを持つ必要はありません。 基本的な防衛プログラミングの原則など、違反している他の非ソリッドの原則はありますか? 私のコンストラクタは次のようになります: MyConstructor(GUID userid, String username) またはこれ: MyConstructor(User theUser) 投稿編集: 「パスIDまたはオブジェクト?」で質問に回答することが提案されています。これは、どちらの方向に進むかの決定が、この質問の中心にあるSOLID原則に従う試みにどのように影響するかという質問には答えません。
30 java  c#  design  solid 


9
リスコフの代替原則に違反した場合、何が問題になる可能性がありますか?
私は、リスコフ代替原理の違反の可能性について、この非常に投票された質問に従っていました。Liskov Substitutionの原則が何であるかは知っていますが、開発者としてオブジェクト指向コードを書いている間にこの原則を考えないと、何が間違っているのかが私の心ではまだはっきりしていません。

3
静的メソッドを持つ静的クラスはSOLIDと見なされますか?
SOLIDには、 「プログラム内のオブジェクトは、そのプログラムの正確性を変更することなく、サブタイプのインスタンスで置き換えられるべきである」という概念を持つLiskov置換原則が含まれています。 静的メソッド(Mathクラスに少し似ている)を持つ静的クラスにはインスタンスがまったくないため、静的メソッドを持つ静的クラスがある場合、システムはSOLIDと見なされますか?

12
ソリッドと早すぎる抽象化の回避
SOLIDが何を達成することになっているのかを理解し、モジュール性が重要であり、その目標が明らかに役立つ状況で定期的に使用します。ただし、次の2つの理由により、コードベース全体に一貫して適用できません。 時期尚早な抽象化を避けたい。私の経験では、具体的なユースケース(現在または近い将来に存在する種類)なしで抽象化ラインを描画すると、間違った場所に描画されます。このようなコードを変更しようとすると、抽象化ラインが助けになるのではなく邪魔になります。したがって、どこに有用なのかがよくわかるまで、抽象化ラインを描画しないという側面を誤解する傾向があります。 私のコードをより冗長にし、理解しにくくするなど、重複を排除しない場合、モジュール性を高めることを正当化するのは難しいと思います。フローが単純で線形であるため、非常に適切にファクタリングされたラビオリコードよりも、シンプルで密結合された手続き型またはGodオブジェクトコードの方が理解しやすい場合があります。書くのもずっと簡単です。 一方、この考え方はしばしば神の対象につながります。私は通常、これらを控えめにリファクタリングし、明確なパターンが出現する場合にのみ明確な抽象化ラインを追加します。明らかにモジュール性を必要とせず、大幅な重複がなく、コードが読み取り可能な場合、Godオブジェクトと密結合コードで何か問題があるとしたらどうでしょうか。 編集:個々のSOLID原則に関しては、Liskov Substitutionは常識の形式化であり、どこにでも適用されるべきであると強調するつもりでした。また、すべてのクラスは、何らかの抽象化レベルで単一の責任を負う必要がありますが、実装の詳細がすべて1つの巨大な2,000行クラスに詰め込まれた非常に高いレベルかもしれません。基本的に、抽象化は、抽象化を選択した場所で意味をなす必要があります。モジュール性が明確に役に立たない場合に私が疑問に思う原則は、オープンクローズ、インターフェース分離、特に依存関係の逆転です。これらは抽象化が意味をなさないだけでなく、モジュール性に関するものだからです。

8
SOLID原則の一部またはすべてがコードをきれいにするのに相反するOOPのフレーバーはありますか?
私は最近、ビデオゲーム開発におけるOOPについて友人と議論しました。 友人の驚いたことに、多くの小さなクラスといくつかの抽象化レイヤーを含むゲームのアーキテクチャを説明していました。これは、すべてに単一の責任を与え、コンポーネント間の結合を緩めることに集中した結果だと主張しました。 彼の懸念は、多数のクラスがメンテナンスの悪夢につながることでした。私の見解では、それはまったく逆の効果をもたらすだろうということでした。何世紀にもわたって思われたものについてこれについて議論を続け、最終的には同意しないことに同意し、SOLID原則と適切なOOPが実際にうまく混合されない場合があったと考えています。 SOLID原則に関するWikipediaのエントリでさえ、それらは保守可能なコードの作成を支援するガイドラインであり、アジャイルおよび適応プログラミングの全体的な戦略の一部であると述べています。 だから、私の質問は: OOPで、SOLID原則の一部またはすべてがコードのクリーン化に役立たない場合はありますか? Liskov Substitution Principleが安全な継承の別のフレーバーと競合する可能性があることはすぐに想像できます。つまり、誰かが継承を通じて実装された別の有用なパターンを考案した場合、LSPがそれと直接競合する可能性が非常に高いです。 他にありますか?おそらく、特定のタイプのプロジェクトまたは特定のターゲットプラットフォームは、より少ないソリッドアプローチでより適切に機能しますか? 編集: 私は自分のコードを改善する方法を尋ねていないことを指定したいだけです;)私がこの質問でプロジェクトに言及した唯一の理由は、少しコンテキストを与えることでした。私の質問は、一般的に OOPと設計原則についてです。 あなたは私のプロジェクトについて興味している場合は、参照これを。 編集2: この質問には、次の3つの方法のいずれかで答えると思いました。 はい、SOLIDと部分的に競合するOOP設計原則が存在します はい、SOLIDと完全に競合するOOP設計原則が存在します いいえ、SOLIDはミツバチのひざであり、OOPは永遠に優れています。しかし、すべてと同様に、万能薬ではありません。責任を持って飲んでください。 オプション1と2は、長くて興味深い回答を生成する可能性があります。一方、オプション3は、短くて面白くないが、全体的に安心できる答えです。 オプション3に収束しているようです。

11
銀行の世界でコード設計の努力または怠lazを選択する
私は素晴らしい投資銀行で2年間働いてきました。 私は、最適化されたコードを作成し、適応された優れたデザインパターン、ソリッド原則、デメテルの法則を尊重し、あらゆる種類のコードの重複を回避することを望んで、いくつかの技術プロジェクトを作りました 本番環境での配信=>バグがゼロの場合、すべてが期待どおりに行われています。 しかし、大部分の開発者は、すべてのコードが読解には複雑すぎることを正確にするために来ました。たとえば、「ifおよびinstanceofをいくつか作成し、ポリモーフィズムを忘れて、緊急の生産バグを修正するのが非常に簡単になるようにします」。私は答えることを好まなかった...... これらの開発者はまったく好奇心がないことを知っており、優れた設計を理解する努力を拒否しています(たとえば、90%の開発者は戦略パターンとは何かを知りません。 )、私のプロジェクトマネージャーは、私は本当に間違ったやり方であり、世銀の世界にとって理想主義すぎると言った。 私に何をアドバイスしますか?本当に良いコードの欲求を維持するか、そうである開発者の大多数に私を適応させるならば、私によると、私による開発者の仕事のすべての美しさである設計コードによって本当に面白くないです。 それとも逆に、基本的なオブジェクト指向の原則とベストプラクティスを習得して、自分のコードに適応する必要がありますか?

5
フォールバックのある特別なケースは、リスコフ代替原理に違反しますか?
FooInterface次のシグネチャを持つインターフェイスがあるとします。 interface FooInterface { public function doSomething(SomethingInterface something); } そして、ConcreteFooそのインターフェースを実装する具体的なクラス: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { } } ConcreteFoo::doSomething()特別なタイプのSomethingInterfaceオブジェクトが渡された場合、ユニークな何かをしたいと思います(と呼ばれますSpecialSomething)。 メソッドの前提条件を強化するか、新しい例外をスローする場合、それは間違いなくLSP違反ですが、SpecialSomething汎用SomethingInterfaceオブジェクトのフォールバックを提供しながらオブジェクトを特別にケースに入れた場合でもLSP違反になりますか?何かのようなもの: class ConcreteFoo implements FooInterface { public function doSomething(SomethingInterface something) { if (something instanceof SpecialSomething) { // Do SpecialSomething magic } else { // Do generic SomethingInterface …

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