オブジェクト指向プログラムの場合:抽象化が多すぎますか?どれだけ適切ですか?
私はいつの時代も根っからの人でした。高レベルのカプセル化と抽象化の背後にある概念を理解しましたが、多すぎるとプログラムを混乱させるだけだといつも直感的に感じていました。
私はいつも、空のクラスやレイヤーを残さない抽象化のために撮影しようとしました。疑わしい場合は、階層に新しいレイヤーを追加するのではなく、既存のレイヤーに何かを適合させようとします。
しかし、最近、より高度に抽象化されたシステムに遭遇しています。階層の後半で表現が必要になる可能性のあるすべてのものが最初に取得されるシステム。これは多くの空のレイヤーにつながり、最初は悪いデザインのように見えます。しかし、考え直してみると、これらの空のレイヤーを残すことで、リファクタリングをあまり行わなくても、将来的にフックする場所が増えることに気づきました。これにより、古いものを調整するために必要な作業をほとんど行わなくても、古い機能の上に新しい機能を追加できるようになります。
これの2つのリスクは、必要なレイヤーを誤って取得する可能性があることです。この場合、コードを拡張するためにかなりのリファクタリングを行う必要がまだあり、使用されていないレイヤーがまだたくさんあります。しかし、最初の抽象化を思いつくのに費やす時間、それを台無しにする可能性、そして正しく理解すれば後で節約できる時間によっては、試してみる価値があるかもしれません。
私が考えることができる他のリスクは、それをやり過ぎて、すべての追加のレイヤーを必要としないというリスクです。しかし、それは本当に悪いのでしょうか?余分なクラスレイヤーは本当に高すぎるので、使用しない場合は多くの損失になりますか?ここでの最大の費用と損失は、レイヤーを作成する前に失われる時間です。しかし、その時間の多くは、より低レベルのコードではなく、抽象化されたコードで作業できるときに、後で節約できる可能性があります。
それが多すぎるのはいつですか?空のレイヤーと余分な「必要性」の抽象化が過剰になるのはいつですか?少なすぎは少なすぎます?スイートスポットはどこですか?
必要な抽象化の量を判断するのに役立つ、キャリアの過程で見つけた信頼できる経験則はありますか?
それで、それは多すぎるのですか?空のレイヤーと余分な「必要性」の抽象化が過剰になるのはどの時点ですか?少なすぎますか?スイートスポットはどこですか?
これらの質問に対する決定的な答えはないと思います。 「多すぎる」「少なすぎる」という感覚を養うには経験が必要です。たぶん、いくつかのメトリックまたは品質管理ツールの使用が役立つかもしれませんが、一般化するのは難しいです。それは主にそれぞれのケースに依存します。
回答の探求にあなたを鼓舞するかもしれないいくつかのリンクはここにあります:
開発はすべて、ソフトウェアエンジニアリングの取り組みに存在するさまざまな緊張の間の適切なバランスを見つけることです。
抽象化の要点はfactor out数学演算のように、特定のものからの共通プロパティです:
ab + ac => a(b + c)
これで、3つではなく2つの操作で同じことを行います。この因数分解により、式が単純になりました。
抽象化の典型的な例はファイルシステムです。たとえば、プログラムでペンドライブ、SDカード、ハードドライブなど、さまざまな種類のストレージデバイスに書き込むことができます。
ファイルシステムがない場合は、直接ディスク書き込みロジック、ペンドライブ書き込みロジック、SDカード書き込みロジックを実装する必要があります。しかし、これらすべてのロジックには共通点があります。それらはファイルとディレクトリを作成するため、抽象化レイヤーを作成し、ハードウェアベンダーに特定のことを実行するためのインターフェイスを提供することで、この共通のものを抽象化できます。
より多くのものは共通の特性を共有します。抽象化は、次のような利点があります。
ab + ac + ad + ae + af
に:
a(b + c + d + e + f)
これにより、9つの操作が5つに減ります。
基本的に、優れた抽象化はそれぞれ、システムの複雑さをおよそ半分にします。
抽象化を有効にするには、共通のプロパティを共有する少なくとも2つのものが常に必要です。もちろん、1つを引き裂いて抽象化のように見えますが、それが有用であるとは限りません。
10 => 5 * 2
エンティティが1つしかない場合は、「common」という単語を定義できません。
だからあなたの質問に答えます。 システムを可能な限りシンプルにすることで、十分な抽象化が得られます。
(私の例では、加算はシステムの部分を接続しますが、乗算は抽象とコンクリートの関係を定義します。)
少なすぎますか?
「低レベル」の要素を日常的に使用し続け、常にそうしたくないと感じている場合。抽象化します。
それで、それは多すぎるのですか?
定期的に一部のコードパーツの断片を作成できず、それらを前のレイヤーまでデバッグする必要がある場合。この特定のレイヤーは何も寄与せず、単なる障害であると感じます。もうやめろ。
スイートスポットはどこですか?
私は実用的なアプローチを適用するのが好きです。あなたが抽象化の必要性を見て、それがあなたの人生をどのように改善するかを理解しているなら、それのために進んでください。 「公式に」追加の抽象化レイヤーがあるはずだと聞いたが、その理由が明確でない場合は、それを行わずに、まず調査してください。誰かが何かを抽象化することを主張するが、もしそれがもたらすものを明確に説明できない場合は、離れるように伝えます。
理論的には、それはすべき 3つの(かなり単純な)変数のみを使用した単純な数学の問題です:
S * P> Cの場合、コードは適切です。 S * P <Cであれば、それは悪いことです。
ただし、これが純粋に理論的な理由は、一般に、使用の確率や使用による節約を推測できないためです。さらに悪いことに、推測することも、通常はmeasureが存在することのコストさえも。
少なくとも一部の人々はこれから結論を出しました。 TDDでは、標準的なマントラは「あなたはそれを必要としない」(YAGNI)です。簡単に言えば、現在の要件を満たすコードに直接貢献しないものはすべて悪いものと見なされます。本質的に、彼らは、使用の可能性が非常に低いので、そのような余分なコードを含めることはnever正当化されると結論づけました。
これの一部は、「トップダウン」開発ではなく「ボトムアップ」開発に戻ります。私はボトムアップ開発を「ライブラリ開発」と考えがちです-つまり特定のアプリケーションを開発する代わりに、アプリケーションで必要な種類のライブラリを実際に開発しています。十分なライブラリがあれば、その一般的なタイプのほとんどすべてのアプリケーションを比較的簡単に開発できると考えています。
また、プロジェクトの規模にもかなり依存します。何十年も使用されている巨大なプロジェクトは、廃棄されてより迅速に置き換えられる小規模なプロジェクトよりもはるかに長期的な投資を正当化します。これには、実生活でも明らかな類似物があります。使い捨てカミソリのフィット感、仕上げ、仕上がりについては、今後数年間使用する新しい車のようなものと同じように、1週間足らずで捨てることができます。 。
簡単に言うと、コードが理解しにくい場合、抽象化が多すぎます。
これは、すべてをハードコーディングする必要があると言っているのではありません。これは、書き込みと読み取りが最も簡単なコードだからです。
最も簡単なテストは、数日間それを置き、それを取り戻し、自問することです。これは意味をなします。より良いアプローチは、それを他の誰かに与え、彼らがそれの表または裏を作れるかどうかを確認することです。
現実は、それがどれだけうまく将来を見通せるかにかかっているということです。追加のレイヤーをあまり作成せずに、予測できる変更を計画したいとします。システム間でデータを転送するデザインがある場合は、先に進んでインターフェイスを作成し、計画された実装をデフォルトとして使用します。たとえば、FTPを使用してファイルを移動しますが、標準は来年メッセージベース(またはその他)になる予定です。
デザイン内のレイヤーについては、追加されたレイヤーにより、小さいクラスを簡単に記述できる場合があります。具象クラスが単純になることを意味する場合は、概念レイヤーを追加してもかまいません。
実際に使用されていないすべての抽象化は多すぎます。システムが単純なほど、変更が容易になります。抽象化レイヤーは、ほとんどの場合、システムをより複雑にします。
OTOH、なんらかの抽象化なしで複雑で保守不可能な混乱をプログラムすることは確かに可能であり、「標準化された」抽象化レイヤーは、ほとんどの人が自分で行うことができるよりも優れたシステムの構築に役立つ場合があります。
アイテムを見る(6a)
of RFC 1925 そして、それが本当に本当であることを知っています。抽象化レイヤーを追加しても修正できない唯一の問題は、抽象化レイヤーが多すぎることが原因です。 (特に、すべての抽象化は全体を理解するのを難しくします。)