[〜#〜] solid [〜#〜] が何を達成し、モジュール性が重要でその目標が明らかに役立つ状況で定期的に使用することを理解しています。ただし、2つの理由により、コードベース全体に一貫して適用することができません。
時期尚早な抽象化を避けたい。私の経験では、具体的なユースケース(現在またはforeseeableに存在する種類)なしで抽象化線を描画すると、間違った場所に描画されます。そのようなコードを変更しようとすると、抽象化の線が役に立たずに邪魔になります。したがって、私は、抽象化線がどこで役立つかがよくわかるまで、抽象化線を描画しないという側に誤りを犯しがちです。
私のコードがより冗長になり、理解が困難になるなど、重複を排除しない場合、モジュール性の向上を正当化するのは難しい。フローが単純で線形であるため、非常によく因数分解されたラビオリコードよりも、単純で密結合の手続き型またはGodオブジェクトコードの方が理解しやすい場合があります。また、記述もはるかに簡単です。
一方、この考え方はしばしば神の対象につながります。私は一般にこれらを保守的にリファクタリングし、明確なパターンが出現した場合にのみ明確な抽象化ラインを追加します。モジュール性が明らかに必要でなく、大幅な重複がなく、コードが読み取り可能である場合、神のオブジェクトと密結合コードのどこに問題があると思いますか?
編集:個人のSOLID原則に関しては、私はLiskov Substitutionが常識の形式化であり、あらゆる場所に適用する必要があることを強調するつもりです。 、すべてのクラスは、あるレベルの抽象化で単一の責任を持つ必要がありますが、実装の詳細がすべて1つの巨大な2,000行クラスに詰め込まれている非常に高いレベルである可能性があります。基本的に、抽象化は、どこを抽象化するかを選択する意味があります。原則モジュール化が明らかに有用ではない場合、私は質問します。これらはモジュール化に関するものであり、抽象化だけでは意味がないため、オープンクローズ、インターフェース分離、特に依存関係の反転です。
以下は、システム設計のバランスをとる方法を理解するのに役立つ簡単な原則です。
S
。メソッドの数やデータ量の点で非常に大きなオブジェクトが存在しても、この原則を維持できます。 Ruby Stringオブジェクトを例にとります。このオブジェクトには、スティックを振るよりも多くのメソッドがありますが、それでも責任は1つだけです:アプリケーションのテキストの文字列を保持します。メンテナンスの問題は、「後でこのコードで問題が発生した場合、どこでこのコードを見つけることができますか?」本質的には、ソフトウェアのメンテナンスが必要になったときに、足で自分を撃たないようにできることをしようとしています。大きなオブジェクトが妥当な抽象化である場合、誰かがクラスをX行/メソッド/プロパティなどにするべきだというメトリックを思いついたからといって、それらを分割する理由はほとんどありません。どちらかといえば、それらはガイドラインであり、厳格な規則ではありません。
ほとんどの場合、あなたは自分の質問に答えたと思います。 SOLIDは、概念を抽象化のレベルを上げる必要がある場合に、コードをリファクタリングする方法に関する一連のガイドラインです。
他のすべてのクリエイティブ分野と同様に、絶対的なものはなく、トレードオフがあります。実行すればするほど、「現在の問題ドメインまたは要件に十分であるかどうかを判断するのが「簡単」になります。
そうは言っても-抽象化はソフトウェア開発の中心です-ですから、それを行わない正当な理由がないなら、練習はあなたをより良くし、トレードオフの直感を得るでしょう。それが有害にならない限り、それを支持してください。
I want to avoid premature abstraction.In my experience drawing abstraction lines without concrete use cases...
これは部分的に正しいと部分的に間違っています。
間違っている
これは、OO principals/SOLIDを適用できないようにする理由ではありません。適用を防ぐだけです早すぎる
これは...
右
コードがリファクタリング可能になるまでリファクタリングしないでください。要件が完了すると、または、あなたが言うように「ユースケース」がすべてそこにあるとき。
I find simple, tightly coupled procedural or God object code is sometimes easier to understand than very well-factored...
単独またはサイロで作業する場合
しないことの問題OOはすぐにはわかりません。プログラムの最初のバージョンを書いた後、
Code is fresh in your head Code is familiar Code is easy to mentally compartmentalize You wrote it
これらの良いものの3/4は短時間ですぐに死んでしまいます。
最後に、神のオブジェクト(多くの機能を持つオブジェクト)があることを認識し、個々の機能を認識します。カプセル化。それらをフォルダに入れます。時々インターフェースを使用します。自分で長期的なメンテナンスをしてください。特に、リファクタリングされていないメソッドは無限に膨らみ、神のメソッドになる傾向があるためです。
チーム内
しないことの問題OOはすぐにわかります。良いOOコードは少なくともいくらか自己文書化し、読みやすいです。特に、適切なグリーンコードまた、構造の欠如により、タスクの分離と統合がはるかに複雑になります。
ラージオブジェクトと密結合コードが適切で、適切に設計されたものが何も必要ない場合には、何の問題もありません。これは、 経験則が教義に変わることの別の兆候です。
疎結合と小さくシンプルなオブジェクトは、多くの一般的なケースで特定の利点を提供する傾向があるため、一般的にはそれらを使用することをお勧めします。問題は、原則が適用されない場合でも、原則の背後にある根拠を盲目的に適用しようとする人々に盲目的に適用しようとする人々にあります。
私はあなたがこれを必要としないという観点からこれにもっと近づく傾向があります。この投稿では特に、継承という1つの項目に焦点を当てます。
私の最初のデザインでは、2つ以上あることがわかっているものの階層を作成します。多くの場合、同じコードの多くが必要になるため、最初から設計する価値があります。 最初のコードが配置された後、そして私はより多くの機能を追加する必要があります、私は私が持っているものを見て、「私はすでに同じまたは類似の機能を実装していますか?」もしそうなら、それはおそらくリリースされるように頼んでいる新しい抽象化です。
これの良い例は、MVCフレームワークです。最初から、コードビハインドを使用して1つの大きなページを作成します。しかし、別のページを追加したいとします。ただし、背後にある1つのコードは、新しいページに必要な多くのロジックを既に実装しています。したがって、ロジックを実装するController
クラス/インターフェイスを抽象化しますそのページに固有元の「神」のコードビハインドに共通のものを残します。
コードの将来のために、原則を適用しないタイミングを開発者として知っているなら、それはあなたにとって良いことです。
SOLIDは、複雑さを回避してコードの品質を向上させるために抽象化する必要がある場合に、それがあなたの述べた値で低下し始めている場合に知っておくために心に残ることを望みます。
さらに重要なのは、大多数の開発者が1日の仕事をしていて、あなたほど気にしていないことを考慮してください。最初に長時間実行するメソッドを設定した場合、それを維持または拡張するときにコードに参加する他の開発者は何を考えますか?はい、BIGGER関数、LONGER実行クラスなどを推測しました神のオブジェクト、そしてそれらは成長するコードをキャッチしてそれを正しくカプセル化することができるという原則を心に留めていません。あなたは「読める」コードが腐った混乱になりました。
したがって、悪い開発者はそれを行うことになると主張するかもしれませんが、少なくとも最初から物事がシンプルでよく整理されていれば、より良い利点があります。
グローバルな「Registry Map」や「God Object」が単純であれば、特に気にしません。それは本当にシステム設計に依存します。時にはそれを回避して単純なままでいられることもあれば、できないこともあります。
大きな機能と神のオブジェクトはテストするのが非常に難しいことを証明できることも忘れないでください。コードをリファクタリングおよび変更するときにアジャイルを維持し、「安全」に感じたい場合は、テストが必要です。関数やオブジェクトが多くのことを行う場合、テストを書くことは困難です。
神オブジェクトの問題は、通常、それを有利に分割できることです。定義により、それは複数のことを行います。それをより小さなクラスに分割する目的は、1つのことをうまく行うクラスを持つことができるようにすることです(そして、「1つのこと」の定義も拡張しないでください)。つまり、特定のクラスについて、そのクラスが行うべきことが1つわかったら、それをかなり簡単に読み取って、そのクラスが正しく実行されているかどうかを判断できるようになります。
私はそこにあると思いますisあまりにも多くのモジュール性とあまりにも多くの柔軟性のようなものですが、それはあなたが過剰な設計と過剰なエンジニアリングの問題であり、あなたがあなたがしていない要件を考慮している場合ですt顧客が望んでいることさえ知っている。多くの設計アイデアは、コードの実行方法の変更を簡単に制御できるようにすることを目的としていますが、誰も変更を予期していない場合、柔軟性を含めることは無意味です。
私はより単純なガイドラインを使用します。そのための単体テストを記述でき、コードの重複がない場合、それは十分に抽象的です。さらに、後のリファクタリングに適した位置にいます。
それ以上は、SOLIDを念頭に置く必要がありますが、ルールというよりもガイドラインとしてのほうが重要です。
モジュラー性が明らかに必要ではなく、大幅な重複がなく、コードが読み取り可能である場合、神のオブジェクトと密結合コードのどこに問題があるのでしょうか。
アプリケーションが十分に小さい場合は、何でも保守できます。より大きなアプリケーションでは、神のオブジェクトはすぐに問題になります。最終的に新しい機能を実装するには、17個のGodオブジェクトを変更する必要があります。人々は17ステップの手順に従ってあまりうまくいきません。神のオブジェクトは常に複数の開発者によって変更されており、それらの変更は繰り返しマージされる必要があります。あなたはそこに行きたくない。
過度で不適切な抽象化についての懸念を共有しますが、時期尚早な抽象化については必ずしもそれほど懸念しているわけではありません。
それはおそらく矛盾のように聞こえますが、抽象化を使用しても、過度にコミットしすぎない限り、つまり必要に応じてリファクタリングを行うことができれば、問題が発生する可能性は低くなります。
これが意味することは、コードのある程度のプロトタイピング、実験、およびバックトラッキングです。
とはいえ、すべての問題を解決するために従うべき単純な決定論的ルールはありません。経験は非常に重要ですが、間違いを犯してその経験を積まなければなりません。そして、以前の間違いでは準備ができなかったことを犯すために、常にもっと間違いがあります。
それでも、教科書の原則を出発点として扱い、プログラミングについて学び、それらの原則がどのように機能するかを確認します。 SOLIDのようなものよりも優れた、より正確で信頼性の高いガイドラインを提供することが可能である場合、誰かがおそらくすでにそうしているでしょう。 。
よくできました。プログラムを設計およびコーディングするための明確で確定的なアルゴリズムを提供できる人がいれば、人間が書く最後のプログラムは1つしかありません。人間が介入することなく、将来のすべてのプログラムを自動的に書くプログラムです。
適切な抽象化線を引くことは、経験から引き出すものです。あなたはそうすることで間違いをするでしょう、それは否定できません。
SOLIDは、その経験を集中的に形にしたものであり、この経験を苦労して得た人々からあなたに渡されます。抽象化が必要になる前に抽象化を作成しないようにすると言ったとき、あなたはそれをかなり釘付けにしました。さて、経験SOLIDは、問題の解決を手助けしてくれますあなたは決して新しいことはありませんでした。しかし、私を信じてください...非常に現実的です。
SOLIDはモジュール性に関するものであり、モジュール性は保守性に関するものであり、保守性とは、ソフトウェアが本番環境に達し、クライアントが未発見のバグに気付くと、人道的な作業スケジュールを維持できるようにすることです。
モジュール性の最大の利点は、テスト容易性です。システムのモジュール性が高ければ高いほど、テストが容易になり、堅固な基盤を迅速に構築して、問題のより難しい側面に取り組むことができます。あなたの問題はこのモジュール性を要求しないかもしれませんが、それがあなたがより良いテストコードをより速く作成することを可能にするという事実だけがモジュール性のために努力するためのブレインではありません。
アジャイルであることはすべて、迅速な出荷と高品質の提供との間の微妙なバランスをとろうとすることです。アジャイルは、私たちが手を抜く必要があるという意味ではありません。実際、私が関わってきた最も成功したアジャイルプロジェクトは、そのようなガイドラインに細心の注意を払ったプロジェクトです。
見過ごされているように見える重要な点は、SOLIDはTDDとともに実践されていることです。TDDは、特定のコンテキストで「適切」なものを強調し、表示される多くの疑問を緩和するのに役立ちますアドバイスすること。