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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

5回答

8824閲覧

publicの危険性

navesanta

総合スコア198

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

1グッド

2クリップ

投稿2016/09/16 23:08

編集2016/09/17 01:20

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

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

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

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

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

stereo_code👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2016/09/17 00:30

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

2016/09/18 13:31 編集

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

回答5

0

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

追記 09/18

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

投稿2016/09/16 23:53

編集2016/09/18 13:03
yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

アクセス修飾子がないため、全てが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 04:07

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

navesanta

2016/09/17 07:05

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

0

ベストアンサー

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

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

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

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

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

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

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

投稿2016/09/17 01:47

編集2016/09/17 01:49
otn

総合スコア84421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

navesanta

2016/09/17 02:16

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

退会済みユーザー

2016/09/17 03:42

>「カプセル化」の他、「疎結合」「モジュール結合度」などのキーワードで調べてみると良いかと思います。 オブジェクトが隠蔽すべき処理コードの拡散 オブジェクトが自己責任で行わなければならない処理を、オブジェクトの外部に記述できる。これにより、そのオブジェクトを利用する箇所には、常に同じコードが記述され、コピー・ペーストされるようになる。同時に、コピー・ペーストに少しづつ異なる処理が付け加えられ、拡散することも起こる。 こうなると機能変更のために、調査と修正に膨大な時間を費やすことになり、諦めたくなります。こんな仕事したくないですね。 オブジェクトの責任でできることは、オブジェクトの内部に隠蔽しましょう。処理コードが一箇所に記述されていると、保守作業はうんと楽になります。クラスの利用者は、保守のことを考えながら、クラスの設計者と話し合いましょう。 「凝集度と結合度」についての議論を調べてみてください。
guest

0

こんにちは。

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

投稿2016/09/17 01:17

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

navesanta

2016/09/17 01:31

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

2016/09/17 01:37

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

0

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

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

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

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

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

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

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

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

投稿2016/09/17 00:59

編集2016/09/17 01:46
iwamoto_takaaki

総合スコア2883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問