安全のためにカプセル化はどのように使用されますか?


8

OOPを学習しています。私はカプセル化について多くのことを学びましたが、読むほど、混乱しました。

私は(プライベートにすることで)データを隠し、プロパティまたはメソッドとしてクラスのユーザー(他の開発者)に公開することを理解しています。また、カプセル化によって詳細を隠すことも理解しています。

記事(http://www.csharp-station.com/Tutorial/CSharp/lesson19)で私は読んだ:

記事の要約

オブジェクトを設計するときは、他の人がそれをどのように使用できるかを考える必要があります。最良のシナリオでは、オブジェクトを使用するすべてのプログラムが適切に設計され、コードが変更されることはありません。ただし、実際にはプログラムは頻繁に変更され、チーム環境では多くの人が一度に同じコードに触れます。したがって、オブジェクトがどのように自然のままの画像だけでなく、間違って行くことができるかを検討することは有益である必要があります使用すること。

BankAccountオブジェクトの場合は、オブジェクト外のコードが10進数のAmountフィールドまたは文字列CustomerNameフィールドにアクセスできる状況を調べます。コードが作成された時点で、すべてがうまく機能します。ただし、開発サイクルの後半では、情報間の関係(または内部状態の定義を変更する他の有効な理由)を複製したくないため、BankAccountオブジェクトは文字列CustomerNameではなくint CustomerIDを追跡する必要があることに気付きます。 。このような変更は、元々設計されたとおりに(CustomerNameが文字列である)BankAccountクラスを使用するように構築されているため、コードに波及効果を引き起こし、アプリケーション全体でその状態にアクセスするコードを変更する必要があります。

カプセル化のオブジェクト指向の原則は、このような問題を回避するのに役立ち、メソッド、プロパティ、インデクサーなどの型メンバーを介して内部状態を非表示にし、アクセスを抽象化できます。カプセル化は、オブジェクト間の結合を減らし、コードの保守性を向上させるのに役立ちます。

質問 カプセル化は、コードに変更を加えるとき、およびその波及効果からどのように役立ちますか。データメンバーの場合、その型をintからfloatに変更すると(プロパティを使用してこれを公開している場合でも)、このコードを既に使用している変数の型を変更する必要があります。

カプセル化がこのような変更にどのように役立つかを教えてください。

このヘルプとガイダンスをありがとう。

回答:


8

カプセル化は、コードに変更を加えるとき、およびその波及効果からどのように役立ちますか。データメンバーの場合、その型をintからfloatに変更すると(プロパティを使用してこれを公開している場合でも)、このコードを既に使用している変数の型を変更する必要があります。

カプセル化の利点は、クライアントコードを壊すことなく内部実装を変更できることです。コードへのインターフェースを変更する必要があると判断した場合、それはあなたを保護しませんが、それは別の問題です。

例:ある商品の単位あたりの価格を表す値があるとします。価格はセントで表され、小数セントを扱わないため、プロパティを整数にすることにしました(C#に詳しくないため、ここではCを使用します)。

int _price

int pricePerUnit(void) {
    return _price;
}

int priceForUnits(int units) {
    return units * _price;
}

丸め誤差のためにあなたの会社が多くのお金を失っていることに誰かが気付くまで、それはすべてうまくいきます。追跡する商品の多くは何千もの単位で売買されるため、少なくとも0.001セントの精度で価格の追跡を開始する必要があります。クライアントに直接アクセスさせるのではなく、価格をカプセル化できるほど賢いので、その変更をすばやく行うことができます。

double _dprice

int pricePerUnit(void) {
    return (int)_dprice;
}

int priceForUnits(int units) {
    return (int)(units * _dprice);
}

クライアントが価格を取得するために使用するインターフェースは同じままですが、クライアントが返すデータはより正確になりました。ユニットあたりの価格が$ 1.001の場合、priceForUnits(1000000)以前よりも$ 1000高い価格が返されます。これは、システムへのインターフェイスをまったく変更していないために発生し、したがってクライアントコードは破損していません。

さて、必ずしもそれがあなたがする必要があるすべてではないかもしれません。クライアントに価格をより正確に報告できるように、インターフェースを変更または強化する必要がある場合もあります。

double pricePerUnit() {
    return _dprice;
}

そのような変更クライアントコード破壊するので、代わりに古いインターフェイスを維持して、より新しくより良いルーチンを提供することができます。

int pricePerUnit() {
    return (int)_dprice;
}

double accuratePricePerUnit() {
    return _dprice;
}

あなたとあなたのチームの他のメンバーは、システムのすべてのクライアントをより新しい、より良いものを使用するように変換するプロセスに着手できますaccuratePricePerUnit()。クライアントコードは、そのタスクを進めるにつれてより正確になりますが、古いものでも、以前と同じように機能し続けるはずです。

とにかく、重要なのは、カプセル化によって一貫性のあるインターフェイスを提供しながら内部の動作を変更できるため、他のコードを壊すことなく有用な変更を行うことができるということです。他のコードを更新しなければならないことを常に保護するわけではありませんが、少なくとも制御された方法でそれを行うのに役立ちます。


3

私の経験では、カプセル化によって「間違った」ことを行うことがはるかに困難になります。意味的に一緒に機能する機能をグループ化して、悪い動作や予測できない動作を引き起こす可能性のある機能から分離することができます。また、安全性と信頼性の向上に役立つ可能性があるエンドユーザーから詳細を隠すのにも役立ちます。

John D Cookによるこの投稿を検討してください。Breadオブジェクトがあると考えてください。このパンをスライスする自然なこと。だからあなたはslice()関数を書くので、あなたはすることができます

slice(loaf)

loafあなたが作成した新しいオブジェクトで。意味あり。しかし、注意しないと、誤って電話してしまう可能性があります。

slice(finger)

fingerプロジェクト内のオブジェクトのどこか。これは非常に悪いことになる可能性があります。代わりに、この関数/メソッドをBreadクラスにカプセル化して、これを実行できるようにします

loaf.slice()

おそらく関連付けられているメソッドがないため、これは間違いなくfinger.slice()誤って呼び出すのを防ぐのに役立ちます。fingerslice()

これは少し不自然な例ですが、役立つと思いました。カプセル化はOOPの過小評価されている側面である場合がありますが、それは良いことです。


2

カプセル化は、大規模な開発者グループが作業をより効率的に調整するのに役立ちます。開発者の各グループは異なるモジュールで作業し、それらのモジュールはカプセル化されています-コードを、使用を厳密に制御できない少数の広く利用可能なオペレーターと、厳密に制御できる多数の内部オペレーターに分けます。これは、開発者の各グループが、モジュールの維持に重要な不変条件を定義し、他のモジュールの開発者が何をするかに関係なく、それらの不変条件が確実に保持されることを意味します。

カプセル化は不変式の保存を可能にするため、セキュリティ/安全性の不変条件を維持するためによく使用されます。

  • 適切な認証情報がないとデータストアにアクセスできない
  • 銀行口座には、他の銀行口座から削除された金額よりも多くの金額が追加されることはありません。
  • 特定の操作が常にログに記録されること

オブジェクト能力モデルはステロイドでカプセル化されたセキュリティに敏感なコードを書くための方法論です。

セキュリティモデルは、参照を偽造できないことに依存しています。アクターのアドレスの合成を参照してください。

オブジェクトは、参照でメッセージを送信することによってのみ相互作用できます。参照は次の方法で取得できます。

  1. 初期条件:記述されている計算の世界の初期状態では、オブジェクトAは既にオブジェクトBへの参照を持っている可能性があります。
  2. 寄付:AがBを作成する場合、Bは、Aがそれを寄付することを選択したAの参照のサブセットで生まれます。
  3. はじめに:AがBとCの両方への参照を持っている場合、AはCへの参照を含むメッセージをBに送信できます。Bはその参照を後で使用するために保持できます。

オブジェクト機能モデルでは、すべての計算は上記のルールに従って実行されます。

カプセル化や情報の隠蔽、モジュール化、懸念の分離など、オブジェクト指向プログラミングの動機となる利点は、機能ベースのプログラミングにおける最小特権や特権分離などのセキュリティ目標に対応します。


2

カプセル化は、コードに変更を加えるとき、およびその波及効果からどのように役立ちますか。

典型的で単純な例を挙げましょう。まず、カプセル化を使用していないとします。一連のデータがあり、配列を使用してそのデータを格納します。また、その配列を使用するプログラムの別の部分があります。さて、ある時点で、リンクリストがデータを格納するためのより良い選択であると判断した場合。配列をリンクリストに置き換えると、どうなりますか?配列処理ロジックをリンクリスト処理ロジックに置き換えるために変更を加えない限り、プログラムは壊れます。

ただし、OO /カプセル化を使用する場合、プログラムをクラスに分割します。1つはデータを格納し、もう1つはデータを使用します。最初のクラスでは、実装(カプセル化)を隠し、次のようなメソッドを通じてサービスを公開します

size()
remove(int index)
add(int index, Object o)
get(int index)

...

この2番目のケースでは、格納クラスの実装を配列からリンクリストまたはその他のものに変更しても、クライアントには影響しません。波及効果はありません。


1

カプセル化が変更の波及効果を減らすのに役立つ主な方法は、実装の詳細をできるだけ多くクラスに公開しないことです。インターフェイスをクラスの使用に必要なメンバーのみに制限することにより、クラスを使用するコードに影響を与えることなく、実装に多くの変更を加えることができます。

それはあなたが引用したテキストによってなされたポイントであるように思われますが、私はまたそれを私の最初の読みで少し混乱させました。


1

常にではありませんが、BCブレーク(バイナリ互換または動作互換)を導入しなくても、クラスの機能を変更できると思います。つまり、エンドユーザーがクラスに「何か」を行うように指示する方法を変更する必要なく、クラスが「何か」を行う方法を変更できます。

戻り値の型を変更する例は、BCブレークです。これは、以前にクラスを使用した人は、再コンパイルしないと新しいバージョンを使用できないためです。これは最後の手段としてのみ行うべきものであり、専門的な設定では、建築家の許可を得て、書類が提出され、顧客に通知された後などにのみ行うことができます。

また、オブジェクトの状態を完全に制御できます。

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