むりせず♪なまけず? ~ぷろくらすてぃねいたーの言い訳雑記~

よた ときどき .NET  by 刈歩 菜良 CTP

目次

ニュース

C# VB.NET掲示板
C#, VB.NET 掲示板

わんくま同盟ブログ
わんくま同盟ブログ

Web アプリケーションを簡単編集できる無償ツール WebMatrix ダウンロードはこちら

あわせて読みたい

日記カテゴリ

書庫

Blog 利用状況

なぜフィールドを公開してはいけないのか

元ネタは「公開されたフィールドは存在が悪であるということ
でも、そこに到達した元ネタは「Automatic Properties(C#3)

レベルがわんくまーな方にもわかりやすいように噛み砕いた説明にトライします。

オブジェクト指向の重要な概念にカプセル化(*1)というのがありますが、C#やVB.NETではカプセル化をスマートに実現するための方法としてプロパティ(*2)というのがあります。

カプセル化を守るため、フィールドはすべてカプセル化して外部からアクセスできないようにします。外部からのアクセスが必要なものに関しては対応したプロパティを定義するというのがクラス設計の常套手段です。
しかし、プロパティって書くの面倒くさいのですよね。
たとえば、C#で書くと、

public class hoga
{
    public int X;
}

と書けば、外部から自由に使える整数型のXが作れますが、これをプロパティにすると。

public class hoga
{
    private int x;
    public int X
    {
        get
        {
            return x;
        }
        set
        {
            x = value;
        }
}

と、書かなくてはいけません。
ご覧のとおり、コード量がとっても増えます(VBだと、さらにもう少しだけコードが増えます)。

だとすると、エラーチェックとか当面想定してないデータならば、面倒くさいからpublicなフィールドにしちゃって、エラーチェックとかが必要になった時にプロパティに切り替えればよい。という安易な考えが首をもたげます。

私も今まではそれでもよいかも。と、思っていました。修正はクラス定義部分だけで、利用者側はフィールドとプロパティの名前が同じである限り、コード変更する必要は全くないと思っていたので。

ところが、私のこの考えはまったく浅はかでした。フィールドをたとえ同じ名前のプロパティに置き換えただけだとしても、利用者側で再ビルドが必要になるそうです。
なんでも、フィールドとプロパティはコードレベルでは互換があっても、バイナリレベルで非互換であるため、利用者側でも再コンパイルが必要とのことです。

これって大問題ですよね。
汎用的に様々なアプリで使用されるようなクラスにとってはまさに致命的です。

なので、やっぱり、フィールドは確実にカプセル化せにゃいかんのだなぁ。と思いました。

【おまけ】
でも、プロパティ書くんめんどくさい。って時に便利なのがAutomatic Propertiesってことですね。
これならチェック処理が必要になった段階で実装を含む記述に書き換えるだけでOK。バイナリ互換も保たれるってわけですね。

*1 カプセル化 ・・・ クラス内部のフィールド(変数)を外部(クラス利用者)から全く見えないようにすること。
*2 プロパティ ・・・ クラス利用者にとってはフィールド(変数)を直接扱っているように利用できるものだが、実際には処理を経由してフィールド(変数)にアクセスさせている。処理を経由するため、エラー値を排除したり、不適切な操作を防止することができる。

投稿日時 : 2007年4月2日 14:56

Feedback

# re: なぜフィールドを公開してはいけないのか 2007/04/02 14:58 刈歩 菜良

超久しぶりのまぢめな技術ネタだ。
しかし、異論反論必至ネタでもある。
どきどき、わくわく... ガクガク、ブルブル...

# re: なぜフィールドを公開してはいけないのか 2007/04/02 15:16 中博俊

ここの仮定がかなりレアなものだと思いますので(アセンブリ境界またぎ)、いったいどれだけのプロジェクトが影響を受けるかというと疑問です。
たぶんLadyBugさんもそう思ってパブリックフィールドを多用していることでしょう。
全体をコンパイルするのが大変とは思えません。
結局ライブラリの提供者(しかも一般的なプロジェクトを越える提供の場合)は
頭を使わなきゃいけないって事ですね。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 15:27 シャノン

> 不適切な捜査を防止することができる。

おとり捜査とかですね!(違

実のところ、これは公開されたフィールドに起因する問題ではなく、サイドバイサイドバージョニングによる予期された動作であるように思います。
予防するために最初からフィールドを使わないようにしておくというのは有効でしょうが、それでバイナリ非互換性をすべて防げるかと言うと、そんなことは当然ありません。
意図しないバイナリ非互換性は避けるべきですが、すべてのバイナリ非互換性が悪なのではありません。

> 異論反論必至ネタでもある。

じゃあご期待にお応えしてw
これは .NET に固有の問題であって、オブジェクト指向一般の問題ではないので、カプセル化云々を持ち出す必要はない気がします。
結局、Automatic Property では、

> クラス内部のフィールド(変数)を外部(クラス利用者)から全く見えないようにすること。

というのは達成できていないわけですから(そりゃフィールドは見えないけど、オブジェクト指向一般の文脈で論じるなら、書き換えが自由な時点で、そんなことに意味は無い)。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 15:32 じゃんぬねっと

シャノンさんの意見に概ね酸性雨。

あと、フィールドを公開したい時って readonly だったりするので、迷うことはないです。
このあたりは、Microsoft のガイドラインに酸性雨なので従っています。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 15:56 シャノン

> フィールドを公開したい時って readonly

御意。
で、ネタ元には

> public readonly のフィールドをプロパティに変更する大きな理由の1つに、コンストラクション以降に値の変更を余儀なくされた場合というのが最も多いと経験しています。

って書いてあるけど、そりゃあ仕様変更なので、バイナリ互換性は失われて然るべき。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 16:42 刈歩 菜良

シャノンさん
> おとり捜査とかですね!
あいた、やっちまいました。

じゃんぬさん
> フィールドを公開したい時って readonly
それならもちろんわたしもフィールド公開に賛成!

今回は書き換えもさせるってことで、どうでっしゃろか?

# re: なぜフィールドを公開してはいけないのか 2007/04/02 16:45 刈歩 菜良

おっ!
readonlyだと意味ないからAutomatic Propertiesはgetアクセッサのみの定義ができないんだな!!
勝手に納得。
( ..)φメモメモ

# re: なぜフィールドを公開してはいけないのか 2007/04/02 16:46 とっちゃん

バイナリ互換をきちんと意識しておくべきなのは、GACへのインストールを前提とするようなものだけでしょうね。
#.NET の場合

個人的にはGACへのインストールは、GrapeCityさんみたいなコンポーネントベンダー(と、MS)だけに許すべきで一般的なアプリ開発(社内や、業務系を含む)では、GACに入れるメリットはほとんど皆無に等しいですしねw

なので、バイナリ互換はそれほど意識する必要はないと思いますよ。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 17:07 じゃんぬねっと

やべっ、前提をしっかり読んでいないことがバレてるw
ごめんなさい。

でも、

> それならもちろんわたしもフィールド公開に賛成!

これには、反対ということを Assert しておきます。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 18:45 とりこびと

なんとなく、フィールドを直接触られるとドキドキしちゃいますぅ。

と、空気を読まずに思ったままを書いてみる。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 21:10 Lady.BUG

> 仕様変更なので、バイナリ互換性は失われて然るべき。

これが仕様変更だというのは誤解でしょう。
フィールドかプロパティかといった設計までが仕様になっているなら仕様書が不具合です(笑
内部的に値の更新が可能になるだけならば、外部からみたみたインターフェス(ニアリーイコール仕様)には何も変更がはいっていないです。仕様の範囲で、実装の都合のいいように修正がはいってしまったというだけ。

仕様にも何も影響がないからといって、バイナリ互換性が失われてしまうということを意識されないで、そのような修正がなされやすい、という状況が問題であろう。ってことなんですよね。

# re: なぜフィールドを公開してはいけないのか 2007/04/02 21:55 Lady.BUG

具体的に、「整数型の A という読み取り専用の情報を保持する」という仕様の型を考えた場合に、

1) public int A;
2) public int A { get { return value_of_a; } }
3) public int GetA();

というのは、どれも仕様を満たしていて、どの形式からどの形式へ変更してもバイナリ互換性は失われますが、「3) と 1)」や、「3) と 2)」といった組み合わせでは、バイナリ互換性が失われることを意識されやすい(ソースコード互換性も失われるためだろう)のに対して、1) と 2) の間の変更は、バイナリ互換性が失われることを意識されにくい、という傾向がある、という話なんですね。

