はじめに
稼働中のシステム改修(機能改善、不具合修正など)を行う際、必ず影響調査を行います。
その際、システムの全体像を把握したいと思うことってありませんか?
特に、業務ルールが変わって、取り扱うデータにも影響しそうなケースでは、「どの機能がどのデータを触ってるの?」というような関係性を把握したくなりますよね。
そういうケースでは、私はまず「CRUD図があるか」を確認します。
CRUD図とは、各機能がDBのどのテーブルに対して、作成(Create)、読み込み(Read)、更新(Update)、削除(Delete)を行うかを表形式で表したものです。
例えば、以下のような感じ。
CRUD図は必ず作るものではありませんが、私がこの業界の仕事を始めた2000年頃にはすでにあり、今も作る機会があります。
CRUD図を作る理由というのは、今でも通じる部分があると思いますので、今一度、実際の作業でどう役立てているかを振り返りつつ、CRUD図の価値を見直してみましょう。
実際の作業で役立てているところ
CRUD図は、「各機能とデータ操作の関係性を俯瞰できる」ところが良い点だと思っています。
実際の作業では、主に、以下のような点で役立てています。
これらは、システムを新規に開発する場合でも改修する場合でも効果があります。
- システムがやっていることをざっくりと理解する
- データのライフサイクルを把握し、そこに矛盾が無いことを確認する
- 保守時の影響調査や容量削減の目安として活用する
- テーブルの更新順序に起因するデッドロック防止策の一つとして役立てる
1. システムがやっていることをざっくりと理解する
システムの全体像を理解するのに役立つ資料はいくつかあると思いますが、CRUD図も割と役に立ちます。
CRUD図には、システムを構成する機能とデータの種類が、一つの表として表現されます。
機能名やデータを保存するテーブル名は、「名は体を表す」形で付けることが多いと思いますので、それらが一つの表で確認できることで、システムがやっていることをざっくりと理解できるわけです。
CRUD図を作る際も、機能の並び順やテーブルを書く順序を、関連性があるものをまとめる形で書いておくと、より理解しやすくなります。
2. データのライフサイクルを把握し、そこに矛盾が無いことを確認する
(1) データのライフサイクルと機能の動作順の確認
例えば、前述で例として挙げたCRUD図のテーブルAの場合、「テーブルAのデータは、機能Aで作成されたものを機能Bで更新し、機能Cで削除される」というデータの流れ(ライフサイクル)が見えてきます。
機能の動作順も「機能Aを動かしてから機能Bを動かす必要がある」ことや、「機能Cのあとに動く機能があった場合に、テーブルAのデータを操作する想定にしていないか」をチェックすることができます。
これは、新規開発時はもちろんですが、あとから機能を追加する場合も矛盾がしないように追加するための目安にできます。
(2) データのライフサイクルの単純な抜け漏れチェック
あるテーブルのデータが、更新(Update)のみしかなく、作成(Create)する機能がどこにも存在しないような、データのライフサイクルの単純な抜け漏れも見つけることができます。
(3) 他の設計物の整合性の確認
CRUD図を作る際に元にした設計物があると思いますが、CRUD図にしてみると、元にした設計物の問題点が見えてくることがあります。
例えば、各業務ごとに業務フローを作っている場合、他の業務で作られる想定だったデータが必要なタイミングで作られていない、といったことがCRUD図のデータ操作部分から見えてくることがあります。
データを主体にして、そのライフサイクルを各業務貫きで見れるCRUD図の良い点ですよね。
元にする設計書が完璧であればこの問題は起こりませんが、現実的にはそれは不可能ですよね。
(システムの特性にもよりますが、そういうのが見つかる前提で柔軟に対応できるような開発の進め方にしたいものです。)
(4) バッチ処理の動作順の根拠
バッチ処理として動かす機能が複数ある場合、時間がかかることが予想されるバッチ処理同士は、パラレルで動かしたいですよね。
操作するデータが関係なければ、パラレルで動かせるわけです。
逆に操作するデータに関係性があるなら、シーケンシャルで動かす必要があります。
CRUD図の各機能のデータ操作範囲を確認することで、バッチ処理の動作順の計画を立てる根拠の一つにすることができます。1
もし、シーケンシャルで動かす必要があるが、バッチを動かす時間内にはまらないような場合、そもそもの機能の見直しなども必要になってきます。
3. 保守時の影響調査や容量削減の目安として活用する
テーブルの利用状況を把握することができるため、保守時の影響調査や容量削減の目安として活用します。
(1) 影響調査の対象機能の絞り込み作業の軽減
データの更新内容が変わる場合や、テーブルレイアウト自体を変更するような場合、具体的な影響内容を調査する前に、まずは、そもそも影響調査が必要となる対象機能を絞り込む必要があります。
CRUD図があると、「影響調査の対象機能を絞り込む」作業を軽減できます。
CRUD図があると、どの機能がどのテーブルを操作しているか、各機能の設計書やプログラムを見なくても把握できます。
対象機能の絞り込みで軽減できた分を、各機能の具体的な影響内容の調査に割り当てることができます。
(2) 影響調査の計画立てに活用
影響調査の対象機能が絞り込めたあと、片っ端から調査するよりも優先順位を付けて調査を行った方が良いです。
ユーザーの業務影響が大きそうな機能から調査するのはもちろんですが、データ操作内容からも優先順位を付けることができます。
例えば、登録するデータ項目が増えた場合、データを作成(Create)している部分や更新(Update)している部分に影響が出る可能性が、データを削除(Delete)している部分よりも高くなります。
こういった場合、影響調査の対象機能が行っているデータ操作の種類とその割合がわかると、影響調査自体の工数見積りも行いやすくなるわけです。
CRUD図があると、こういった情報が読み取れます。
(3) 思い込みによるミスの軽減
テーブルレイアウトに変更がある場合に、実際のプログラムベースで影響調査をしている時、その変更対象のテーブルとは関係無さそうな機能が引っかかってくることがあります。
影響調査をする際、データの種類からおおよそ「この機能に影響がありそう」みたいな当たりをつけていることもあるかと思いますし、効率的に調査をするには必要と思います。
しかし、全く関係無さそうな機能ゆえに、稀に、それが邪魔をして漏らしてしまうこともあります。
CRUD図で、全く関係無さそうなテーブルを操作していることが把握できれば、逆に「何のために操作しているのだろう」という意識を持った上で調査をすることができます。
その結果、影響調査結果の精度が上がることが期待できます。
(4) 容量の削減
改修を繰り返しているうちに、どの機能からも操作されない不要なテーブルが出てくることがあります。
CRUD図上で不要なテーブルが明確になるので、テーブル自体を削除して容量を減らすことができます。2
データベースは、定期的にバックアップを取得すると思いますが、そのバックアップのデータ量を減らすことにもつながります。
クラウドサービスを利用している場合で、容量に応じて課金されるようなケースでは、容量の削減も重要となってきます。
4. テーブルの更新順序に起因するデッドロック防止策の一つとして役立てる
CRUD図は、そもそも「データの更新とかを把握しやすくしよう!」という役割があるので、テーブルの更新に関係する情報を書いても良さそうですよね。
デッドロックが発生する要因はいくつかありますが、テーブルの更新順序が一貫していないことも要因の一つです。
この要因を取り除くのに、CRUD図を役立てます。
CRUD図のテーブル名のところにテーブルの更新順を振っておくなど、CRUD図を見た時にテーブルの更新順序を意識できるようにしておくと良いです。
(こうしようと思った理由は、後述の「余談:デッドロック発生で後悔」を見てください)
おわりに
今回は、CRUD図の価値をあらためて見直してみました。
CRUD図に期待し過ぎている感もありますが、CRUD図を作るかどうかの判断材料にはなるかと思います。
もし、CRUD図を作ることが決まっているとしたら、どうせ作るなら存分に役立てたいですよね。
CRUD図は、全体を俯瞰する系の資料となるので、アジャイル開発でも作っておいた方が良い方の設計物だと個人的には思います。
実際の開発現場では、設計が最新化されていないことも多々あり、設計物に書かれていることを100%信じることは難しいかもしれません。
そのため、影響調査時は、結局はプログラムなどの実際の実装を調査しているケースも多いと思います。
ただし、その実装に対する調査結果だけで影響を判断するのと、それを裏付ける設計物があって判断するのでは、必要になる時間も、判断結果に対する自信の持て方も大きく違ってきますよね。
最近は、業務ごとに独立性を持たせて、他の業務に影響しないように作る方法も主流になってきていると思います。
(業務ごとに開発するアーキテクチャーを選択、データベースも業務ごとに独立して持つ など)
「2025年の崖」と言われているようなレガシーシステムの刷新方法としても注目されているかと思います。
そいうった方法が出てきている背景は、今回のCRUD図を役立てる理由と通じる部分もあるかと思いますので、そういった根本的な部分を考えるのもまた良いかなぁ、なんて思います。
余談:デッドロック発生で後悔
CRUD図からは話がそれますが、デッドロックの苦い経験の話です。
システムを新規開発する時は、デッドロックを防止するような方式設計やコーディングルールを決めて、それを守っていると思います。
改善開発を繰り返していると、だんだんとこういった非機能面を意識しなくなってくるように思います。
改善開発は機能面の改善が多いので、どうしても機能の方に意識がいきがちで、こういった非機能面が置いてきぼりになる傾向があります。
また、既存の形ができあがっているプログラムに手を入れるので、方式設計などを確認せずに、既存に合わせて何となくコーディングしてしまう場合もあります。(怠慢ですが・・・)
その結果、テーブルの更新順を意識しておらず、画面からの更新時に追加したテーブルの更新処理が原因で、デッドロックが頻発するようになってしまいました。
日中でも定期的にバッチが動いているようなシステムだったのですが、そのバッチ処理とぶつかって、本番でデッドロックが発生・・・。
局所的な改修だったので、テストも画面の機能的な確認のみしかしてませんでした。
デッドロックは方式設計やコーディングルールを守れば、発生を大幅に抑制できる類のものなので、発生させてしまった時は後悔しました・・・。
「なんで確認しなかったんだろう」と後悔しましたが、そもそも意識もできていませんでした。
(それ以来、途中から既存システムの改修を担当するような場合、方式設計やコーディングルールの存在を確認するようになりました)
そういうこともあって、CRUD図があるなら、テーブル操作の確認のためにどうせ目にすることになるから、そこにテーブル更新順序も書いておこうという考えに至りました。
CRUD図にテーブルの更新順序を書いておくと、「デッドロック」そのものも意識するようになります。
デッドロックが発生してしまうと、ユーザーに迷惑をかけてしまうので、発生させないようにしましょう。3