SmartHR Advent Calendar 2020 の3日目です。
本記事の概要
最近、テーブル定義をチームメンバーに共有する時は Rails migration のアレではなくて TypeScript の型定義で表現するようになりました。バックエンドエンジニア以外への配慮というよりも(それも少しはあるけど)、自分自身がよりイメージしやすいからというのがあったり無かったり。
— Wataru MIYAGUNI (@gongoZ) 2020年9月7日
例えばこういう感じでテーブル設計(物理データモデル)したものを
エンジニア含めデザイナーやプロダクトマネージャー(以下、PdM)に共有する論理データモデルは、以下のように TypeScript の型定義風にして共有するみたいなことをやってみている、というお話です。
type UUID = string type Book = { id: UUID authorId: UUID publishedAt: Date } type Author = { id: UUID name: string penName: string | null }
またはこんな感じ
type UUID = string type Book = { id: UUID author: Author publishedAt: Date } type Author = { id: UUID name: string penName: string | null books: Book[] }
TypeScript 風なので、なんだったらこれでも OK
type 書籍 = { id: uuid 著者: 著者 出版日: Date } type 著者 = { id: uuid 氏名: string ペンネーム: string | null }
補足
- SmartHR 全体の開発フローとして採用(試用)しているものではありません。個人的な活動です 👍
- この施策で何が変わったかとかまでは書いてないです。まだ始めたばかりなので 💪
経緯
1. 前提
SmartHR における開発の流れは、ざっくりこうなっています(本当にざっくりです)。
なんやかんやあって、スタート 🏁
抽出されたユーザーストーリーから、PdM が *1 概念データモデル を作成する
チームメンバーでレビューしていく
設計していくぞー
エンジニアが 物理データモデル を作成(テーブル設計)する
チームメンバーでレビューしていく
開発していくぞー
なんやかんやあって、リリース 🎉
今回は 5 〜 6 のお話です。
2. 発端
ある日、とある新機能開発のテーブル設計をチームメンバーに共有する機会がありました。 ERD を見てもらい、共有会は無難に進み、なんやかんやありながらも最終的に GoGo の方針が固まりました。
その過程で、とあるメンバーとこういったやりとりがありました。
👳♀️ = 僕 👤 = フロントエンジニア --- 👳♀️ 「というわけで、こんな感じのテーブルにしようと思います」 authors テーブル: t.string :name, null: false t.string :pen_name t.timestamps books テーブル: t.string :author_id, null: false t.datetime :published_at 👤 「null: false ってなんですか?」 👳♀️ 「データベースの NOT NULL 的なやつの ActiveRecord::Migration での記法ですね!」 👤 「ついてないやつは Nullable?」 👳♀️ 「です!」 👤 「t.timestamps って何ぞや」 👳♀️ 「created_at と updated_at を同時に生み出してくれるすごい奴です」 👤 「拝承」
何気ないやりとりでしたが、後日あらためて考えた結果、あまり私の共有の仕方が良くなかったなと思い至りました。
- Ruby on Rails に(この時点ではまだ)不慣れだったメンバーを含めた共有会で、この見せ方は逆にわかりづらい
- いずれは慣れていってもらうというのが理想系だが、そもそもスタートに見せる形ではなかった
- そもそも詳細な実装については、このあとのコードレビューで見てもらうことになっている
- スタートとしては、まずは認識の誤差を埋めるために イメージしてもらいやすい形 にすべきだった
- 「どうせこのまますぐコードに写して commit するしな」みたいな気持ちで横着していた
詳細な実装方針とか、言語としての仕様とか、いろいろな作業フェーズで必要な情報は変わってくると思います。 それでいうと、今回の発端となったフェーズでは
今から私たちが作ろうとする機能は、どんなデータを扱うのか
といった、より概念レベルでの、なんというか 身に沁みやすいもの で共有できるといいのだろうなと考えました。
TypeScript の型定義記法を選択した理由
特に深い意図はなくて、単純に「周りにそれを理解できる人が多かったから」です。
元々のきっかけとなった話し相手がフロントエンジニアだったということもあり
👳♀️ 「そういえば僕たちは TypeScript を使っています」 👤 「はい」 👳♀️ 「↓ こうじゃなくて……」 authors: t.string :name, null: false t.string :pen_name 👳♀️ 「↓ これならどうよ」 type Author = { name: string penName: string | null } 👤 「わかりやす! 特に `string | null` あたり」 👳♀️ 「なるほど。僕もそう思っていました」 👤 「せやったか」
TypeScript 風で良さそうだな? という気持ちになってきました。
また、デザイナーやPdM も、情報設計を TypeScript 風に記述していたことが判明しました。
新機能追加や改修のための概念データモデルを作成する際にも、既存のテーブル構成に対して積み重ねているため、この時点で既に TypeScript 風になっていると楽してもらえそうだなと考えました。
つまり
👳♀️ 「みんな TypeScript いけるじゃん! これにしよ!!」
まとめ
(論理)データモデルの共通言語として TypeScript は結構書き心地が良いなと感じました。
気合いが入っている時は図でしっかり書いた方が視覚的にモチベーションが高まりやすいこともあるので、ある程度いい感じに選んでいければと考えています。
今回の試みはまだ試行回数が少ないので何とも言えませんが、これをきっかけとしていい感じになっていけば嬉しい。嬉しい。
*1:"ユーザーストーリーをどのように実現するのか、デザイナーおよびエンジニアと仕様を検討します。概念データモデルの作成や、ワイヤの作成など、作るために必要な仕様の具体化を行います。" https://tech.smarthr.jp/entry/2020/01/23/141628