isyumi_netブログ

isyumi_netがプログラミングのこととかを書くブログ

状態を管理する変数は正規化しよう

先日のブログで「あなたの書いたプログラムには状態を保持した変数がある。そこが散らかるとめんどくさいことになるのできちっと管理しよう」という話をした。 

blog.isyumi.net

 

おさらいだが、状態変数というのはサイクルをまたぐ変数だ。博士のメモだ。管理するための色々な技法があるので一つ紹介しよう。RDBと同じように状態変数も正規化しよう。正規化はデータ同士の不整合が起こらないようにするために、重複した値を削除していくことだ。データの矛盾にはシステム外との矛盾とシステム内での矛盾がある。あなたのシステムに20歳と登録されている人が本当は30歳だった、というような矛盾は防ぎづらい。しかし、システムのある場所には20歳と登録されているのに、他の場所には30歳と登録されるような間違いは正しいプログラミングをすれば防げるはずだ。

ここに動画一覧とユーザー一覧がある。ここでuser1がvideo2を再生したとしよう。動画エンティティの視聴ユーザー一覧にuser2を追加した。

正規化していない

しかし、user1の視聴動画一覧にvideo2を追加するのを忘れてしまった。これでは状態変数が矛盾してしまう。そこで動画一覧とユーザー一覧に加えて視聴履歴一覧を追加した。これで視聴履歴一覧に値を挿入するだけでよくなった。

正規化した

小さな点だが勘違いしないようにしたいのは、正規化の目的は手数を減らすことではなく矛盾が発生しないようにすることだ。データ構造を考えるときはどうすればより矛盾が発生しにくいデータ構造になるかを考えよう。

また、重複には「言えること」も含まれる。例えば、四角形の縦と横と面積を持つ変数を考えてほしい。

class Rectangle {
int height;
int width;
int area;
}

四角形の面積は縦 * 横である。つまり、縦・横・面積の三つのうち2個判明していれば最後の1個は不要である。状態として持つのではなく、面積が必要になった時に計算すればいい。

class Rectangle {
int height;
int width;
}

他の例をあげれば

  • 誕生日と現在時刻と年齢
  • Aさんの位置とBさんの位置と距離
  • 税抜き価格と税率と税込価格

などがある。このような変数も重複と考えて削除していこう。