🦔
意味のなさそうなDTO(Data Transfer Object)
Daily Blogging93日目
設計を気にし始めると次から次へと概念とかパターンが出てきて大変
このクラス意味あるのかな?
APIのレスポンス用にデータを成形しているだけのクラスがある
※ブログ用に加工済み
class ResponseProducs
attr_reader :a_ids, :b_ids
def initialize(a_ids: [], b_ids: [])
@a_ids = a_ids
@b_ids = b_ids
end
end
呼び出しもとはこんな感じ
a_ids = fetch_a_ids
b_ids = fetch_b_ids
ResponseProducs.new(a_ids: a_ids, b_ids: b_ids)
いやこれいるかな????
なんか冗長的だしクラス一つ増えて逆にわかりづらい気がする
複数箇所で利用しているわけでもない
こういうクラスはどう扱うべきなのか
色々調べてる時にDTOとの出会いを果たす
これ多分DTO
DTO(Data Transfer Object)とは、
異なるシステムや層間でデータを転送するためのオブジェクトです。DTOは通常、ビジネスロジックを含まず、データを持ち運ぶだけの役割を果たします。
by ChatGPT
異なる層っていうのは、クリーンアーキテクチャとかで見るあの層のこと
ResponseProducsもDTOといえそう
ビジネスロジックもないし
DTOの例
DTOの例でいうと、Serializerが当てはまる。
class UserDTO
attr_reader :name, :email
# userオブジェクトをそのまま受け取る
def initialize(user)
@name = user.name
@email = user.email
end
# 必要に応じて他のメソッドを追加
def full_name
"#{name} <#{email}>"
end
end
こう使う
user = User.find(1)
# 最終的にこれを返す
user_dto = UserDTO.new(user)
これはレスポンスに含めたい値を削り取ってる
こういうのは、レスポンスに含めてはいけない値の排除ができるので意味ある
こうすればいいんじゃないか
ResponseProducsは受け取ったデータをインスタンス変数に格納し直しているだけなので冗長的
他のAPIでは利用していない
こういう場合は、とりあえずリファクタの方法が2通りありそう
さよならResponseProducs
一つ目はResponseProducsの削除
クラス化している意味ないから削除する。
呼び出しもとでHashとかStructした方が良さそう
a_ids = fetch_a_ids
b_ids = fetch_b_ids
{ a_ids: a_ids, b_ids: b_ids }
Factoryメソッド
もう一つは、データの取得とオブジェクトの成形を同じクラスで受け持つ
class ResponseProducs
attr_reader :a_ids, :b_ids
def initialize(a_ids: [], b_ids: [])
@a_ids = a_ids
@b_ids = b_ids
end
# Factoryメソッドでデータ取得も統合
def self.build
a_ids = ModelA.fetch_a_ids
b_ids = ModelB.fetch_b_ids
new(a_ids: a_ids, b_ids: b_ids)
end
end
個人的にはデータの整形とデータ取得ロジックの呼び出しが1箇所にまとまっている方が好き
Discussion