今回は個別ワークとして、人数少な目ですがデータベースのテーブル設計を進めます。
参加者は、FORTE、モウフカブール(大澤)、もっとです。
まずは、テーブルの一覧として必要なものを列挙します。親ともいえるものですね。
- サークル
- 頒布物
- イベント
- タグ
これをもとに、テーブル設計を進めていきます。最初に、スプレッドシートに枠を作ります。日本語での説明、カラム名、型、主キーになるものを決めるフラグ、Null許可のフラグを設定します。
具体的には、シートを見たほうが早いでしょう。議論の経緯は別途記載しますが、できあがったサークルテーブルは次の図のようになります。
idというカラム名があり、データベースのカラム名(インデックスとして)idがあります。その型はText型です。また、サークルを一意に選択する他の主キーになるものですがから、主キーのフラグが立ちます。当然、Null不可(未記入は不可)です。
一つ具体的に書いてみると、要件がはっきりしますね。
過去(7月2日)に整理した同人誌テーブルから必要な要素を持ってきます。
抜け漏れを防ぐために、拾ったものは枠をつける形でチェックしながら進めます。
ところで、現時点ではMVP(Minimum Viable Product)を作るにあたって必要なものだけにするのか、今後追加する可能性があるのはあらかじめ手いれておくのかという議論が生まれました。
一旦は、ページにあるものだけとすることで進めることにします。追加は面倒といえば面倒ですが、複雑になり設計が遅れてしまうことはMVPの目指すところではありません。
そして出来上がったのが、先のテーブルです。
サークル名は必須なので、Null不可とします。サークル紹介文はdescriptionという名前にして、Null可です。サークル紹介文を書かない人はまずいませんが、記入がないからといって、実装上困るわけではありませんからNull可です。
サークル主は、Auth関係でロール(役割)とともに使うものです。編集権限の設定も絡むので、あとにします。CirlcleMembersみたいなテーブルがあって、Roleとともに扱うのかなー、という話をして、一旦保留です。
サークル主に紐づいた情報として、ログインルートをTwitterだけにするというのもシンプルでよいですね。今は案として出しておき、今後決定していきます。
命名規則についての話が出てきます。カラム名をどうつけるのか、単数形なのか複数形なのか、大文字始まりなのか全小文字なのか、キャメルケースとするのか、などのお作法についてです。
Ruby on Railsでは、複数形を使うことが多く、型がある言語では単数形を使うことが多い等のもやっとしたお作法があるようです。
もちろんあとから任意に変えることはできますし、Hasuraに載せるときにHasura推奨の形に変換するとして、一旦は、小文字、スネークケース、複数形として進めます。
また、私はここで初めてキャメルケースという言葉を知りました。キャメルとは動物のラクダのことです。2単語をつなぐとき、単純につなぐと意味が取りづらくなります。hoge parameterという単語を繋いで変数名などを作るとき、単純につないでは意味が取りづらくなります。区切り方次第では誤解を生じさせることがあるかもしれません。そんな時、hogeParameterと書くとどうでしょう?単語の繋がりがわかりやすくなりますよね。そして、真ん中に大文字が入るので、ラクダのこぶに見立てて、キャメルケースと呼びます。類似の表記として、スネークケースもあります。hoge_parameterと書くのがスネークケースです。
こういうお作法についても知ることができるのはモブの利点ですね。
つぎは、サークルに紐づくURLです。これは、サークルに紐づく情報ではありますが、別テーブルとして追加します。最初に4つといったテーブルが増えることになりますが、設計の結果ですからOKです。
サークルリンクは、サークルのTwitterやBOOTHなどの販売サイトなどが格納される想定です。
サークルとの紐づけのためのidがあります。
TwitterやBOOTHなどいくつかのURLが存在しますが、リンク名が必要かどうか、表示順序が必要か、という議論が出ます。
デザインとして、順番決め打ち((Twitter,Facebook,BOOTHと決め打ちにするのか)、並べ替えを許容するのかを考える必要があります。order_numを作って、表示順をユーザーに決めてもらえるようにし、リンク種別を任意にするということも可能といえば可能です。
しかし今回は、デザイン的にも、テーブル設計的にも相当面倒になるので、順序・デザイン決め打ちで、アイコンのみ表示とします。
表示名(XXサークル公式、公式Blog等)は表示できないという形になります。若干自由度は下がりますが、コントロール、設計はしやすくなります。
入力ページの作成も楽になります。また、同じ種別の複数登録もなしです。Twitterアイコンが2個並ぶとかはやりたくないので、不許可です。サークルIDとリンク種別でユニークにできます。
入力ページと表示ページのイメージは図のようになります。シンプルですね。(アイコンや文字のデザインは適当です。本番ではもっとスマートになるはず)
たいていのサークルは十分なのですが、本人IDとサークルIDを分けている場合などはちょっと困る例が出てくる可能性がありますね。親方Project、たぬてっく、モウフカブールなど、関係者にエッジケースが多いのはきっと気のせいです。
idとリンク種別でユニークのフラグを立てておきます。
URL、各SNSについてはこれで完了です。
更に続いて、頒布物のテーブル設計です。
頒布物とは?article?item? cicleitems?アイテムという単語が汎用的過ぎるので、circle_itemsとしてサークルの持ち物であるという印象付けをします。
頒布物のふりがなはいる?に対しては、今は使わないので不要じゃないですかね?また今のUIには存在しないという意見もありつつ考えます。
将来的には、検索や並び替えのために必要そうです。技術書典にはふりがなあり、BOOTH、技書博はなしです。
基本的には、サークルの並びは発行順だと思われますから、優先度が高いわけではありません。ないよりあったほうがいいのは間違いないですが、それを言い出すときりがないので悩ましいところです。初期には間違いなく並び替えは不可、できたとしてピン止めするとかといった状況です。
ふりがなを作ると、サークル側の入力も大変になります。
このようなことをいろいろ考えて、あとで必須になるなら今作っておきましょうということになりました。
スマホサイトでは、カタカナ打つのが面倒なのでひらがなで入力させた方が親切ですが、基本PCサイトなのでどっちでもよさそう、かつ、変換もできるので、カタカナを想定したフィールドをつくっておくこととしました。
頒布物の中でもボリュームが大きいのがタグとジャンルです。次はこの部分について設計します。
まず、タグとジャンルの表示上の扱いについて整理します。タグとジャンルは似たようなものですが、ジャンルは階層になっていて検索性を上げるものです。タグは並列の概念です。
MVP的にはなくてもよいのですが、横断的に探すという機能がギポタルの目標とするものなので、将来的には必須機能です。 これをあとで追加するのはかなり手間なので、必須なものであれば現時点で追加することにします。
ジャンル表示は、テーブルとして入れます(今回使わないかもしれませんが…)。
また、後々Not-Null制約となるカラムは入力時点で揃っていないと後で整合性を取るのが厳しくなるため、現時点で追加することにします。
更にジャンルはテキストではなく、別にあるテーブルからの番号をIntで引いてくることにします。
BOOTHやとらのあなのURLを格納しておき、それがある場合には頒布先のアイコンを表示する形です。
あとで商業誌も載せられるようにしたほうが良いということが分かったため、amazon_urlも追加しています。
販売サイトというテーブルを作るということも考えられますが、tora_URLやbooth_URLという形で生の値として持つことを考えます。技術書典URLはどうなるか?という点については、常設URLができたらそれでも良いが、とりあえずは技術書典9限定のURLにするというアイディアが出て、今回はそれを採用しています。
手打ちするときにテーブル一緒だった方がやりやすくない?という想定も含まれます。
リリースを技術書典当日としましたが、入力したりする時間を誰も想定してないといいうダメ運用です。
また、技術書典9限定で、tbf9_urlというURLタグを作っておきます。これをcircleのテーブル内に暫定的に入れておき、サークルトップページにダイレクトに飛べるようにします。MVPが終われば消えるという運用にします。
スプレッドシートに手打ちし、CSVで書き出し、GraphQLに食わせる形で流し込むのでしょうか?
元の項目も、頭から要不要を判断していきます。基本的にはNull許可となります。
-
ページ数? 要る。UIには表示しなくても、登録流し込みを作る場合には必要。
-
電子or物理 不要。
-
本の値段 必要 配布サイトによって価格が違う場合は?標準適な価格を入れる。
-
アクセス数 いらない
-
リンク先 個別の紹介ページとかを想定。技術書典とかBOOTHに飛べれば十分だし、description内で書いてほしい。
-
初出イベント 必要。フロントのように入れ替わり流行り廃りの早い技術においては、たとえば3年前の内容は価値が下がっているという例があります。ですから発行時期は確認できる必要があります。また技術書典の記入欄にあるので、流し込みに必要という側面もあります。
-
もくじ 不要 テキストに書いてもらえれば良い
-
画像 枚数を決める必要あり。技術書典は4枚、BOOTHは枚数多いですね。画像テーブルは必要だけど、扱いが難しい。また、登録できるようにしなければいけません。
画像を削除するときにどの画像が残っているかが不明です。画像テーブルが削除されたときのコールバックでストレージを削除するといった動作をさせるなら、テーブルがあったほうが便利です。
画像1.2.3.4があったとき2を消したときに詰めるのかどうするのかという細かい話も出てきます。
シンプルに考えると、画像URLを配列として持つといったことが可能です。また、MVPの段階では1枚のみとし、URLを持つだけとします。
- 配布数 要らない
- 閲覧数、いいねの数 要らない
- 対象読者 descriptionに
- 無料版、お試し版 descriptionに
- タグ タギングテーブルを作って対応
- 解説 本の解説。descriptionに。
- 頒布委託先 おそらくイベントでの委託先。不要。
- 出版日付 奥付にある初版の日付を想定。技術書においていつ出版されたのかは結構重要なのです。フロント、Reactなどの知識で3年前の本と1年前の本は結構違うので重要です。
- シリーズ 不要
- 出版社 印刷所を想定。不要
- 商業/同人フラグ 不要?問い合わせベースで追加する?欲しいと言われたら追加する。そして、商業誌を載せるなら、AmazonのURLが欲しくなるので、URLテーブルにAmazonを追加します。
- 版の違い 明確に扱うならDB的にはあったほうが嬉しいが、入力がめんどくさいです。また、ギポタルのユーザーとしては、旧版は不要なので、最新版
- 在庫状況 不要
- 対象レベル 不要。descriptionへ。
- 発行イベント 初出イベントと同じ。
- CircleID 本は複数のサークルに所属することはないので、一意に。URLも、CircleID/items/になる予定ですので、複数サークルに所属することは想定しません。
結果として、モブで列挙した構成要素のうち、およそ1/3くらいが実テーブルのカラムとして採用されました。
普段仕事ってどう進めてますか?暗黙知、経験だけで転がしていて、世の中の標準から比較して雑すぎるなんてことがないか?という確認をしました。
OJTで学ぶとはいえ、会社によってやり方は違うし、決して体系だって教えてくれるわけではありません。
自分のやり方があまりにも雑/細かすぎたりしないことを確認できるのも、モブワークならではかもしれません
次は、タグのテーブルを作ります。タグそのものを定義するためのテーブルとして、tagというテーブルを作ります。ここには、タグ名のみが列挙されています。
次に、頒布物に紐づくタグテーブルを、頒布物タグ taggingとしてテーブルを作ります。付ける先の頒布物IDと、付けるタグが引けるようにします。
同様に、ジャンルのテーブルも作ります。
親子関係を書きたいところですが、循環参照になりえるのはデータベースのアンチパターンです。2階層や3階層に限定してギリOKなレベルもあり得ますが・・・
メリットよりデメリットが勝る事もあり、親子関係はMVPからは外します。
トップページがどう並ぶのか、という疑問が出ますが、少なくとも初期はサークルページは並びません。トップページには本のみが並びます。出版日付が新しい順になる予定です。サークルはサークル画像がないので並べづらいですし、あくまで本が主体のサービスですから、それでよいのではないでしょうか。
ジャンルの並び順は、登録数が多い順などに、運営で恣意的に決めることになると思われます。並ぶ順がないのと、頒布物を入り口にするという当初思想と矛盾がありません。
最終的に、本のページはこんな感じになりそう、ということで、Figmaのスクリーンショットを作ってくれました。素敵!
恒例のFun done learnをやっておしまいです。なんだかんだで2時間余りかかりました。お疲れさまでした。