質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

publicの危険性

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 5,754

score 198

プログラムをやっていて以前から疑問に思っていたので教えて下さい。

アクセス修飾子でprivateやpublicなどがありますが権限を強化するprivate自体の意味は分かりますが、実際にpublicにすると発生するリスクがよく分かりません。

すべてpublicにしてアプリを作成した時に発生するであろう問題を具体的な例を出して教えて下さい。実際にあった例などありましたら有難いです。

カプセル化の定義は理解しているつもりです。
「カプセル化」とは、変数などにアクセス修飾子をつけることで、外部クラスやメソッドからのアクセスを遮断すること。

外部にみせたくないということは分かりますがでは、(根本的に)もし見ることが出来たり、(特に)アクセスできると例えばPlaystoreにアップしたら具体的にどういう問題が起きるのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • otn

    2016/09/17 09:30

    「カプセル化」について理解した上での質問でしょうか?それ以前での質問でしょうか?

    キャンセル

  • isacRu

    2016/09/18 22:31 編集

    publicにしてしまったら、アクセサにする意味ない…

    キャンセル

回答 5

+14

  • オブジェクトの内部構造を知らずに呼び出すと整合性を壊してしまうようなメソッドであるなら、publicにしてしまうと知らずに使った利用者によって不整合を引き起こされかねません。
  • ひとたびpublicにして公開したメソッドは、誰がどう呼び出しているともわからないので、もう仕様を変えるわけにいかなくなります。

追記 09/18

2項目挙げたうちの前者はカプセル化に関わることで、otnさんが詳しく述べてくれました。後者についてはraccyさんが実例を挙げて詳説してくれたのですが、これは「開放・閉鎖原則」と呼ばれるものです。調べるときのキーワードにどうぞ。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+8

アクセス修飾子がないため、全てがpublicになるJavaScriptでの事例を見つけたので、紹介します。

発生した問題のPR: https://github.com/knockout/knockout/pull/796

jQueryを内部で使用しているKnockoutというJavaScriptライブラリで発生した問題です。

jQueryにはドキュメントに無い関数がいくつか存在します。これらは公開された関数の内部で使用することが目的であり、将来にわたっても維持するかは未定のものです。将来のバージョンでは廃止や動作の変更がされる可能性が高く、ライブラリ作成者側にとっては利用者には使わせたくはありません。しかし、JavaScriptにはprivateといったアクセス修飾子が無いため、jQuery側でそれらの関数を使わないようにさせることができません※。仕方が無いため、ドキュメントには書かないという消極的な手法をとるしかありませんでした。

※ 無理矢理privateもどきにする方法は一応あるのですが、ソースの可読性や実行速度、メモリ使用量などに影響があるため、積極的に使用したい物ではありません。

そのドキュメントに無い関数のうちの一つであるjQuery.clean()という関数をKnockoutは使っていました。これが悲劇の始まりでした。jQuery 1.9から内部でjQuery.clean()の使用を止め、この関数は削除されました。つまり、jQueryを1.9にアップデートするとKnockoutが動かないという問題が発生したのです。Knockout側はjQuery.clean()を使わない方法でコードを修正し、jQuery 1.9にも対応できるようにしました。それが上のPRです。

これは誰が悪いのでしょうか?jQuery側はドキュメントに無い関数を勝手に使うのが悪いと主張するでしょう。それは正しいです。では、Knockout側はどう思うでしょうか?実際に動作確認を行うとき、jQueryのドキュメントに無い関数を使っているかどうかを自動的にチェックする方法はありません。ドキュメントに有ろうが無かろうが、関数は、実装されていれば正しく動くのです。どんなにテストを行ってもこの問題を事前に検知することは不可能だったでしょう。

もし、JavaScriptにpublicやprivateがあったとしたら?jQueryの開発者はこのような関数について全てprivateに設定していったでしょう。もし、privateによってjQuery.clean()がjQueryの外側で使えないようになっていれば、Knockout側もテストですぐにわかって、そのようなコードが入り込むことは無かったでしょう。つまり、ドキュメントに書かないという消極的な方法では無く、エラーにするという積極的な方法によって、利用者に使ってはいけないことを確実に周知できたのです。後から削除や変更された場合も、今回のような無用な混乱は避けることができたのです。


どうでしたか?privateがあってよかったなーと思えましたか?

小規模な開発であればそれほどメリットがあるように思えないかも知れません。しかし、複数のライブラリ、モジュール、パッケージに別れ、それぞれが独立し、それぞれを作る人が異なるような大規模開発において、内部だけにしか使わない物を見せないと言うことはとても重要です。とくに、コンパイルを行うような言語ではコンパイル時に使ってはいけない関数がわかるというのはとても意味があることです。開発者側は、内部利用の関数について互換性を気にせずにいくらでも最適化できますし、利用者側は、何を使って良いのか明確になり、ドキュメントにあるかないかの確認をするなんて時間の無駄なことをする必要もなくなります。

規模が大きくなり、分散と疎結合が必要ななったとき、そのときこそ、privateの秘匿化が価値を持つのです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/17 16:05

    privateの価値理解しました。事例説明ありがとうございます。

    キャンセル

