始まりは突然に。
昨日のブログにツッコミが入りました(‘ω‘ )
イミュータブル大切!
— hiro@miraito (@hirodragon112) 2019年2月21日
まあ、この例の場合、UserクラスがchangeStatus()を持つのが本来は良いとは思いますが。 https://t.co/QIQOUy2NFE
なるほどたしかに!
changeStatusというフィールド値をUserに持たせたほうが、Userのフィールド値とか状態に触れる知識を外部に持たせないって出来ますね。
状態に対する関心も、あちこちに分散しない……!
ってことで、頂いたアドバイスを自分なりに解釈して実装してみる。
(で、出来たらちょっとレビューをお願いしてみる・・・!)
頂いたアドバイス
Userクラスは「User」を表すモデルだと思いますので、Userの状態はUserのみに内包されているべきかと。
— hiro@miraito (@hirodragon112) 2019年2月22日
User のstatusを変更する処理(今回ではChangeUserStatus())が Userクラス以外にあると、
そうすれば、Userの知識が他のクラスに漏れることなく、Userクラスは「User」を表す「モデル」として機能しだします。
— hiro@miraito (@hirodragon112) 2019年2月22日
今 @suin と話していてイミュータブル目線で適切な表現を貰ったので、合わせて紹介しておくと、
— hiro@miraito (@hirodragon112) 2019年2月22日
「この ChangeUserStatus() はミューテートしない関数というだけで、Userクラスがイミュータブルな訳ではないですね」
蛇足の蛇足としてご参考にまでに!
実装
class User { private $name; private $status; public function __construct(string $name, int $status) { $this->name = $name; $this->status = $status; } public function __set($name, $value) { throw new Exception('This object can't be set field value.'); } public function setStatus(int $status) { return new User($this->name, $status); } public function setName(string $name) { return new User($name, $this->status); } }
応用
フィールド値にインスタンスを持つ場合。
前に勉強したやつ実装してみる。
【デザパタ自作】イミュータブルパターン(インスタンス内包対応)【266日目】 - エンジニアのひよこ_level10
class User { private $name; private $status; public function __construct(string $name, Status $status) { $this->name = $name; $this->status = clone $status; } public function __set($name, $value) { throw new Exception('This object can't be set field value.'); } public function setStatus(Status $status) { return new User($this->name, clone $status); } public function setName(string $name) { return new User($name, clone $this->status); } }
感想?
こんな感じ・・・?
これで、たぶん値の変更は不可能になって、データは新しいオブジェクトを返すようになっているはず・・・?
使用感としても、ユーザーは内部に何を持ってるかを意識せず、関数だけ意識できる気がする。
// 全部違うインスタンスになる。たぶん変更出来ないはず $user = new User('youkan', new Status(false)); $user = $user->setName('Uiro'); $user = $user->setStatus(new Status(true));
Tell Don't Askの観点とか知らない言葉が出てきてるので、いつか勉強したいというか、
早くぺちおぶ行きたいのに、Laravel JP Conferenceとかイベントに被るから行けなかった・・・(登壇者だからどうあがいても行けなかった)
また今度こそ、行きたいね・・・!