「時期尚早の抽象化」とは何ですか?


10

私はフレーズが乱れているのを聞いたし、私には議論が完全に正気ではないように聞こえます(ここでわざわざ言っているとすみません、それは私の意図ではありません)。

一般的なケースがわかる前に抽象化を作成したくない場合は、(1)属していないものを抽象化に入れるか、(2)重要なものを省略します。

(1)私にはこれはプログラマーが十分に実用的ではないように聞こえます、彼らは最終的なプログラムには存在しないものがあると仮定しているので、抽象化のレベルが低い状態で作業していますが、問題はありません時期尚早な抽象化、それは時期尚早な結着です。

(2)重要なことの省略は1つです。後で重要になることが仕様から省略されている可能性があります。これに対する解決策は、独自の結論を導き出してリソースを無駄にすることではありません。間違っていると思います、それはクライアントからより多くの情報を取得することです。

これは、抽象化から具体化に至るまで常に作業する必要があります。これは、最も実用的な方法であり、その逆ではないためです。

そうしないと、クライアントを誤解し、変更が必要なものを作成するリスクがありますが、クライアントが独自の言語で定義した抽象化のみを構築する場合は、このリスクにぶつかることはありません(少なくとも、いくつかの具体的な暗闇の中でのショット)、はい、クライアントは詳細について考えを変える可能性がありますが、本来彼らが望むものを伝えるために使用していた抽象化は依然として有効である傾向があります。

以下に例を示します。クライアントがアイテムバギングロボットの作成を希望しているとします。

public abstract class BaggingRobot() {
    private Collection<Item> items;

    public abstract void bag(Item item);
}

私たちは、クライアントが使用した抽象化から何かを構築していますが、わからないことについては詳しく説明していません。これは非常に柔軟性があり、「時期尚早な抽象化」と呼ばれるのを見てきましたが、実際にはバギングがどのように実装されたかを想定するのは時期尚早です。複数のアイテムを一度にバギングすることをクライアントと話し合った後、 。クラスを更新するために必要なのはシグネチャを変更することだけですが、ボトムアップを始めた人にとっては、大規模なシステムのオーバーホールが必要になる可能性があります。

時期尚早な抽象化などはなく、時期尚早な結集だけです。このステートメントの何が問題になっていますか?私の推論のどこに欠陥がありますか?ありがとう。


1
時期尚早な抽象化の反対はYAGNIです -あなたはそれを必要としないでしょう、それは私の意見ではほとんど常に間違っています。ほとんど。私はそれが起こるのを見てきましたが、それはまれです。私はあなたがここで言っていることにほとんど同意します。
user1118321

回答:


19

少なくとも私の意見では、時期尚早な抽象化はかなり一般的であり、OOPの歴史の初期には特にそうでした。

少なくとも私が見たところから生じた主要な問題は、人々がオブジェクト指向階層の典型的な例を読むことでした。彼らは、将来の変化に対処するすべての準備が整っ作りについて多く語ってしまったかもしれません(彼らは希望信じていない、特に十分な理由があったにも関わらず)に発生します。しばらくの間多くの記事に共通する別のテーマは、「哺乳類はすべて同じである」または「鳥はすべて同じである」という単純なルールに反するカモノハシのようなものでした。

その結果、実際には従業員のレコードなどを処理するだけでよいコードが作成されましたが、クモまたは甲殻類を雇ったことがある場合に備えて、注意深く書かれました。


したがって、時期尚早な抽象化は抽象化の行為ではなく、抽象化の仕様レベルを超えて抽象化する行為です。それはもっと理にかなっていて、それが実際に起こっているのを見ることができました。私は、上司が概説する抽象化のレベルで作業していることを同僚に明確にする必要があるだけだと思います。
ジェームズ

1
@James:それは、バージョン1.0の仕様に基づいて「多すぎる」ことを抽象化することも意味します。それは、新しいバージョンの仕様の新しい要件を知っていると信じているため、v1.0をより一般的な方法ですでに実装しているためです。必要。何か、それ以降のバージョンで何が起こるかを想像するのは良いことですが、オーバーエンジニアリングの特定のリスクもあります。
Doc Brown、

@DocBrown私はその時期尚早な結着と呼びます。抽象化とは、情報を追加するのではなく、削除することです。必要以上に抽象化に追加する場合は、抽象化の低レベルについて何かを想定しています。抽象化の定義は「根底にある本質を抽出するプロセス」であるため、「抽象化」はあまり意味がないと思うので、2つを区別したいと思います。実際のものやイベントの。」
ジェームズ

6

抽象化は目的を達成するための手段であることを覚えておくことは重要です。抽象化を使用してプログラム全体の動作を統一し、新しいクラスの追加が予想される場合に、その瞬間に抽象化が必要な場合にのみ、新しいクラスの追加を簡単にします。

