BCD Design の Common を徹底解説

## はじめに

ドワンゴでニコニコ生放送のWebフロントエンジニアをやっています、 @misuken です。

今回は [BCD Design](https://qiita.com/misuken/items/19f9f603ab165e228fe1) の共通の関心事である Common(Common Domain) に関して徹底解説していきます。

## BCD Design とは

2020年3月に発表した [BCD Design によるコンポーネントの分類](https://qiita.com/misuken/items/19f9f603ab165e228fe1) 

> ## 概念軸による分類
>
> BCD Design はコンポーネント名に使用される単語の意味や性質を相対的に利用することで、 コンポーネントを Base Case Domain の3つの概念へ法則的に配置し、体系的に管理できるようにする分類手法です。

元々は AtomicDesign でモヤモヤする問題を解決するコンポーネント分類手法として考案されたものでしたが、 BCD Design のスキルは色々な分野で幅広く通用することもわかってきたので、Webフロントやコンポーネントに関係のない分野の方も、元記事やこの内容を参考に、今まで抱えていたモヤモヤをスッキリしていただけると幸いです。

## Common の解明

[以前発表した BCD Design の記事](https://qiita.com/misuken/items/19f9f603ab165e228fe1) では、共通の関心事である Common に関してあまり詳しい説明が書いてありませんでした。

あのときはまだ完全な確信に至れていない部分があり、軽く触れるにとどまっていたのですが、あれからもずっと BCD Design の本質と向き合い続けた結果、明確な答えに辿り着いたので発表したいと思います。

## Common の役割

関心事である Domain には、そのサービスに強く依存する関心の領域と、大体いつでもどこでも共通で存在する関心の領域(単語自体が持つ性質とも言える)の二つが存在しています。

例えば、 Tag や Category といった関心は、どのサービスでもほとんど差のない共通の関心であり、サービス独自の関心の領域が無いと言えることもある一方、 Member Site User などは、サービス独自の関心の領域もありつつ、どのサービス間でもほぼ共通の関心の領域を持っています。

このような場合は次のような構成で捉えることができます。

![](https://storage.googleapis.com/zenn-user-upload/79fbe2ad6e94211b97dbf8c8.png)
※ 以前 BCD Design　を発表したときと少し移動したものもあります

Common の部分を一般的な関心の領域、Domain の部分をサービス独自の関心の領域として見たとき、それぞれに Member Site User があるものの、その境界の存在には大きな価値があります。

## Common の真髄

例えば、あなたがサービスを作った後、また新しいサービスを作ることを想像してみてください。
前のサービスと差の生じる部分というのは**サービス独自の関心領域**であるため、 Domain の領域だけ作り変えれば良いということを示しています。

他にも MemberCategory と UserCategory を持つサービスがあった場合、その二つの Category はサービスに強い依存を持つと思われますが、二つの Category に精通する Category としての性質、つまり Category のみの関心の領域は、他のサービスでも十分利用可能な内容になっているはずです。

このように捉えることで、 Domain ではサービス独自の関心が煮詰まった高凝集な領域が手に入るので、大規模なサービスでは特に Common (共通の関心という意味)という分類を用意するメリットが大きくなります。

## 現実的な話

実際にはそこまでキレイに Common からサービス独自の関心を取り除くことは難しいかもしれません。
しかし、 Domain をそのサービスで特に強い関心のある単語のみの構成にすることには、別の側面からも大きな意味があります。

サービスを開発する際のほとんどは、そのサービスの特に強い関心に対して開発を行っていくことが多いでしょう。
その際、強い関心のあるディレクトリが大量のディレクトリに埋もれていると、探しにくく、ちゃんと管理できているのか不安になったりします。

そこで、サービスの特に強い関心のみを Domain に並べます。
すると、そのサービスが主にどのような関心で構築されているのかが明確になり、そこに重要な関心が凝集されていて辿る順序もキレイになるため、新しいメンバーなどにも優しい環境になります。(把握や学習のコストも低減されます)

## Common は必須ではない

もちろん、必ず Common が必要なわけではありません。
Domain のディレクトリに全部突っ込んでも問題ないという運用もあるでしょう。

関心のサービス依存度の高低や、一般的な関心との境界がある場合、 Category や Error や Tag といった細かい関心と分けたい場合など、そのサービスでこうあってほしい(開発がしやすい)と思う Domain ディレクトリ像を決めて、残りは Common へ移動という形がスムーズでしょう。

## 依存関係の注意点

Domain と Common の間で一点だけ注意しておく必要があるのは、 Domain から Common を参照することは良いのですが、 Common から Domain を参照することは避ける必要があります。

参照方向が単一になっていないと、循環参照や複雑さの原因になるためです。

もし循環参照になりそうな場合は、必ず Common 側から依存したい Domain の一部(そこは一般的な関心に近いはずです)を Common のほうに分離しましょう。

つまり、 User の例で言うと、 Domain にあった User の中から、 一般的な関心に近い部分を切り出し、 Common 側に書くようにすると、 Domain に残ったサービス依存度の強い User からも、 Common の User からも参照できる位置関係になるので、 Common 内では FollowerUser という表現が可能になります。

このように、 Domain と Common という違う特性を持った関心の領域が二段構えにあることで、どれだけ関心が増えたとしても、常に複雑さを最小にでき、適切に管理可能な構成を手に入れられます。

## まとめ

- 一般的な関心や複数の Domain で共通する関心の領域は Common が向いています
- Domain 内ではサービス依存の高い関心を中心に構成するとサービス自体を把握しやすくなります
- 関心の中でもサービス依存度の高い部分と汎用的な部分をしっかりと境界付けられます
  - 通常は BaseXxx のような存在を作りたくなるシーンでも Common が使える可能性が高いです
  - **Domain と Common に同じ名前のディレクトリがあっても問題ありません**
  - 要は同じ関心の対象であっても汎用的にしたい部分とそうでない部分があるからです
  - 依存関係の循環には気を付けましょう
- Domain と Common の境界がうまく分けられない場合は、無理せず Domain のみで運用しましょう
  - 確実に移動可能なものは Common に移動するなど少しずつでも問題ありません

Common を使い回して Domain に集中できる環境が整うと非常に便利です。
ぜひ、Domain にメインの関心事を集中させて、薄くて高凝集の理想的な形を手に入れてください。

## おまけ

最近社内LTにて、「BCD Design 単語表」というものを発表しました。
これはニコニコ生放送におけるコンポーネント名の単語ほぼ全てを分解し、 Base Case Common Domain に分類したもので、非常に興味深いものになっているので、そう遠くないうちに公開できればと思っています。

また、この BCD Design の流れから、関心の対象に様々な形容詞が掛け合わさるなど、複雑な文脈の違いを要求される場面でも、関心が分散せず、理解しやすく、法則的にスケールし続けるディレクトリ構成も確立されたので、そちらも公開予定です。