いつ抽象コードを記述し、いつ具体化するのか?


9

私はおもちゃのプロジェクトとして小さなツールに取り組んでおり、2つのディレクトリの違いを示し、どのファイル/ディレクトリが追加、削除、変更されたかなどを示しています。

私はこれらの変更を、それがファイルであるかディレクトリであるかを区別せずに、単に「ChangeItem」オブジェクトとして表現しようとしていました。しかし、それらをツリーに表示する方法、子供の親が誰であるかを知る方法など、多くの問題が発生しました。また、非常に直感的ではありませんでした。

次に、ディレクトリの変更とファイルの変更の間で変更を分割します。これにより、コーディングが非常に簡単になり、何が起こっているのかを理解することが容易になりました。これで、ディレクトリ内のすべてのファイルを選択するなど、はるかに簡単になりました。

私の質問は、抽象化を使用するか、コードでより具体的にするかをどのようにして知ることができるかです。抽象化が多すぎるか少なすぎるかをどのように判断できますか?

回答:


9

画家は、紫が多すぎるか少なすぎるかをどのようにして知るのでしょうか。

彼は色を混ぜ、ストロークを試し、スケッチをいくつか作成して、何が起こるかを確認します。次に、図面全体が見栄えがよくなり、調和がとれるまで、比率を調整します。

コードについても同様です。私たちは初めて実装のアイデアを得て、それを反省し、その強力な側面と週の側面を分析し、それが機能するかどうかを試してみます。次に、アイデアを反復プロセスで調整して、抽象化、カプセル化、ポリモーフィズムなどの比率を調整し、正しく見えて必要に応じて機能するようにします。


21

最初に具体的なコードを記述します。

抽象コードは、具体的なコードを簡素化するため、必要なときに作成します。

コンクリートから始めて、コンクリートの類似点と相違点を調べた後、抽象化を見つけるのが最も簡単です。


13
3つのルールを常に思い出してください。少なくとも3つのクライアントがない抽象化は抽象化ではありません。それは希望的な考えです。通常は間違っています。優れた抽象化が抽出され、設計されていません。
イェルクWミッターク

3

ライブラリを作成するときに抽象的なコードを作成し、さまざまな条件下で機能するように機能を一般化する必要があります。

しかし、この方法でライブラリを作成することは困難です。通常のアプリケーション(たとえば、基幹業務アプリケーション)では、この種の一般化は「時期尚早の最適化」の一種と見なされ、一般に「必要ない」と特徴付けられます(YAGNI)。

反復的なコードがより一般化されたソリューションの設計を要求する転換点があります。しかし、通常、この種の冗長性を取り除くリファクタリングは、一般化されたライブラリを作成するよりもはるかに簡単です。

結局、抽象ソリューションの実装に必要な追加の複雑さは、それらが提供する柔軟性によって正当化されなければなりません。


3

私が従う経験則は、かなり一般的ですが、3回目の執筆に気付くまでは、抽象化を試みるべきではありません。

初めて問題の領域を単に理解しないと、すべての誤った部分を過剰に設計することになります。2回目は、最後の問題に対する理想的なソリューションを構築するために完全に配置されます。3回目は、ようやく、変更が必要な事柄に役立つ適切な抽象化を思い付き、簡単なことを行うのに邪魔にならないようにするための良い位置にいます。


1
3回目は良い目安です。3回目に何かを書く前に、一般化することはほとんどありません。
クエンティンスターリン

1
同様のコードの大きさにも依存しませんか?魔法の「3回」をまだヒットしていないという理由だけで、2行だけ異なる2ページのコードをコピーして貼り付けることはしません。
Scott Whitlock、

@ scott-whitlock:もちろんです。それが経験則である理由です。必要に応じて無視してください。さらに、有機的な抽象化(たとえば、「ほぼ正確にfooである必要があるため、オプションのパラメーターをfooに追加した」)と、事前設計の一部である抽象化との間には違いがあります。
btilly

1
@Scott Whitlock:「2行だけが異なる2ページのコードをコピーして貼り付けることはできません」。それは抽象化の要求ではありません。それはまだちょうど良いデザインです。3xルールは、時期尚早な抽象的なデザインを回避するために、非常に厳密に維持する必要があります。
S.Lott、2011

ここでは「適宜」がキーワードです。私の2セント-多くの場合、「継承より構成を優先」が適用されます。時々、抽象化で解決する問題はif (cond) { //use one object} else {// use the other object }、特にとしてより良いでしょう。バイナリ決定セットの場合。
マイケルK

2

質問を読むことで、私はあなたが抽象的なものでも具体的なものでもよいと言うでしょう。コンテキストの問題であり、各コンテキストで可能な最も抽象的な表現を使用します。

特定のおもちゃのアプリの場合、ChangeItemは変更の最も抽象的な表現です。次に、継承によってDirectoryChangeItemand FileChangeItemでより具体的になります。複合パターンを使用してツリーをモデル化できます。表示したい場合は特定の表現を使用し、トラバースする場合は抽象表現を使用できます。

そして、質問に具体的な答えを与えるために、その下に別のレイヤーが必要だと感じるまで、できるだけ具体的にします。


1

通常、抽象化は、複雑さ、エントロピーなどの問題に対処し、コードをサイバネティックにするために、さらには低レベルの読みやすさでさえ有用です。最初にハードコードします-抽象化が前もって明らかでない場合のみ。ほとんどの抽象化は、複数の実装が同じパターンを共有するときに発生します。

抽象化は、2つ以上のセットの合同または統合であると考えてください。ベン図を単純なモデルとして考えてみましょう。円が重なる部分、つまり、セットがマージされます。

A:{a、b、c、d、e}とB:{d、e、f、g、h}の2つのセットがある場合。私が抽象化を検討し始めるポイントは、A + Bの単一性です。{d、e}は抽象化する場所です。同様に、AとBの違い(ABまたはBA)が互いに同型である場合、つまりf、gまたはhからa、bまたはcを作成するための低コスト(およびその逆)であれば、抽象化を続けます私の心の奥に。

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