104

「リーク抽象化」という用語はどういう意味ですか?(例を挙げて説明してください。私は、単なる理論を理解するのに苦労することがよくあります。)

4

11 に答える 11

115

ミートスペースの例を次に示します。

自動車にはドライバーの抽象化があります。最も純粋な形では、ハンドル、アクセル、ブレーキがあります。この抽象化により、エンジン、カム、タイミング ベルト、スパーク プラグ、ラジエーターなど、ボンネットの下にあるものに関する多くの詳細が隠されます。

この抽象化の優れた点は、ユーザーを再トレーニングすることなく、実装の一部を改善された部分に置き換えることができることです。ディストリビューターキャップを電子点火に交換し、固定カムを可変カムに交換するとしましょう。これらの変更によりパフォーマンスが向上しますが、ユーザーは依然としてハンドルを操作し、ペダルを使用して発進と停止を行います。

実際には驚くべきことです... 16 歳または 80 歳の人が、内部の仕組みをあまり知らなくても、この複雑な機械を操作できます。

しかし、漏れがあります。トランスミッションは小さな漏れです。オートマチック トランスミッションでは、ギアが切り替わる瞬間にパワーが失われるのを感じることができますが、CVT では、スムーズなトルクを最後まで感じることができます。

大きな漏れもあります。エンジンの回転が速すぎると、エンジンが損傷する可能性があります。エンジンブロックが冷たすぎると、車が始動しないか、パフォーマンスが低下する可能性があります。また、ラジオ、ヘッドライト、エアコンを同時に回すと、燃費が低下します。

于 2011-06-23T02:37:58.767 に答える
57

これは単に、抽象化によって実装の詳細の一部が公開されること、または抽象化を使用するときに実装の詳細に注意する必要があることを意味します。この用語は、2002年頃のJoel Spolskyによるものです。詳細については、ウィキペディアの記事を参照してください。

典型的な例は、リモートファイルをローカルとして扱うことができるネットワークライブラリです。この抽象化を使用する開発者は、ネットワークの問題により、ローカルファイルとは異なる方法でこれが失敗する可能性があることに注意する必要があります。次に、ネットワークライブラリが提供する抽象化以外のエラーを具体的に処理するコードを開発する必要があります。

于 2010-10-07T15:03:03.397 に答える
15

ウィキペディアには、これについてかなり良い定義があります

漏れやすい抽象化とは、複雑さを軽減 (または非表示) することを目的として実装された抽象化を指し、基礎となる詳細が完全には隠されていません。

言い換えれば、ソフトウェアの場合、プログラムの制限や副作用によって機能の実装の詳細を観察できるときです。

簡単な例は、C# / VB.Net クロージャーと、それらが ref / out パラメーターをキャプチャできないことです。それらをキャプチャできない理由は、リフティング プロセスがどのように発生するかの実装の詳細によるものです。これは、これを行うためのより良い方法があると言っているわけではありません。

于 2010-10-07T15:05:28.903 に答える
14

.NET 開発者によく知られている例を次に示します。ASP.NET のPageクラスは、HTTP 操作の詳細、特にフォーム データの管理を隠そうとします。これにより、開発者はポストされた値を処理する必要がなくなります (フォーム値がサーバーに自動的にマップされるため)。コントロール)。

しかし、最も基本的な使用シナリオを超えてさまようPageと、抽象化が漏れ始め、クラスの実装の詳細を理解しない限り、ページを操作するのが難しくなります。

一般的な例の 1 つは、コントロールをページに動的に追加することです。動的に追加されたコントロールの値は、適切なタイミングで追加しない限り、マップされません。つまり、基になるエンジンが入力フォームの値を適切なコントロールにマップする前です。それを学ばなければならないとき、抽象化が漏れています。

于 2010-10-07T15:51:58.843 に答える
10

まあ、それは重要ではありませんが、ある意味では純粋に理論的なものです.

物事を理解しやすくするために、抽象化を使用します。個々の項目である順序付けられた文字のセットを扱っているという事実を隠すために、何らかの言語で文字列クラスを操作することがあります。数字を扱っているという事実を隠すために、順序付けられた文字のセットを扱います。数字を扱っているのは、1 と 0 を扱っているという事実を隠すためです。

漏れやすい抽象化とは、本来隠すべき詳細を隠さない抽象化です。Java または .NET で 5 文字の文字列に対して string.Length を呼び出すと、5 から 10 までの任意の答えを得ることができます。これは、これらの言語が文字と呼ぶものが実際には UTF-16 データポイントであり、1 または 1 を表すことができる実装の詳細のためです。キャラクターの.5。抽象化が漏れました。ただし、リークしないということは、長さを見つけるには、(実際の長さを格納するために) より多くのストレージ スペースが必要になるか、O(1) から O(n) (実際の長さを計算するため) に変更されることを意味します。私が本当の答えを気にしているなら (多くの場合、あなたはそうではありません)、実際に何が起こっているのかを知る必要があります。

