2018年2月20日火曜日

クラスやメンバのスコープを広くしすぎない

クラスやプロパティ・メソッドのスコープは、それが利用される範囲に応じて適切に設定する必要があります。「Public にしておけばどこからでも参照できるから楽」という考え方は危険です。

※これは2013年に書いたものです。


外部に公開する必要があるもののみ Public にする


ある Private メソッドに引数を追加したいとなった場合、影響範囲はそのクラスのみに留まります。Friend ( C# では internal ) メソッドであればそのアセンブリまでに留まります。しかし Public メソッドである場合は影響範囲を限定することができません。そのアセンブリが他のアセンブリから参照されており、そのメソッドが使用されているかもしれないからです。もちろんアセンブリを外部に配布していなければそのような心配は不要ですが、いわゆる「基幹業務システム」と言われるシステムは多くのアプリケーションで構成されており、知らないうちに網の目のように参照されていたという経験のある方もいるのではないでしょうか。

Public にするということは外部に対して公開するということを意味しています。公開する必要があるから Public にするのです。公開するからにはバージョンの互換性など相応の義務も発生します。互換性の問題が起きたときに「勝手に別のアセンブリから参照されていたから」と言い訳はできません。

 公開する必要がなければ Friend や Private としておき、公開しなくてはならなくなった時点で Public に変更するのが良いと思います。逆に Public から Friend, Private へスコープを縮小させるような変更はさけるべきです。そのクラスやメンバを削除するのと同じだからです。

ObsoleteAttribute 属性の利用


何らかの理由によって以前に公開していたクラスやメンバを使用してほしくないことを伝えるには、スコープはそのままにしておき ObsoleteAttribute 属性を使用します。「○○は旧型式です」というような警告を Visual Studio に表示させることができます。.NET Framework 標準ライブラリの中にもそのようなクラスやメンバがあるのを見たことがあると思います。

VB.net のコントロールの Modifiers プロパティ


ところで、Visual Studio の VB.NET フォームデザイナでコントロールを配置したときのスコープ(Modifierプロパティ)の既定値が Friend であるのも困りますね。複数のフォームが複雑に参照し合う原因になっています。

フォームAがフォームBを呼び出し、フォームBからフォームAのテキストボックスに入力されている値を参照するようなケースです。こういうことをしてしまうとフォームAはフォームBがなくては成り立たず、フォームBもフォームAがないと成り立たなくなります。フォームBを流用して新しいフォームを作ろうとしたときにフォームAがないとコンパイルエラーになって、フォームAを追加すると別のフォームが必要になって…ということが起こりやすくなります。

既定値が Friend であることがこういった仕様を助長していると思います。オプションで既定値を指定できればいいんですが…。

0 件のコメント:

コメントを投稿

paiza のスキルチェックをやってみました

いまさら感はありますが、 paiza のスキルチェックをやってみました。指定された時間内にコードを書いてユニットテストにかけ、その結果を基に評価を数値化してくれるというものですが、ゲーム感覚で空き時間を見つけて進めていこうと考えています。 どうやら時間が短いほど高い評価を得...