blog.oskn259.com

このエントリーをはてなブックマークに追加

穴だらけのテーブル設計には懲役・罰金が発生してほしい(浄化槽編)

こちらの記事の続きです。
https://blog.oskn259.com/article/how_confusing_table_effects

こちらを見ていただいてからの方が、より一層お楽しみいただけるかと思いますが、 読んでいなくても問題ありません。

あらすじ

  • 前任者の残したテーブル設計がヤバい
  • それに引っ張られてAPIコードがヤバい
  • それに引っ張られてフロントコードがヤバい
  • 死ぬな、このままでは・・・!
  • 全ての罪を背負う浄化槽構想

浄化槽構想

全ての問題はテーブル構造が終わってることから始まりました。
ベストなのはこの構造から作り直すことですが、 そうするとapi, front, batchなど全てを作り直す作業が必要となり、 しかもリリースできるのはそれら全てが揃ってからになります。

リリース以来最大のマンモスプロジェクトになり、 その最中は新規機能の追加といった、ユーザーに価値を届けるような施策は一切行えません。

そこまでしなくても、段階的に改善していく方法はないでしょうか?

そもそも、機能が正しく分離されていれば付け替えが可能なはずではないでしょうか?
こうした結合度の高さも問題と言えそうです。

そこで構想したのは、「浄化槽」 を定め、そこに全ての罪を集約することです。

図のように、Access Controll層とData Access Object層を設けることによって、 まったく新しい概念設計に変換してしまおうというものです。

ひとつずつ見ていきましょう。

Data Access Object layer

テーブルをTypeScriptの世界に連れてくるための存在です。

テーブルのスキーマをUserEntityProfileEntityといった型に一対一変換して扱っており、 テーブル上の概念設計をそのまま使用する形になります。

また、updateを行う際のユーテリティ関数も用意しています。

以降テーブル上のデータに触る際には、必ずDataAccessObjectを介します。
問題の根本的な解決はここでは行われませんが、その後の記述が圧倒的に簡潔に、見やすくなります。

Access Controll layer

元のテーブルの概念を 全く新しい概念設計として提供 する層です。

例えば現行テーブル設計の問題点として テーブルと意味の非対応 という問題がありました。
userprofileという名前でありながら、実態は全く違うという状態です。

Access Controll layerでは、ドメイン上の単語と実態が結びつくように変換を行います。
例えばprofileという単語が指すのは、他ユーザーに公開したい自分のプロフィール情報、になるわけです。
一旦全てを取得してその後加工 」 をここで済ませているとも言えます。

もう一つの重要な機能として、 整合性を失う変更を防止する というものがあります。

重複フィールド の存在する状況で整合性を担保するために 特定フィールドの無視 を徹底する必要があることは、先の記事で説明しました。
Access Controll layerはこれを徹底することで、それより上のレイヤーへの問題の波及をブロックします。

型の変遷

最終的にデータ型はこのように変遷して、最終的にフロントへと届けられます。

  • user table
    • ユーザーの登録に関わる情報、プロフィールの一部を保持
    • profile tableと重複フィールドアリ
  • profile table
    • ユーザーのプロフィールを保持、登録に関わる情報も一部保持
    • user tableと重複フィールドアリ

↓↓↓↓

  • UserProfileForResponse
    • ユーザーが自ら公開し、他ユーザーに見せたいプロフィール情報
  • UserStatusForResponse
    • ユーザーの登録に関わる情報や、統計情報

フロントコード的にも、変換後のデータを受け取った方が扱いやすそうですよね?

api「v3」

構想に基づき、既存のAPIコードを改修していく線もありますが、 今回はAPIコードベースをv3として新設して徐々に移行していく方針を採りました。

開発言語にはnodeを採用しました。
これはフロントと同じ言語を採用することで要求スキルセットを絞り、 少ない開発者でプロジェクトを進められるようにする目的です。

v2でなくて?

本題とは逸れますが、APIコード自体がヤバい問題も存在しており、 過去にAPIv2を発足していました。

だいたいこんな流れでした。

  • v1ではPHPを採用
    • CodeIgniterという聞いたことなかった使用
  • v2発足
    • 見えちゃいけない情報を返している問題の改善を目指す
    • そのときの共同担当者がPHPの方だったので、引き続きPHPを採用
    • フレームワークもCodeIgniterを続投
  • 共同担当者退職、工数不足により頓挫
    • 一部の機能はv2で動くように
  • v3発足

現在

一部の機能はAPIv3で稼働しています。

手放しで喜べる状況とはまだいきません。
フロント側も先の後遺症が大きく、さらにredux-sagaによる難読化など別の問題を抱えており、 やさしい世界にはもうひと手間必要な状態です。

しかし、移行できた機能に関しては素晴らしく抽象化されており、 サービスにおける単語と実際の機能がしっかりと紐づいています。
また、フロント側が特に意識しなくても、整合性を失うような変更はできないようになっています。

このクソッタレな世界に一輪の花を植えることができたのではないでしょうか。

後任者氏へ

各所、命名が怪しいのは自覚しています。
もっと設計パターンを勉強していれば、より良い命名や選択肢をとれたかもしれません。

しかし、まずは設計思想を理解してください。
一見するとやたらと層状になっていて不要な構造にも思いますが、 ちゃんと意味があってこうしているのです。

語り継がねばならぬ。