より議論の余地のあるケースは、メソッドやプロパティが内部の仕組みに侵入できるようなケースで発生し、それらが抽象化のリークであろうと、より低いレベルの抽象化に移行する明確に定義された方法であろうと、人々が同意しない問題になることがあります.

于 2010-10-07T15:11:54.917 に答える
9

引き続き RPC を使用して例を示します。

RPC の理想的な世界では、リモート プロシージャ コールはローカル プロシージャ コールのように見える必要があります (実際にはそうです)。プログラマーが呼び出したときに、ローカルに保存されて実行されるのか、それともリモートで保存されて実行されるのかがわからSomeObject.someFunction()ないような、プログラマーに対して完全に透過的でなければなりません。理論的には、これによりプログラミングが簡単になります。SomeObjectsomeFunction

ローカル関数呼び出しを行うこと (世界で最も遅いインタープリター言語を使用している場合でも) と次のことの間には大きな違いがあるため、現実は異なります。

  • プロキシ オブジェクトを介して呼び出す
  • パラメータのシリアル化
  • ネットワーク接続の確立 (まだ確立されていない場合)
  • データをリモート プロキシに送信する
  • リモート プロキシにデータを復元させ、ユーザーに代わってリモート関数を呼び出す
  • 戻り値のシリアル化
  • 戻り値をローカル プロキシに送信する
  • シリアル化されたデータの再構築
  • リモート関数からの応答を返す

時間だけでも、約 3 桁 (またはそれ以上!) の違いがあります。これらの 3 桁以上の桁数は、パフォーマンスに大きな違いをもたらし、RPC を実際の関数呼び出しとして誤って初めて扱ったときに、プロシージャ呼び出しの抽象化が明らかにリークします。さらに、実際の関数呼び出しでは、コードに深刻な問題がなければ、実装のバグ以外の障害点はほとんどありません。RPC 呼び出しには、通常のローカル呼び出しから予想される以上の失敗のケースとして、次のような問題が発生する可能性があります。

  • ローカル プロキシをインスタンス化できない可能性があります
  • リモート プロキシをインスタンス化できない可能性があります
  • プロキシが接続できない可能性があります
  • 送信するパラメーターは、完全に作成されないか、まったく作成されない場合があります
  • リモートが送信する戻り値は、それをそのままにするか、まったくしない可能性があります

したがって、「ローカル関数呼び出しと同じ」RPC 呼び出しには、ローカル関数呼び出しを行うときに対処する必要のない追加の障害条件が大量に含まれています。抽象化が再びリークし、さらに困難になりました。

結論として、RPC はすべてのレベルでふるいのようにリークするため、悪い抽象化です (成功した場合と失敗した場合の両方)。

于 2010-10-07T16:12:08.397 に答える
4

django ORM 多対多の例の例:

サンプル API の使用法で、多対多属性に Publication オブジェクトを追加する前に、基本 Article オブジェクト a1 を .save() する必要があることに注意してください。また、多対多の属性を更新すると、基になるデータベースにすぐに保存されますが、単一の属性を更新すると、.save() が呼び出されるまでデータベースに反映されないことに注意してください。

抽象化は、単一値属性と複数値属性が単なる属性であるオブジェクト グラフで作業しているということです。しかし、リレーショナル データベースに裏打ちされたデータ ストアとしての実装はリークします... RDBS の整合性システムがオブジェクト インターフェイスの薄いベニアを通して現れるためです。

于 2010-10-07T15:48:30.977 に答える
1

スケールと実行によって導かれるある時点で、なぜそのように動作するのかを理解するために、抽象化フレームワークの実装の詳細に精通する必要があるという事実。

たとえば、次のSQLクエリを検討してください。

SELECT id, first_name, last_name, age, subject FROM student_details;

そしてその代替:

SELECT * FROM student_details;

現在、それらは論理的に同等のソリューションのように見えますが、個々の列名の指定により、最初のソリューションのパフォーマンスが向上しています。

これは些細な例ですが、最終的に Joel Spolsky の引用に戻ります。

すべての自明でない抽象化は、ある程度、漏れやすいものです。

ある時点で、運用が一定の規模に達すると、DB (SQL) の動作を最適化する必要があります。そのためには、リレーショナル データベースの仕組みを理解する必要があります。最初は抽象化されていましたが、漏れがあります。ある時点でそれを学ぶ必要があります。

于 2018-10-10T09:25:53.973 に答える