抽象化は、それが必要になる可能性があるという理由だけでは追加しません(将来、新しいクラスを追加する必要があると考える根拠がないため)。ここでの適切な比喩は配管であるかもしれません。うまくいけば、水が上/下、東/西、北/南に流れることができる6方向パイプが、最も柔軟なタイプのパイプになることに同意するでしょう。理論的には、パイプが必要な任意の場所で6方向パイプを使用し、不要な方向を遮断することができます。

シンクの下のリークの問題を修正しようとして、パイプのすべてのセクションが6方向のパイプの断片であることがわかった場合、そのように設計した人にイライラして髪を引き出したいと思います。問題がどこにあるかわからないだけでなく、適切な方法でゼロから開始することはほぼ間違いなく簡単です。

もちろん、コーディング配管ではありませんが、比喩はまだ立っています。抽象化は、それらの6方向パイプピースを使用するようなものです。近い将来、いずれかの6方向からパイプを接続する必要があると正直に信じる場合は、これらを使用してください。それ以外の場合、抽象化は単純な複雑化であり、何も必要としないパターンを使用したり、すべてを実行しようとする神クラスを使用したりすることと大差ありません。使用されておらず、今後も使用される可能性が低い場合は、最終的に何もないクラスを追加します。

確かに、プログラムを書く技術は概念的に非常に抽象的なものです。抽象化は、抽象化のために存在するのではなく、いくつかの実際的な方法で実用的であるため、言及する価値があります。抽象化を使用する必要があると感じた場合もそうですが、後で配管をチェックするように依頼しないでください。;)


あなたは少しclass中心的であるように見えます…多くのクラスがあったとしても、抽象化はそれらに利用される/それらに利益をもたらすことに限定されません。
Deduplicator

1
@Deduplicator結構ですが、それでも私のポイントは変わりません。抽象化を使用する場合、それはすぐに有益であるか、近い将来の計画的な変更である必要があります。クラスや関数型プログラミングについて言及していることは重要ではありません。
ニール・

3

何年も前にオブジェクト指向の分析と設計について知ったとき、私たちは顧客が必要とするシステムの簡単な英語の説明から始めました。

それを見ると、どんな名詞(または名詞句)も可能なクラスと見なされます。動詞(または動詞句)は、クラスの潜在的なメソッドになります。つまり、「袋詰めロボット」はクラスになる可能性がありBaggingRobotます。「袋を開ける」という方法になるかもしれませんOpenBag

数回繰り返すと、これはクラス図になります。

この時点では、抽象クラスはありません。顧客は、袋詰めロボットの抽象的な概念を望んでいません。彼らは物をバッグに入れるロボットを望んでいます。すべてのクラスは具象であり、一連のメソッドがあります。

抽象クラスは、次のことが明らかになったときにのみ導入されます。

  • 階層を形成できる同様のクラスがいくつかあります。
  • それらは実際には共通点を共有しているため、基本クラスは有用な目的を果たします。

私にとって「時期尚早な抽象化」とは、一部のから継承するBaggingRobot 必要があることを想定してBaseRobotおり、さらに悪いことに、BaseRobotすべてのロボットに共通するものを知る前に一連のメソッドを開発しようとしています。


抽象化は、抽象クラスと同義ではありません。インターフェイスは抽象化です。私は抽象クラスだけでなく、抽象化全般について話している。おそらく、インターフェイスを使用してこれをより明確にすることができたでしょう。クライアントと同じ抽象化レイヤーでシステムを開発する場合、言語は自然に抽象化されるため、拡張する必要があるいくつかの抽象クラスが作成される可能性があります。それよりも低い作業は、私が「時期尚早の結束」と呼んでいるものであり、システムがどのように機能するかについてのクライアントの考えはあなたの考えと同じであると単純に仮定します。
ジェームズ

ItemオブジェクトをBagオブジェクトに入れるBaggingRobotオブジェクトは、すでに物をバッグに入れる実際のバギングロボットの抽象概念です。
user253751

1

まだ存在していない問題を解決したいと思い、クライアントが要求していることが間違っていると信じている場合を除いて、発生することを想定する十分な理由はないようです。それが事実である場合、私は、抽象またはその他の推測ソリューションの実装よりも多くのコミュニケーションをお勧めします。クラス定義を「抽象化」するだけで無害に見えるかもしれませんが、後で拡張できることを知って安心しているかもしれませんが、必要がない場合や、設計を複雑にするような方法で拡張する場合もあります。間違ったものを抽象化することによって、線。

あなたの例に沿って、あなたはそれがロボット自体であると想像しますか、バッグに入れられているアイテムまたはバッグ方法が将来的に変化するでしょうか?

