ここでは、オブジェクトの性質について、以下の観点で解説します。
同一性
オブジェクトが同一(identical)とは、オブジェクトが時や場所を越えて、それ自身と同じであるということです。
これは、個々のオブジェクトがID(identifier:識別子)を持つことを意味します。
同一性(identity)とは、オブジェクトが持つ、同一であるかどうかを示す性質のことです。
同一性を持つオブジェクトはコピーできません。
例えば、NFT(non-fungible token:非代替性トークン)は同一性を持つオブジェクトです。
NFTとは、ブロックチェーン上に記録される一意で代替不可能なデータ単位で、画像・動画・音声、およびその他の種類のデジタルファイルなど、容易に複製可能なアイテムを一意なアイテムとして関連づけることができるものです。
ソフトウェア開発で、問題領域(ドメイン)に存在するオブジェクトを分析するときに重要な観点は、オブジェクトの同一性を意識するかどうかです。
等価性
オブジェクトが等価(equivalent)とは、オブジェクトの値が等しいいことです。
これは、オブジェクトの持つ状態変数の値が等しいことを意味します。
等価性(equivalence)とは、オブジェクトが持つ、等価かどうかを示す性質のことです。
ビットコインなどの暗号通貨も含め通貨には等価性があります。
Aさんが持つ1000円もBさんが持つ1000円は、同一性はありませんが、同じ1000円という価値を持ちます。
ソフトウェア開発で、問題領域(ドメイン)に存在するオブジェクトを分析するときに重要な観点は、オブジェクトの等価性を意識するかどうかです。
不変性
オブジェクトが不変(immutable)とは、オブジェクトが値を変えないことです。
これは、個々のオブジェクトが状態(状態変数の値)を変えないことを意味します。
逆に、可変(mutable)なオブジェクトは、状態を変えていきます。
不変性(Invariant)とは、オブジェクトが持つ、不変かどうかを示す性質のことです。
ソフトウェア開発で、問題領域(ドメイン)に存在するオブジェクトを分析するときに重要な観点は、オブジェクトの不変性を意識するかどうかです。
可変なオブジェクトが状態を変える性質を連続性といいます。
参照透過性
Wikipediaでは、参照透過性(referential transparency)について次のように説明しています。
ある式が参照透過であるとは、その式をその式の値に置き換えてもプログラムの振る舞いが変わらない、言い換えれば、
同じ入力に対して同じ作用と同じ出力とを持つプログラムになる
ことを言う。
具体的には変数の値は最初に定義した値と常に同じであり、関数は同じ変数を引数として与えられれば同じ値を返すということになる。
参照透過性が成り立っている場合、ある式の値、例えば関数値、変数値についてどこに記憶されている値を参照しているかということは考慮する必要がない、即ち参照について透過的であるといえる。
複数の機器やソフトウェア、システムなどを連携して動作させる際に、ある構成要素の存在を意識しなくてもその機能を有効にすることができることを透過的(transparent)といい、透過的な性質を透過性(transparency)といいます。
transparentには、透明な、透き通るという意味だけではなく、その結果、明白な、わかりやすいという意味があります。
透過的とは、複数の機器やソフトウェア、システムなどを連携して動作させる際、ある構成要素の存在を意識して、その機能を使うより、存在を意識しなくても使えた方が、機能を使う側から見て、その機能がシンプルで(複雑ではなく)わかりやすいという意味です。
例えば、使う側が、暗号化してからファイルを保存しなければならないシステムより、ファイルを保存すれば自動的に暗号化してくれるシステムの方がシンプルでわかりやすいですよね。
以上より、オブジェクトの参照透過性とは、クラスのメソッドが、変数値についてどこに記憶されている値を参照しているか意識しなくても、常に同じ入力に対して同じ結果を出力するかどうかという、オブジェクトの持つ性質のことと考えます。
プログラミングにおける副作用
関数やメソッドの主な作用は、引数を受け取り値を返すことで評価値を得ることですが、これ以外に、コンピュータの論理的状態(ローカル環境以外の状態変数の値)を変化させる作用を、プログラミングにおける副作用といいます。
プログラミングにおける副作用は、コンピュータの論理的状態を変化させるので、それ以降で得られる処理の結果に影響を与えます。
なので、副作用は、予期せぬエラーを発生させるリスクとなり、それを下げるため以下のようなコストを発生させ、結果的に、ソフトウェアの保守性を下げることになります。
- 副作用によってどこに影響があるか調査しなければならない
- その影響によって、動作に支障が出ないようにしなければならない
また、副作用が起こるクラスなどのソフトウェアの構成要素は、常に同じ結果を提供するわけではないので、交換可能な部品としてのモジュール性、再利用性が低くなります。
参照透過なメソッドや関数の場合、コンピュータの論理的状態(ローカル環境以外の状態変数の値)を変化させないので、副作用を起こすことはなく、ソフトウェアの保守性や再利用性を確保することができます。
同一性と等価性
オブジェクトにおける同一性と等価性の関係ですが、以下のように論理包含の関係になります。
つまり、同一(IDが同じ)ならば等価(値も同じ)という論理関係です。
同一(IDは同じ)だけど等価でない(値は違う)という状況はありません。
Aさんが持つ1000円もBさんが持つ1000円は、同一性はありませんが、同じ1000円という価値を持ちます。
これは、「同一ではないが等価である」という例です。
同一性と不変性
オブジェクトを同一性と不変性の観点から以下のように分類することができます。
- 同一性を持つ(IDがありコピーできない)
同じ初期値を持つオブジェクトを複数生成することは不可能。- 不変性がある
初期値を変えることができない。
NFT(Non-Fungible Token、非代替性トークン)が該当すると考えられます。 - 不変性がない
初期値を変えることができる。
後述する参照オブジェクト(エンティティ)が該当します。
- 不変性がある
- 同一性をを持たない(IDがなくコピーできる)
同じ初期値のオブジェクトを複数生成することが可能。- 不変性がある
初期値を変えることができない。
後述する値オブジェクトが該当します。 - 不変性がない
初期値を変えることができる。
生命現象?
- 不変性がある
不変性と参照透過性
不変性を持つオブジェクトを不変オブジェクト、不変性を持たない(状態を変える)オブジェクトを可変オブジェクトといいます。
不変オブジェクトと可変オブジェクの特徴は以下のようになります。
- 不変オブジェクト(immutable object)
不変オブジェクトの場合、変数の値は最初に定義した値と常に同じなので、メソッドは同じ変数を引数として与えられれば同じ値を返す。
なので、クラスのメソッドが、変数値についてどこに記憶されている値を参照しているか意識する必要はなく参照透過である。
不変オブジェクトの場合、それに対する参照が異なっても(同じであっても)、等価なオブジェクトのクラスのメソッドは、同じ変数を引数として与えられれば同じ値を返す。
※この場合の参照とは、他の場所にあるデータ(オブジェクト含む)を指している情報を含む小さなオブジェクトのこと。 - 可変オブジェクト(mutable object)
可変オブジェクトの場合、変数の値は最初に定義した値と常に同じとは限らないなので、メソッドは同じ変数を引数として与えられれば同じ値を返すとは限らない。
なので、可変オブジェクトの場合、どの変数値を参照しているか考慮する必要があるので参照透過ではない。
参照オブジェクトと値オブジェクト
参照オブジェクト(エンティティ)と値オブジェクトの特徴をまとめると以下のようになります。
- 参照オブジェクト(エンティティ)
- 同一性
同じオブジェクトは同一(同じIDを持つ)である。 - 連続性
可変(mutable)である。 - 参照透過性
参照透過でない。
- 同一性
-
値オブジェクト
- 等価性
同じオブジェクトは等価(値が同じ)である。 - 不変性
不変(immutable)である。 - 参照透過性
参照透過である。
- 等価性
参照型と値型
- 参照型
参照型は、変数や定数に代入されるときや関数に渡されるとき、同じインスタンスの参照が渡される。 - 値型
値型は、変数や定数に代入されるとき、あるいは関数に渡されるとき、値がコピーされる。
[…] ている値を参照しているか意識しなくても、常に同じ入力に対して同じ結果を出力すること。 同一性、連続性、等価性、参照透過については、オブジェクトの性質を参照してください。 […]
[…] ;計測、説明するオブジェクトで不変性、等価性を持ち、交換可能なも& […]