まあ、バイナリ互換性については、再利用性の高いアセンブリの場合であって、パッケージ製品を開発する場合なんかでは大きな問題にならないでしょう。

# re: なぜフィールドを公開してはいけないのか 2007/04/03 9:41 刈歩 菜良

じゃんぬさん
> > それならもちろんわたしもフィールド公開に賛成!
> これには、反対ということを Assert しておきます。
なぢぇ?
ヽ(。_゜)ノ

Lady.BUGさん
> 仕様にも何も影響がないからといって、バイナリ互換性が失われてしまうということを意識されないで、そのような修正がなされやすい、という状況が問題であろう。ってことなんですよね。
なるほど、私の考えよりはるかに深いところでした。勉強になります。
そのあとの3つの例も至極わかりやすい!
さすがLady.BUGさんです。

> まあ、バイナリ互換性については、再利用性の高いアセンブリの場合であって、パッケージ製品を開発する場合なんかでは大きな問題にならないでしょう。

これが中さんのいう「ここの仮定がかなりレアなものだと思いますので」にもつながるのかな?

インストラクターを生業としているわたくしにとっては、初学者向けに教科書的には「フィールドをpublicにしちゃだめ。かわりにプロパティを使いましょう。」と言いたいのですが、逆にフィールドじゃないと不都合がある場合ってあるのでしょうか?
「めんどくさい。」とかは別として。

