ValueObjectについて調べてみた

Value Objectについて調べてみた

GW、せっかくなので勉強してみよう、と意気込んだ結果色々と手を出して、気がついたらValue Objectについて調べてました。

どうしてこうなったのかと説明をしつつ、少し記事にしてみます。

※この記事は定義の良し悪しについて論じるものではなく、自分が調べたことをまとめたものです。批評をする意図はありません。

勉強を始めた動機

最初はデザインパターンを学習しようとしていました。 というのは先日、ちょっとしたWebアプリケーションを作成する機会があり、その際に「これはどう実装するのが良いのかな」と悩んだことがきっかけです。

普通にコーディングするのは問題なくできますが、「このプログラムはどこに配置すべきかな」「オブジェクトをどう組み立てよう」と考えると「これで良いのか分からない」と思うことが多くありました。

そこでGofデザインパターンが兼ねてより積読にもなっていたので学びつつも、提唱されたものがもう30年前ということもあり「本当に学ぶのがベストなのか?」という疑念が湧いてきました。

そうした疑念に対して、所属先のコミュニティで紹介してもらったのが次のPodcastでした。

実際に聴いてみて、t-wadaさんが最後にこのように言われていました。

なので、現代においては、デザインパターンを正面から学んでくってよりは、リファクタリングから、オブジェクト指向プログラミングとしてのデザインパターンに近づくってほうが、オススメルートです。

49. GoFデザインパターンとDI + リファクタリング (後編) w/ twada の59:14前後より引用

という事で、リファクタリングについて学んでいた、というのがまず1つです。

その際に学習したのはこちらの書籍です。 - リファクタリング(第2版)既存のコードを安全に改善する

文中に、次のような表現がありました。

  • ふさわしい構造体がまだ存在しないなら、作成する。
    • 後で振る舞いをまとめやすいのでクラスにすることが多い。構造体が「値オブジェクト(Value Object)」[mf-vo]なのかを確認すると良い。

リファクタリング(第2版)既存のコードを安全に改善する 第2版第2刷 著者 Martin Fowler 著、児玉 公信 訳、友野 晶夫 訳、平澤 章 訳、梅澤 真史 訳 P146 より引用

この[mf-vo]というのは次のMarin FowlerのWebサイトを指していたので、「Martin FowlerもValue Objectについて言及しているんだ」と思い次のサイトを閲覧しました。

https://martinfowler.com/bliki/ValueObject.html

が、ここで紹介されているValue Objectとは次のような説明でした。

When programming, I often find it's useful to represent things as a compound. A 2D coordinate consists of an x value and y value. An amount of money consists of a number and a currency. A date range consists of start and end dates, which themselves can be compounds of year, month, and day.

As I do this, I run into the question of whether two compound objects are the same. If I have two point objects that both represent the Cartesian coordinates of (2,3), it makes sense to treat them as equal. Objects that are equal due to the value of their properties, in this case their x and y coordinates, are called value objects.

邦訳

プログラミングをする際、物事を複合物として表現することが役立つことがよくあります。2D座標は、x値とy値で構成されます。金額は、数値と通貨で構成されます。日付範囲は、開始日と終了日で構成され、それぞれが年、月、日の複合物であることがあります。

これを行う際、2つの複合オブジェクトが同じかどうかという問題にぶつかります。もし、カルテシアン座標(2,3)を表す2つのポイントオブジェクトがある場合、それらを等しいとみなすのは理にかなっています。この場合、x座標とy座標というプロパティの値によって等しいとされるオブジェクトは、値オブジェクトと呼ばれます。

Martin Fowler 2016年 11月14日 https://martinfowler.com/bliki/ValueObject.html より引用

自分が知っているValue Objectとはちょっと違う気がしたので、調べてみました。

というのが、ここまでの流れです。前置きが長くなりましたが、次から本題です。

自分が知っているValue Objectとは

自分が知っているValue Objectとは「特定のドメインを表現するためのオブジェクト」のような表現で表されるものでした。

この考えに意識的に触れたのは「ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本」でした。 正しくは、「値オブジェクト」として記述がありました。

以下、引用です。

プログラミング言語にはプリミティブな値が用意されています。それらをやりくりしてシステムを組み上げることも可能ですが、システム固有の値を定義することがときに必要となります。このシステム固有の値を表現するために定義されたオブジェクトが値オブジェクトと呼ばれるものです。

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本 成瀬 允宣 著 2020年2月13日 初版第1刷 P16 より引用

私は当時この本を読んで「こうすればバグは確かに生まれにくくなるはずだ!」と強く思ったのを覚えています。

例えば商品コードを取り扱う中において、以下のようなバリデーションが複数箇所で利用されるとどうでしょうか。

半角英数字数値6桁で表されるものだとして

  • 入力値の桁数が6桁であることのチェック
  • 入力値が半角英数字であることのチェック

こうしたロジックが複数箇所に点在すると、それは好ましくないのかな、と個人的に感じたからです。

という理由があり、自分の中で感銘を受けるに至ったWordであったのは間違い無いですが、少なくともMartin Fowlerとは異なる言説です。 また、そのほか個人的に勉強になったなと思っている書籍では次のような記述がある事を確認しています。

値の種類ごとに専用の型を用意するとコードが安定し、コードの意図が明確になります。このように、値を扱うための専用クラスを作るやり方を値オブジェクト(Value Object)と呼びます。

現場で役立つシステム設計の原則〜変更を楽で安全にするオブジェクト指向の実践技法 増田亨 著 2019年11月2日 初版 第3刷 P32, 33 より

