記事
· 2022年3月10日 4m read

ストレージ定義の変更による危険性

背景

先日、ObjectScript の永続(Persistent)クラスのプロパティを編集していたところ、ストレージ定義が最後の変更を反映するように更新されていないことに気づきました。

この場合、クラス定義に不要となったプロパティを削除した上で保存し、再コンパイルしましたが、それでもストレージ定義に残ったままになっていました。

それでも焦ることはありませんでした。 ストレージ定義がコンパイル時に自動生成されるのであれば、それを削除して、クラスを再コンパイルすればよいからです。 もちろん、この後、削除されたプロパティはストレージ定義に表示されなくなりました。

問題解決... ですよね?

(ブブー、間違いです)

後になって、このアプローチはクラスにデータが保存されていないときに機能することがわかりました。 ただし、既存のデータがあるのであれば、重大なデータ参照の問題が発生する可能性があります。

 

そもそもストレージ定義とは?

ストレージ定義はクラスプロパティとデータベース内のその物理ストレージ場所をリンクするマップとして機能します。

複数のスロットのある本棚とどのスロットに本が収まっているかを追跡するためのリストがあるとします。 新しい本は、常にリスト上で空いている一番左のスロットに配置され、スロットは昇順で番号が付けられています。

 

シナリオ ストレージ定義 ステータス 本棚での喩え
1 クラスにはまだデータが保存されていない状態で、ストレージ定義を変更します。 OK                                                                                              棚に本がない状態で、後に本が収納されるべきスロットのマップを変更します。 データなし = データ参照の問題はありません。
2 クラスにデータが保存されている状態で、データを保存せずに新しいプロパティを追加し、その後でプロパティを削除して別のプロパティを追加します。 (つまり、データが保存される前に、最後に追加されたプロパティの名前を変更します) OK スロット 3 は、次に空いている棚のスロットです。 本 C がスロット 3 に配置されることを書き留めても、実際にはまだスロット 3 には配置しません。その状態で、スロット 3 は本 D 用に予約されているとしてマップを更新します。
3 クラスにデータが保存されている状態で、データが保存されたプロパティをストレージ定義から削除します。 エラー 本棚のスロット 1~3 には本が収まっています。 マップには(スロット 1: 本 A、スロット 2: 本 B、スロット 3: 本 C)と示されています。 本 B をマップからのみ削除します。 本 B はまだ棚にありますが、マップではスロット 2 が空になっている状態です。 次に新しい本を追加する際に、マップにはスロット 2 を利用できることが示されているため、無意識にスロットをダブルブッキングすることになります。

 

シナリオ 3 の続き

この問題は、マップから本 B を削除するときに、物理的にスロットからも取り除くことで回避したいところですが、 それをやってはいけません。誤ってデータテーブルを破損してしまう可能性があります。 驚いたことに、データを手動で変更する方が、棚から本を取り出すことよりもはるかに危険です。

 

オプション ストレージ定義 本棚での喩え
1 何もしません。 データとストレージ定義はそのままにしておきます。 本 B を二度と読むことがないのであれば、それを探すこともないため、マップに存在したままでも問題はありません。
2 ストレージ定義に使用しなくなったプロパティが残っていることが気になるのであれば、データはそのままにして、使用されなくなったことを示すように、ストレージ定義内のプロパティ名を更新します(例: propertyA => propertyADeprecated) 本 B は棚に置いたままにし、マップ内のスロット 2 のタイトルを「本 B」から「本 B(関連性なし)」に変更します。

 

お読みいただきありがとうございました! 

@Vivian Leeさんが書いた元の記事へ
ディスカッション (0)2
続けるにはログインするか新規登録を行ってください