Open3
サービス層とリポジトリ層の責務の切り分け
要件
イベントを管理するシステムを作る。
そこでイベントテーブルとイベントヒストリーテーブルを作成する。
イベント作成時はイベントテーブルとイベントヒストリーテーブルにデータをインサートする
更新時はイベントテーブルの該当レコードを更新し、イベントヒストリーテーブルにデータを作成する
リファクタ前
仕様・要件
イベントの更新処理
指定された eventId に対応するイベントを更新する。
操作ユーザー(operationUser)の情報を履歴(eventHistory)とイベント(event)に記録する。
履歴管理
eventHistory を suffixNumber でバージョン管理。
最新の履歴を取得し、更新前の状態を保存。
トランザクション管理
履歴作成とイベント更新はトランザクションで処理し、一貫性を保証。
戻り値
更新処理完了後、更新されたイベントの id を返す。
service.ts
public async updateEvent(
id: number,
input: UpdateEventInput
): Promise<number> {
const data = await this.eventRepository
.updateEvent(id, input)
.catch(() => {
throw new NotFoundException('event id or event history is not found');
});
return data.id;
}
repository.ts
public async updateEvent(
eventId: number,
input: UpdateEventInput
): Promise<Prisma.Prisma__EventClient<Event>> {
const baseInfo: Pick<Event, 'uniqueId' | 'name' | 'createdAddress'> = {
uniqueId: input.uniqueId,
name: input.name,
createdAddress: input.operationUser,
};
return this.prisma.$transaction(async (tx) => {
// 最新のイベントデータを取得
const latestEventHistory = await tx.eventHistory.findFirst({
where: { id: eventId },
orderBy: { suffixNumber: 'desc' },
});
if (!latestEventHistory)
throw new NotFoundException('Event History not found');
await tx.eventHistory.create({
data: {
...baseInfo,
id: eventId,
suffixNumber: latestEventHistory.suffixNumber + 1,
createdAddress: input.operationUser,
},
});
const eventData = await tx.event.findUnique({
where: { id: eventId },
});
if (!eventData) throw new NotFoundException('Event not found');
return tx.event.update({
where: { id: eventId },
data: {
...baseInfo,
updatedAddress: input.operationUser,
},
});
});
}
リファクタ後
- サービス層とリポジトリ層の責務の分離
- 404と500の使い分け