checkベストアンサー

+4

カプセル化の言葉は知っているがメリットが理解できないと言うことですね。

(特に)アクセスできると例えばPlaystoreにアップしたら具体的にどういう問題が起きるのでしょうか? 

直接にプログラムに脆弱性が生まれるか?という意味でなら、生まれません。
あくまで開発者の生産性の問題です。バグが生まれやすくなるため、テストで取り切れないと結果的に脆弱性が出来ることはあると思いますが。

2,アプリを開発している一個人
3,アプリを複数で開発している共同開発者の方々

これは、「一度頭に浮かんだことは絶対に忘れない」という人で無い限り2も3も同じです。
オブジェクト指向プログラミングするのにカプセル化を使わないと、オブジェクト指向のメリットが失われ、デメリットだけになり効率が低下します。

まあ、publicにしなくてもpublicなセッター・ゲッターを定義すればほぼ同じデメリットが生まれますが。

「カプセル化」の他、「疎結合」「モジュール結合度」などのキーワードで調べてみると良いかと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/17 11:16

    >「疎結合」「モジュール結合度」などのキーワード
    検索してみて大変参考になりました。分からなかった点が理解できました。
    android studioを自己流で初めて2年、unityを初めて半年ほど経ちますが基本的なオブジェクト指向の設計方法が理解できていませんでした。ありがとうございました。

    キャンセル

  • 2016/09/17 12:42

    >「カプセル化」の他、「疎結合」「モジュール結合度」などのキーワードで調べてみると良いかと思います。

    オブジェクトが隠蔽すべき処理コードの拡散

    オブジェクトが自己責任で行わなければならない処理を、オブジェクトの外部に記述できる。これにより、そのオブジェクトを利用する箇所には、常に同じコードが記述され、コピー・ペーストされるようになる。同時に、コピー・ペーストに少しづつ異なる処理が付け加えられ、拡散することも起こる。

    こうなると機能変更のために、調査と修正に膨大な時間を費やすことになり、諦めたくなります。こんな仕事したくないですね。

    オブジェクトの責任でできることは、オブジェクトの内部に隠蔽しましょう。処理コードが一箇所に記述されていると、保守作業はうんと楽になります。クラスの利用者は、保守のことを考えながら、クラスの設計者と話し合いましょう。

    「凝集度と結合度」についての議論を調べてみてください。

    キャンセル

+1

こんにちは。

全てpublicでも本質的には問題ありません。
しかし、人はミスを犯しやすいです。そのミスの一部を防ぐためにprivateにするのは効果的です。
外部からアクセスする必要がないメンバをprivateにしておけば、間違って外部からアクセスすると言語処理系がエラーを検出してくれますので。
プログラムが大規模になる程、これらのミスが痛い(バグの原因を見つけにくい)のでより有用になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/17 10:31

    >しかし、人はミスを犯しやすいです。そのミスの一部を防ぐためにprivateにするのは効果的です。
    ここが知りたい部分です。
    「人はミスを犯しやすい・・」この場合の「人」とは・・・
    1,アプリを利用するユーザー
    2,アプリを開発している一個人
    3,アプリを複数で開発している共同開発者の方々

    キャンセル

  • 2016/09/17 10:37

    2, 3ですね。
    自分で作ったプログラムでも時間が立つと記憶が薄れて本来外部からのアクセスを想定していないメンバへアクセスするというミスを犯します。
    更に他の人はそれが本来外部からのアクセスを想定していないことを把握しそこなう(ドキュメントに記載漏れ、ドキュメントを読まない等)ミスもあります。もちろん、ドキュメントをちゃんと読んでいても時間が立てば忘れてしまいます。

    キャンセル

0

問題と呼べるほどのものは無いです。

ただし、オブジェクト指向っぽくならないし、その利点の一つであるカプセル化がうまく働かなくなります。

ではカプセル化が無い状態とはどのような状態かというと、グローバル変数だけでプログラムを書く状態です。アセンブラやCOBOLでは基本的にこの状態です。つまり、かけないことは無いです。

私はCOBOLを書いていましたが、それぞれの変数がどのタイミングでどんな変更がされるかを意識しながら書かないといけませんでした。

キチンと管理できればバグのないプログラムになりますが、管理できなければ意図しない動作をし、プログラムが異常停止したポイントの状態をすべての変数を表示して確認する必要がありました。そして、意図せずに変数を変更した箇所(もしくは初期化などを忘れた箇所)を発見するのです。(最終的に私はプリフィックスでアクセスレベルを明示するようになりました。)

特にこの作業は、他人のコードやコーディングから3日以上経過すると調査がプログラム全体にかかることがあります。

初めから、プログラムのどこで変更されるのかを宣言し、コンパイラレベルでエラーになれば調査の手間が減るので、私は適切に(つまりできる限り小さく)権限を設定することを心がけています。

まあ、個人的なものや使い捨てコードなら、コーディングスタイルは自由なのでやってみるのもいいです。やってみなくては分からないものも多いし、質問者さんは案外、問題ないと感じるかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る