「下書き」「一時保存」という要件を甘く見積もってはいけない
「一時保存や下書きできるようにしたい」といった要望が出てくることがあると思います。世の中のサービスでよくある機能ですしあったら便利だなと思うのも当然です。
同じ要望を受けた当時の私はその大変さに全く気づいていませんでした。
意外と考えることが多いよ、というのが伝わると幸いです。
当初明確になっていた仕様
- 入力フォームには必須と任意の項目があるが、必須項目が未入力状態でも一時保存できる
- 入力フォームにはファイルを添付できる
- 正式データと一時データは同じ一覧ビューの中で両方とも表示させる
- 一時データはユーザー単位ではなく共有される(誰かが作った一時データは自分も閲覧編集できる)
- 一時データは正式データに対してひとつのみ存在できる
最終的には上記以外にももっと細かい仕様になったのですが、この後の検討や設計の流れに沿って随時記載していきます。
データの持ち方の方針
方法としては以下二つの案がありました。
- 単一のテーブルで管理する
- 一時保存フラグなどを立てて正式か一時かを判別できるようにする
- 必須項目でも nullable にする
- 正式用のテーブルに加え、項目がほぼ同じ一時用テーブルの2つで管理する
- 正式テーブルの必須項目は not null にする
- 一時テーブルの必須項目は nullable にする
正式と一時を同一ビューで表示するという仕様があるので前者の単一テーブル管理の方が良さそうかとも思いましたが、ほぼ nullable なので入力内容的にもバリデーションが結構大変そうということから、後者の二つのテーブルで管理する案を採用しました。
採用案のメリデメの詳細は以下の記事が参考になりましたので貼っておきます。
状態管理と処理内容の整理
ここが当初の見込みと一番乖離がありました。
「一時データを正式保存したらどうなるべき?」みたいなことを網羅的に整理しました。初期段階でこんなもんかな〜と思っていたのが以下のパターンです。
- 保存データを一時保存したら、その保存データとは別に一時保存データが作成される
- 保存データを正式保存したら、保存データを更新する
- 一時データを正式保存したら、その一時データの内容で正式保存データに対して更新をかける
- 一時データを一時保存したら、一時データを更新する
ただこれには問題がありました。例えば以下の通りです。
-
新規作成時に一時保存した場合
一時データが新たに作成される。この段階では正式データは存在していない。
->(正式✖️・一時⭕️) -
1.で作成された一時データを編集して正式保存した場合
この時点では正式データはないので、一時データの内容を基に正式データが作成される必要がある。また下書き(一時データ)を正式保存したのに下書きが残ったままなのはおかしいので、正式データが作成された後、下書きは削除されるべき。
->(正式⭕️・一時✖️) -
2.で作成された正式データを編集して一時保存した場合
正式データの入力内容を基に一時データが作成される必要がある。元々編集していた正式データはそのまま残り、正式データと一時データが両方とも存在している状態になる。
->(正式⭕️・一時⭕️) -
3.で作成された一時データを編集して正式保存した場合
ユーザーの操作としては2.と同じようだが、2.とは異なりこの時点では対になる正式データが存在している。そのため一時データの内容を基にして正式データは更新される必要がある。一方、2.と同様に下書き側は削除されるべきである。
->(正式⭕️・一時✖️)
ここでポイントなのは例えば「一時データを正式保存する」という同じ操作でも、その編集している一時データと対になる正式データが存在するか否かで処理が異なるという点です。
他のパターンも含めてまとめたのが以下の表です。
UIからの操作 | 処理時点 データ有無 |
処理内容 | 処理後 データ有無 |
---|---|---|---|
正式データを新規作成 | 正式:✖️ 一時:✖️ |
正式データが作成される | 正式:⭕️ 一時:✖️ |
一時データを新規作成 | 正式:✖️ 一時:✖️ |
一時データが作成される | 正式:✖️ 一時:⭕️ |
正式データを正式保存 | 正式:⭕️ 一時:✖️ |
正式データが更新される | 正式:⭕️ 一時:✖️ |
正式:⭕️ 一時:⭕️ |
正式データが更新される +正式と対になる一時データが削除される |
正式:⭕️ 一時:✖️ |
|
正式データを一時保存 | 正式:⭕️ 一時:✖️ |
正式データの内容で一時データが作成される | 正式:⭕️ 一時:⭕️ |
正式:⭕️ 一時:⭕️ |
正式データの内容で一時データが更新される | 正式:⭕️ 一時:⭕️ |
|
一時データを正式保存 | 正式:✖️ 一時:⭕️ |
一時データの内容で正式データが作成される +編集していた一時データが削除される |
正式:⭕️ 一時:✖️ |
正式:⭕️ 一時:⭕️ |
一時データの内容で正式データが作成される +編集していた一時データが削除される |
正式:⭕️ 一時:✖️ |
|
一時データを一時保存 | 正式:✖️ 一時:⭕️ |
一時データが更新される | 正式:✖️ 一時:⭕️ |
正式:⭕️ 一時:⭕️ |
一時データが更新される | 正式:⭕️ 一時:⭕️ |
添付ファイルと削除に関する考慮も必要だった
前提として、当初明確になっていた仕様にも記載がある通り新規作成や編集時にファイルを添付できるわけですが、プロダクト特有の都合で、その添付ファイルは正式データと一時データとで共有して保持される仕様となっています。一時データに添付されたファイルは、正式データ側にも表示されるということです。
その上で、正式や一時の削除仕様の詳細は元々以下の通り定義されていました。
- 正式データを削除する時
- その正式データと対になる一時データが存在していればそれも削除する
- その後に添付ファイルも削除する
- 一時データを削除する時
- 対になる正式データに対しては何もせず残したままにしておく
- 添付ファイルは正式データと共有しているため削除しない
この場合、対になる正式データが存在しない状態で一時データを削除すると添付ファイルのみがゴミデータとして残ってしまうため、太字の箇所が考慮不足でした。そのため正しい仕様は以下の通りとなります。
- 正式データを削除する時
- その正式データと対になる一時データが存在していればそれも削除する
- その後に添付ファイルも削除する
- 一時データを削除する時
- 対になる正式データが存在する場合、正式データは残したままとなるため、共有している添付ファイルは削除しない
- 対になる正式データが存在しない場合、添付ファイルは一時データのみが保有している状態であるため、添付ファイルも削除する
まとめ
いかがでしたか?
もちろん私の担当したプロダクトの特性上たまたま複雑だった可能性もありますし、スマートに効率的に検討できたかもしれません。よくある機能すぎるのでベストプラクティスがあるのかもしれないですね。仮にあるならもっと早く知りたかったです。
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion
これは問題ないと思います。
正式データからアウトプットがあるとするなら、問題があります。
正式データを元に契約書を生成するのであれば、一時保存したファイルも出力されます。
ワークフローであれば、後続の作業に一時保存したファイルが表示されます。
一時データがあるときは、アウトプットできないとするなら問題ないですが、そうであれば、一時データに添付されたファイルは、正式データ側に表示する意味がありません。
クライアントはよく検討したうえで要望を出しているわけではないので、辻褄が合わないこともあります。
仕様がわからないので何ともいえないですが。
チケット管理的な機能なのですが、実は諸々の都合があって敢えて(仕方なく?)この仕様になっています。とは言えご指摘の内容はおっしゃる通りですし、それ踏まえてもっと良くできたかもな〜とも今更ながら思いました。