DBテーブルにstateカラムを用意して、stateを更新していくような作りは良くないと思ってるので理由を書く。
サンプルケース
Aフォルダに大量のファイルが入っており、1時間に1回、1つのファイルをBフォルダにコピーする定時実行処理があるとする。
テーブル
file_name | state |
---|---|
a.jpg | yet |
b.jpg | yet |
c.jpg | yet |
a.jpgが処理されたらこうなる
file_name | state |
---|---|
a.jpg | finish |
b.jpg | yet |
c.jpg | yet |
定時実行処理の最後にstateをyet => finishにする処理が書かれている。
「c.jpgについて早く処理してくれ」と言われた
ほっておいたらいつか処理されるけど、何らかの事情で急げといわれたのでc.jpgについては手動でコピーした。
そして、c.jpgのstateをyetからfinishに変えるのを忘れていた。
file_name | state |
---|---|
a.jpg | finish |
b.jpg | yet |
c.jpg | yet (本当はもうコピーされてるけどyetのまま) |
すると、そのうちにc.jpgの移動処理が実行されたときに、すでにBフォルダにはc.jpgが存在するためエラーが起きてしまった(「上書きしますか」って聞かれて処理が止まってしまったってことにする。)
何が起こったか?
データと事実に不整合が生まれてしまった。 実際にはc.jpgのコピー処理は(手動で)終わっているのに、データ的には終わっていないことになっていた。
どうすればいい?
stateは事実から導き出すようにする。
今回の場合だと、Bフォルダにファイルがあることを確認して、なければyet、あればfinishと導き出す。
c.jpgのstateは? => 「Bフォルダにc.jpgがあるからfinishです」
つまりテーブルにデータで持たない。処理の中で問い合わせて確認する。
処理は「こうなってほしい」という結果があるはずなので、それの状態を確認してstateを判断する。
上記ケースでのstateカラムは本質的にはデータが冗長になっている
stateカラムは、ようは、データが冗長になっているのだと思う。
ファイルの存在が状態を示しているのに、それをstateカラムとして持たせている。
同じことを指し示す情報が2箇所に存在し、連動していない。
ファイルの存在が変化したとき、合わせてstateカラムの内容を書き換える必要が発生している。
※更に書くと、Aフォルダを見たらなんのファイルがあるかわかるから、file_nameカラムのファイル名データも冗長。
処理対象ファイルが指定されていて、そのファイル名が保存されている、ということなら冗長ではない。
冗長なデータがたくさんあると。。
正常に処理が動いているときはいいけど、なんらかのデータ変更を手動で入れたときに、データの整合性を手動でとっていかなくてはならなくなって辛くなる。
どこの整合性をとらないといけないのかの判断はシステムの広い範囲を把握しないと導き出せないので非常にスコープが大きくなってよくない、と思いました。