注1:以下 bikeshedding です
注2:グローバル定数を避ける必要はないと結論が出ています(下記コメントを参照)
Objective-C でよく使われる XXMyClassHogeConstant
式のグローバルな定数を避けるべきか否かについて、別の記事のコメント欄で @oden@github と筆者 @uasi とで議論がありました。記事の本題と外れたために削除したそれらのコメントを、記録のために再掲します。 @oden@github のコメントは通知メールから引用しました。ただし文中の第三者への @ は @...
に置き換えました。また、 @uasi のコメントはログが残っていないため、元のコメントの大意を箇条書きにしました。
(引用注:元記事の、グローバル変数の定義方法を説明した箇所について)このバージョンでは、定数の説明でグローバル変数を利用しています。
これは絶対に行ってはならないバッドノウハウのひとつです。
- グローバル変数を避けるべき理由は?
@uasi グローバル変数を避けるべき理由であれば「グローバル変数」で検索すると見つかります。
https://www.google.com/#q=グローバル変数グローバル変数を定数に用いることを避けるべき理由は、カプセル化のアンチパターンである点です。
@... 確かに、グローバル変数は、gotoと同様に有用であるケースも存在します。
ご指摘通り「グローバル変数を用いるか否か」という問題は、
「オブジェクト指向を用いるか否か」という設計の問題です。JavaやObjective-Cとは無関係のリクエストを送信したことをお詫び申し上げます。
リクエストは撤回させて頂きたいと思います。
- グローバル変数の読み書きはカプセル化を破るが、定数として使うなら問題ないのでは?
@uasi えっと、よく勘違いされることなのですが、カプセル化とは情報や振る舞いを隠蔽することだけでなく、公開する情報や振る舞いをオブジェクトにまとめることも含まれます。
ここでのアンチパターンという指摘は、定数としての情報が、どのクラスに紐付いているのかが明示的になっていない、という点にあります。こちらも設計の問題になるので、オブジェクト指向を用いない方にとっては意味のない指摘になりますが、
static finalフィールドとグローバル定数は、全く異なる概念のオブジェクトです。前者は継承や多態性によって同一のデータ構造で異なる値の表現等が実現できますが、
これも設計の問題なので継承を用いないコードを書くなら気にする必要はありません。ただし、オブジェクト指向でコードを書くなら、こちらの表現の方が妥当ではないか、
と考えて編集リクエストを送信致しました。多く使われていることが正しいという指摘も理解できますが、個人的には多くの要望から実装されたgoto文を採用したPHPや、C言語ではグローバルスコープにおける_から始まる全ての名前が予約されているにも関わらず、プロパティと紐付くインスタンス変数の名前にデフォルトで_を付けるObjCの挙動には眉を顰めます。
言語的に許されていますし、問題もないかもしれませんが、みんなやってるからと言って、欠点を知りながらそれを勧めるのはどうかと思います。
ただまあこれは設計どころか最早好き嫌いの問題なので、流石にリクエストは控えたいと思います。
- Objective-C では既存の C API との兼ね合いがあるため、厳密なカプセル化よりグローバル定数のほうが実用的ではないか
- 慣習的な命名方法に従えば、定数がどのクラスに属するか見た目上ははっきりする
- UI 関係のクラスなどは継承より移譲を多用しているので、その設計者は継承による振る舞いの変更を重視しなかったのではないか
- 個人的には、 Java 流のオブジェクト指向を遵守するより Objective-C の流儀に従ったほうが、既存フレームワークとの思想の食い違いがなくて楽