setter/getterを強制する規約は廃止すべき
  Java, プログラミング

とある開発プロジェクトに参加したときに、こんなJavaのコーディング規約に遭遇しました。

インスタンス変数のアクセス修飾子は private とし setter/getter メソッドを実装すること。

この規約は良くないですね。

「Javaのインスタンス変数は必ず private にすべし、public にするなどありえない。インスタンス変数は setter/getter を通してアクセスする。これがカプセル化というものですよ。」

こう力説してくれる上級Java開発者が一定数います。

しかし、私はずっと疑問に思っていました。クラスとはデータ構造と操作(アルゴリズム)を持つもの。操作を持たないデータのみで構成されるものはクラスではなく構造体なのではないか? Javaの言語仕様にはstructがないからclassで代用しているだけではないか? classを構造体として使う場合は setter/getter を設けずに、フィールドのアクセス修飾子を public にしてもおかしくないのではないか?と。

あれこれと情報を探してみると、同じことが Stack Overflow でも議論されていました。

この議論の中で「クラスが振る舞いを持たず本質的なデータ構造であるなら、インスタンス変数を public とするのが適切である」とSun Javaコード規約に記載されている、との回答が付きました。

Javaコード規約 10.1 Providing Access to Instance and Class Variables には以下のように記載されていました。

10.1 Providing Access to Instance and Class Variables

Don’t make any instance or class variable public without good reason. Often, instance variables don’t need to be explicitly set or gotten-often that happens as a side effect of method calls.

One example of appropriate public instance variables is the case where the class is essentially a data structure, with no behavior. In other words, if you would have used a struct instead of a class (if Java supported struct), then it’s appropriate to make the class’s instance variables public.

日本語訳は以下の通りです。

10.1 インスタンス変数とクラス変数へのアクセスの提供

正当な理由もなく、インスタンス変数やクラス変数を public にしないでください。多くの場合、メソッド呼び出しの副作用としてインスタンス変数の設定や取得がされるので明示的にインスタンス変数を設定・取得する必要がありません。

適切な public インスタンス変数の一つの例は、クラスが動作を持たず本質的にデータ構造である場合です。言い換えると、(仮にJavaがstructをサポートしていれば) classの代わりにstructを使うという場合、インスタンス変数を public にするのは適切です。

私が感じていた疑問の答えがズバリ書いてありました。 Javaの言語仕様にはなくとも、クラスとは別の概念として構造体を考えることができ、そのようなケースではインスタンス変数のアクセス修飾子を public にするのが適切であるということが20年前からJavaのコード規約には書かれていたのです。

このような動作を持たない本質的データ構造は Passive data structure (受動的なデータ構造) と呼ばれ、PDSと略されることもあるそうです。

受動的なデータ構造(PDS)は、他システムや永続化ストレージ間を移動するデータとしてシステム境界でよく見られます。つまり、O/Rマッパーを使ってデータベース・テーブルの行に対応させるエンティティクラスや、 JSONデータを使ってシリアライズ・デシリアライズするデータクラスなどは受動的なデータ構造(PDS)と言えます。

このようなクラスにまで杓子定規にsetter/getterを実装する必要はなく、むしろ、インスタンス変数を public にすることが適切であるとされているわけです。

これからは、堂々と、受動的なデータ構造のフィールドを public にしていこうと思います。