時期尚早な抽象化は、実際には抽象化を実行する十分な理由がないことを意味します。抽象化は多くの言語では無料ではないため、正当化せずにオーバーヘッドが発生する可能性があります。

編集コメント内のOPのいくつかのポイントに回答するために、ポイント(1)と(2)をより具体的に説明しながら、長いコメントチェーンを必要としない方法で明確にして応答するようにこれを更新しています。

(1)私にはこれはプログラマーが実用的ではないように思えます、彼らは最終的なプログラムには存在しないものがあると仮定しているので、抽象化のレベルが低くても問題はありません時期尚早な抽象化、それは時期尚早な結着です。

(エンファシス鉱山)。最終的なプログラムに存在しないものがあると仮定すると、私はあなたの例で正確に見ています。顧客は、荷物を運ぶロボットを求めました。言語がやや曖昧な場合、これは非常に具体的な要求です。顧客はアイテムを袋に入れるロボットを望んでいるので、オブジェクトのペアを作成します

public class Item {
/* Relevant item attributes as specified by customer */
}
public class BaggingRobot {
  private Collection<Item> items;

  public void bag(Item item);
}

モデルはシンプルで正確であり、ソリューションに複雑さを追加することなく、顧客が要求した以上のものを顧客が望んでいると仮定することなく、顧客が設定した要件に従います。これを提示したとき、彼らは交換可能な袋詰めの仕組みを持っているために、ロボットの必要性を明確にした場合にのみ、その後あなたが今を指すことができるので、あなたは、抽象化のインターフェースまたは他の方法を作成正当化するのに十分な情報を持っているか、特定の値に加算されます抽象化によるシステム。

逆に、純粋な実用主義からの抽象化から始める場合は、別のインターフェースを作成してそれを具体化して実装するか、抽象クラスを作成するか、好きな抽象化の方法を使用します。その後、顧客がこれに満足し、それ以上の拡張が不要であることが判明した場合、時間とリソースを無駄に費やしているか、システムにオーバーヘッドと複雑さをもたらしたかのいずれかです。

(2)に関しては、重要なことを省くことは、早すぎる抽象化の特徴ではないことに同意します。抽象化の有無にかかわらず、重要なものを省略できます。抽象化のチェーンのはるか下にある場合を除いて、それをいずれかの方法で整理することは難しくも簡単でもありません。

代わりに、抽象化を行うと、ドメインモデルが難読化されるリスクがあると解釈します。ドメインモデルのさらなる成長とドメインの理解に劇的な影響を与える可能性のある関係を作成しているため、不適切な抽象化はシステムの推論を非常に困難にする可能性があります。モデルを間違ったうさぎの穴に落とすことにより、抽象化されているものに関する重要な情報ではなく、システム全体に関する重要な情報を省略してしまうリスクがあります。


「まだ存在していない問題を解決したいと思い、クライアントが要求していることにクライアントが間違っていると信じている場合を除いて、発生することを想定する十分な理由はないようです。」-これは私が言ったこととはまったく異なります。実際、私はクライアントが使用した言葉に基づいてのみ構築していることを明確にしました。抽象化を使用するようになったのは、これをしたくないという行為です。
ジェームズ

「推測ソリューションを実装するよりも多くのコミュニケーションをお勧めします」-私が提案したような意味ですか?OPで私が言ったことを引用すると、「これに対する解決策は、自分の明確さを考え出して、間違っているとわかったときにリソースを無駄にすることではなく、クライアントからより多くの情報を取得することです。」
ジェームズ

「クラス定義で「抽象」をたたくだけで、後で拡張できることを知って安心できるのは無害に見えるかもしれませんが」-「抽象」と言うとき、「抽象」を意味するのは「抽象キーワード」を意味するのではありません。インターフェイスは抽象化である可能性があり、抽象化はファジーロジックであり、それがこの投稿全体で述べられていることです。クライアントは抽象化の観点から通信しているので、ドメインについて詳しくなるまで抽象化された用語でプログラミングする必要があります。
ジェームズ

1
「あなたはあなたが決してする必要がないことに気付くかもしれません」-これは意味がありません。クライアントが「アイテムを袋に入れるロボットが欲しい」と言ったら、その基準を満たす抽象化を作成します。クライアントから取得するその他の情報は、バギングの実行方法に関する詳細情報になります。これはあなたの抽象化を無効にしません、クライアントは彼らが購入しているものの背後にある核となる考えについて彼らの考えを突然変えません。ロボットはまだアイテムをバッグに入れます。作成した抽象化は引き続き適用されます。
James

「あるいは、間違ったものを抽象化することにより、デザインを複雑にしてしまうような方法で拡張してしまうかもしれません。」...私が言ったことやタイトルだけを正直に読みましたか?マジ?ポイント(1)と(2)を読む
James
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.