※注意:これは主張ではなく自分が分かっていない分野に関しての学習メモです。
「痛いかもって思いながらもラノベ風タイトルを付けちゃう系おじさん、今日もブログで空回っている」ことはさておき、Spring boot 3を学習していて思ったのだが「やたらゲッターセッターしているなあ」自動で書いてくれるからそれはそれでいいか?と思っていたが、「何でもゲッターセッターしてはダメ」という風潮があるのをふとこちらの記事「昔話「getter/setter おじいさん」」を読んでいて思い出した。
⋯よくよく考え直してみると、この原則自体は正しいはずなのだが、もろもろの知識が足りないので応用が効かないことに気づいたので改めて色々と考えてみた。
getter/setterについての見解
結論から言えば、privateに限定した話ではなく、適切な実装をすべきという話ではないか。何でもかんでも、getter/setterが悪いとか逆に良いとか言う部分的な話ではなく、技術者ならばここで徹底して”おじさん”と話し合うべきだったのでは?と思ったのですが、そうじゃないナウでヤングな彼が『ドメイン駆動設計』を机にポンと置いて去ることしかできないというのがなんだか悲しい。まあ、ネタみたいなので、ネタにつっこむのは野暮ですね。しつこいおじさんきらい。
「privateなクラス変数にsetterとgetterつけたらpublicと同義」はさすがに違うのではないか。だったらわざわざ外部とのやりとりをする出入り口のgetter/setterはつくらない。
個人的にこのようにしておく理由は「デバッグがしやすい」というのが1つ上げられる。出入口が1つに限定されていれば必ずここを通ることが保証される。
考えなしに不用意に外部の口を作るのは問題だけど、ケースバイケース。
インターフェースによりgetter/setterを定義しておくことで、implementsした時にインターフェースのルールを守ることで同じメソッドで処理部分を書くことができる=多様な実装を1つのIFで実現することでポリモルフィズムが実現できる。
このように共通インターフェースにより処理の実装が可能になり、クラスを疎結合にして柔軟性を保つことで、差し替えやモック化によるテストも実施しやすい。
補足:Spring bootってgetter/setterだらけでは?
spring boot の実装時にgetter/setterの塊(ブロック)を目にすることがあるが、これはJavaBeans仕様に従っている為である。なお、JavaBeansの仕様に従いすぎて設計が形骸化することを「JavaBeans症候群(JavaBeans Syndrome)」という。
本当に必要なgetter/setterを書いたり、finalフィールドを付けてコンストラクタで注入する(この場合はsetterが不要になる)。どうしてもsetterが欲しい場合は設計意図を明確にしたsetterを用意する。EntityやValue Objectにはgetter/setterを使わない。
Lombokを使うと便利なのでは?
Lombokという外部ライブラリを使用することで、アノテーションによりgetter/setterなどのボイラープレートコードを記述が可能になる。
また、DTOにはLombokの範囲でgetter/setterを付与する。(ただし、Lombokは便利なツールだが裏でどのように動いているか分かりづらいため使われないケースもある)
例えば、Lombokの@Dataアノテーションは協力で様々なメソッドを自動で生成するので禁止されている場合もある。
※Lombokはロンボクと読むそうで、インドネシアに実際にロンボク島があるそうだ。
recodeとLombokは何が違うのか?
recodeはjava標準=言語仕様のため、外部ライブラリのLombokよりも使うことが好まれる傾向がある。DTOなどのシンプルなオブジェクトに用いる分には問題ない。ただし複雑なビジネスロジックを持つクラスの場合はrecodeを使うべきではなく、Lombokのほうが柔軟な設計が可能である。
※recodeはただのc言語で言う構造体みたいなものだと思っていたが違うようで「継承不可」「セッター不可」という特徴がある。つまりは、生成時に中身の内容が決まり、後から変わらないイミュータブルな特性を持つデータを使用するための仕様。
※Lombokはコードを自動生成する多用な用途に使用するライブラリなのに大して、recodeはイミュータブルなデータ活用の基本的な仕組みである。
まとめ
「DTOはケースバイケースでrecodeやLombokを使用するが、安易にgetter/setterは使うべきじゃないよね」ってことなんじゃないかな。
コメント