# re: なぜフィールドを公開してはいけないのか 2007/04/03 15:46 Lady.BUG

ええと、CLR 準拠/推奨レベルでいうと、

(1) は、const のかわりにのみ用います。const はクロスランゲージ性が低いので、public const を使うかわりに public readonly のフィールドを配します。これは完全な定数として扱い、読み取り専用の値を保持する場所としては用いません。(const には文字列と null 以外の参照型を設定できないという問題もあります)

(2) は、副作用の無い値を公開するために使用します。読み取り専用であるかどうかは仕様/設計の問題なので関係ありません。

(3) は、副作用の有る操作の結果として、値を公開するために使用します。はやり、読み取り専用であるかどうかは仕様/設計の問題なので関係ありません。(設定が可能な場合には、Set や Write や Put などの名称で別メソッドを作成することが多いでしょう)

ですかね?

こんなかんじですので、定数としての public readonly のフィールドは .NET Framework の基本ライブラリ群でも散見できると思います。

教育的に「プロパティにしろ!」といいきるのは難しいところですが、概ねの方針として non static であればプロパティにしろって言い切っちゃってもいいんじゃないかと思ったりしますが、どうですかね?

# re: なぜフィールドを公開してはいけないのか 2007/04/03 16:40 刈歩 菜良

Lady.BUGさん
たびたび詳細なご説明ありがとうございます。
感涙ものです。
(;O;)

> const はクロスランゲージ性が低いので、public const を使うかわりに public readonly のフィールドを配します。
そうなんですね。
( ..)φメモメモ
ここら辺ちょっと調べてまとめてみたいと思います。
const ・・・ 定数
readonly ・・・ 変更できない変数
ん?っておんなじぢゃん。って思っていました。
お恥ずかしい...

>概ねの方針として non static であればプロパティにしろって言い切っちゃってもいいんじゃないかと思ったりしますが、どうですかね?
なるほどぉ。「readonly じゃなければ」ではなく、「non static であれば」なんですね。
あ、そっか、フィールドと対応してないプロパティもありですもんね。フムフム。

理想と現実がかけ離れていることはよくあるわけですが、如何に現実からかけ離れすぎずに理想を教えるかってとこが教育の難しいところなんですよねぇ。

皆様本当にありがとうございました。
# って、締めの言葉っぽいですが、まだまだご意見募集中。(●^o^●)

タイトル
名前
Url
コメント