値オブジェクト(Value Object)とは、値をクラス(型)として表現する設計パターンです。アプリケーションでは金額、日付、注文数、電話番号など、さまざまな値を扱います。こうした値をクラスとして表現することで、各値それぞれのロジックを高凝集にする効果があります。

良いコード/悪いコードで学ぶ設計入門―保守しやすい 成長し続けるコードの書き方 仙塲大也 著 2022年5月12日 初版 第1刷 P37 より

あとは通読できていませんが、エヴァンス本にも記述がありました。

あるオブジェクトが、ドメインにおける記述な側面を表現し、概念的な同一性を持たない場合、そういうオブジェクトは、値オブジェクトと呼ばれる。値オブジェクトがインスタンス化される際に表現しようとするのは、何であるかだけが問題となり、誰であるか、あるいはどれであるかは問われないような設計の要素である。

エリック・エヴァンスのドメイン駆動設計 2020年9月10日 初版第12刷(2011年4月8日が初版第1刷) 牧野 祐子 翻訳 牧野 祐子 原著 今関 剛 監修 今関 剛 翻訳 今関 剛 原著 和智 右桂 翻訳 和智 右桂 原著 Eric Evans 著 P96 より

改めてMartin Fowlerの記事を読んでみる

Martin Fowlerの記事を読んでみると、以下のような記述がありました。

Therefore I find it useful to think of two classes of object: value objects and reference objects, depending on how I tell them apart [1]. I need to ensure that I know how I expect each object to handle equality and to program them so they behave according to my expectations. How I do that depends on the programming language I'm working in.

邦訳

そのため、私は、オブジェクトをどのように区別するかによって、値オブジェクトと参照オブジェクトの2つのクラスを考えることが有用だと考えています[1]。それぞれのオブジェクトが等式をどのように扱うかを確認し、その期待通りに動作するようにプログラミングする必要があります。その方法は、使用するプログラミング言語によって異なります。

ということから、参照オブジェクトと対比するものとして、値オブジェクトを説明していることが読み取れました。 オブジェクトが保存される参照値で比較するのか、シンプルに値で比較するのか、という点で期待通りに動くようにする、ということだなと。

他にも次のような記述がありました。

This is an example of an Aliasing Bug, I change a date in one place and it has consequences beyond what I expected [4]. To avoid aliasing bugs I follow a simple but important rule: value objects should be immutable. If I want to change my party date, I create a new object instead.

邦訳

これはエイリアシングバグの例で、ある場所で日付を変更したところ、予想以上の結果になってしまったというものです[4]。エイリアシング・バグを回避するために、私は単純だが重要なルールに従う:値オブジェクトは不変でなければならない。もし私がパーティーの日付を変更したい場合、代わりに新しいオブジェクトを作成します。

以下のような「よくある」値なのか参照なのかを意識せずに間違ってしまう、という例を防ぐためimmutableにした方が良い、ということだと理解しました。

class Text:
    def __init__(self, value):
        self.value = value

foo = Text("foo")
bar = foo

print(foo.value) # foo
print(bar.value) # foo

bar.value = "bar"

print(foo.value) # bar
print(bar.value) # bar

以上より、Value Objectと一口に言っても色々な捉え方が存在していることが理解できました。

「どういうこと?」と最初混乱していましたが、色々な認識が生まれているんだな、ということが分かりよかったです。

自分の中の結論

どのような意味合いで「Value Object」について、語れているのかは文脈を読んだ上で判断すべき。

Value Object という単語が具体的なようで抽象的な意味合いも含まれてしまうような単語なので、色々な呼び方が生まれている気がする。

また、自分はこういうものを学んだ = 使ってみたい、使ってみようとついつい手を出してしまいがち。 本当にそれは必要なのか、それを使うことが適しているのか?はしっかり検討すべきだなと。

fukabori.fmでkumagiさんが言及されていた内容も結構自分の中で刺さることが多かったので、なぜ使うのか?をきちんと明確にした上で使っていこうと思いました。

Value Objectについて書かれた記事

その他、Value Objectについて書かれた記事がいくつか存在していたので記載しておきます。

というより、これまで結構話題に上がりつつも、当時全然理解できていなかったことがようやく認識できました。。

https://kumagi.hatenablog.com/entry/value-object

https://bufferings.hatenablog.com/entry/2022/05/17/010943

https://little-hands.hatenablog.com/entry/2018/12/09/entity-value-object

https://blog.j5ik2o.me/entry/2022/05/22/204535

https://panda-program.com/posts/three-types-of-value-object

補足

なぜこのような話題を今更取り上げたのか?

それは、自分の学生時代に由来があり。 近江商人の研究(と言っても大したことはしていない)を学生時代にしており、一番驚いたのは近江商人が言ったとされる「三方よし」という言葉は近江商人が言ってないということでした。

「売り手によし、買い手によし、世間によし、三方よし」という表現自体は、歴史用語ではなく、近江商人研究においては、昭和63年(1988)ごろ、近江商人研究者の小倉榮一郎氏によって用いられた、近江商人の到達した商いの精神を端的に表した造語です。

https://e-omi-muse.com/omishounin/about6.html

一応学生時代は近江商人を学ぶという大義名分をかざして入学したので、まさかそんなことあるのかと当時驚いた事を覚えています。

他にも昔は誤用だったけど、今は正式な言葉として認められている言葉もあるなと(今回のValue Objectで特定のものが誤用であると言いたいわけではありません)。 そうした中で、どういう出典で語られている言葉なのかは意識すべきだな、ということで今回調べてみました。

自分の中のちょっとした自由研究みたいなもので、面白かったです。 さて、リファクタリングの学習に戻るとします。