Slide 1

Slide 1 text

2023.09.27 「生活感のある」アーキテクチャ

Slide 2

Slide 2 text

(C)PharmaX Inc. 2023 All Rights Reserve 2 自己紹介 ・Cai Jiaxin(サイ カシン) ・基本はwebエンジニア ・PharmaXには今年の7月にジョイン

Slide 3

Slide 3 text

(C)PharmaX Inc. 2023 All Rights Reserve 3 目次 ①:PharmaXのプロダクトの簡単な説明 ②:背景と課題について ③:アーキテクチャについて

Slide 4

Slide 4 text

4 (C)PharmaX Inc. 2023 All Rights Reserve PharmaXのプロダクトの簡単な説明

Slide 5

Slide 5 text

(C)PharmaX Inc. 2023 All Rights Reserve 5 「薬局」は医療体験の中でも身近な存在 日用品から処方薬まで。「薬局」は皆さまの日常の近くに存在している ドラックストア 調剤薬局 実現したいこと

Slide 6

Slide 6 text

(C)PharmaX Inc. 2023 All Rights Reserve 6 医療体験を横断する2つの事業領域 PharmaXの 事業 YOJO事業 (OTC医薬品・健康食品) 未病・予防 治療 薬局DX事業 (医療用医薬品) オンライン薬局サービスを展開している

Slide 7

Slide 7 text

(C)PharmaX Inc. 2023 All Rights Reserve 7 LINEから利用できるバーチャルな薬局 最短 即日 ※ お薬をもっと手軽に、もっと安心して受け取れる「 YOJO薬局」 お薬はお家までお届け LINEで薬剤師にいつでも相談 好きなときにお薬の説明 ※東京23区内のみ PharmaXの プロダクト

Slide 8

Slide 8 text

(C)PharmaX Inc. 2023 All Rights Reserve 8 ソフトウェアに閉じないプロダクト開発 PharmaXの プロダクト開発 独自の薬局オペレーションシステムを構築し、最適化されたオンライン薬局を実現 × 自社薬局をプロトタイプラボ化 ソフトウェア オペレーション リモート 薬剤師組織 薬局業務を効率化す るオペレーションシス テム(薬局OS) 質の高い患者さま対応 のためのオンライン特 化組織 対人業務の質を高め るための対物業務効 率化 「ソフトウェア×オペレーション×薬剤師組織」を プロダクトとして開発

Slide 9

Slide 9 text

(C)PharmaX Inc. 2023 All Rights Reserve 9 LINE登録者数〜ローンチ初期〜 直 近 は 省 略

Slide 10

Slide 10 text

10 (C)PharmaX Inc. 2023 All Rights Reserve プロダクト背景&課題

Slide 11

Slide 11 text

(C)PharmaX Inc. 2023 All Rights Reserve 11 ジョイン当時のアーキテクチャへの課題 ・背景:YOJO事業でこれまで専任のフロントエンドアーキテクチャがいませんでした。 ・少人数&スピード重視の開発スタイルでやってきたが、プロダクトの更なる発展を考えて、リファクタリン グをロードマップに入れます。 ↓ ・そこで私がPharmaXにジョインし、事業側の要件開発を担当しつつ、リファクタリングにも手をつけてい きます。 ・(スタードアップによくある話ではあるが)そしてすぐ Unit Testすらないことに気づく。 ・「Unit Testなしでやるリファクタリングただの書き直し」という私の偏見の元で、プロジェクトを書き直しつ つ、テストも書いていく。 ・そしてさらにアーキテクチャがなくコンポーネント設計もカオスで、 Unit Testが書けないことに気づきま した。 ・また、ディレクトリ構成も管理されず影響範囲が見えてなく、リファクタリングする際は常に範囲不明なデ グレのリスクが伴う。 ・「そうだ、リファクタリングだけではなくリアーキテクチャもしよう」 →ここからスタート

Slide 12

Slide 12 text

12 (C)PharmaX Inc. 2023 All Rights Reserve アーキテクチャ

Slide 13

Slide 13 text

(C)PharmaX Inc. 2023 All Rights Reserve 13 コンポーネント課題①:早まった抽象化 ・プロダクトは成長するものであり、その初期段階では特に変化が激しい。 ・なので、いきなりやりすぎた抽象化を行うと逆にプロダクトの足枷になることもありま す。 ・抽象化はただの因数分解ではない。 ・また、抽象化(共通化)は「目的」ではなく「手段」であるため、「共通化できるからやる」 のではなく、「すべきからやる」というものです。

Slide 14

Slide 14 text

(C)PharmaX Inc. 2023 All Rights Reserve 14 早まった抽象化の一例 当時はこのようなコードが多く存在していた。 ・共通処理は最初の極一部しかなく、要件追加するたび に、呼び出し元を判別する分岐条件とその分岐にしか使 われないコードが「共通コンポーネント」に残り、増え続け る。 ・このコンポーネントからは呼び出し元の仕様を把握しよ うとしても、断片的なものしかない一方、このコンポーネン ト自身の役割も曖昧になっていく。 ・そしてテストを書こうとしても呼び出し元の仕様によって 挙動が大きく違うので Unitとして綺麗に書けない。

Slide 15

Slide 15 text

(C)PharmaX Inc. 2023 All Rights Reserve 15 改善 ・共通コンポーネントの中から呼び出し元を判別するコードを洗い出し、各呼び出し元に書き戻す。 ・本当に共通している処理だけ、 PdMに仕様を確認してから、再び共通化するかを検討する。 ・code reviewの際にAHAの観点を導入 ・※ AHA(Avoid Hasty Abstractions)  ・検索してみると日本語の資料は少ないが、実は DRY原則とよく並んで話す原則の一つでもあ る。  ・内容を要約すると、「誤った抽象化するくらいなら重複させたほうが遥かに安い」。

Slide 16

Slide 16 text

(C)PharmaX Inc. 2023 All Rights Reserve 16 ※この例はhookだけですがコンポーネント も絡んだ処理と考えてください。 ・共通コンポーネントから「呼び出し元による 条件分岐処理」を取り除くことに成功。 ・各コンポーネント特有の処理はちゃんと各 自の中に閉じ込んでいる。 改善後

Slide 17

Slide 17 text

(C)PharmaX Inc. 2023 All Rights Reserve 17 コンポーネント課題①:テストしづらいコンポーネント

Slide 18

Slide 18 text

(C)PharmaX Inc. 2023 All Rights Reserve 18 Unit Testを書こうとすると ・「外部から値がもらえない場合」のケースは書けても、 「外部から値がもらえる場合」のケースが書けない。 ・もらえる場合且つ値によってさらに分岐があれば、値は テストケース内で制御できないため、それらも書けなくな る。

Slide 19

Slide 19 text

(C)PharmaX Inc. 2023 All Rights Reserve 19 改善 ・外部依存処理はコンポーネント設計の段階から分けるようにする。 ・「こう書くと画面はこうなる」だけではなく、「こう書くとテストはこう書けば いい/こう書かねばならない」も頭の隅におきながら実装するように。 ・テストを意識したコードの分け方を社内のモブプロ会で共有  ・「こういう処理のテストはこう書く」というプラクティスを残す

Slide 20

Slide 20 text

(C)PharmaX Inc. 2023 All Rights Reserve 20 改善後 ・さっきの例の言うと ・外部依存の部分をhookとし て切り離し ・切り離したhookを丸ごと mock化する ・するとテストケース内では、 コンポーネント自身の関心事 について書くことができる。

Slide 21

Slide 21 text

(C)PharmaX Inc. 2023 All Rights Reserve 21 ディレクトリ課題:影響範囲がわからない ・種類で分けたり、機能で分けたり、ディレクトリ構成に一貫とした ルールがなく、ディレクトリ構成から影響範囲の情報が読み取れな い。 ・「ここを書き直したらどこまで影響するか?」はパッと見積もりがで きず、スプリントプランニングで話しづらい。 ・ファイルを作る時はどこに置くか迷う

Slide 22

Slide 22 text

(C)PharmaX Inc. 2023 All Rights Reserve 22 改善 ・ディレクトリ構造にスコープの意味を持たせる ・components/ディレクトリにもpages/の構造を用意する ・画面でいうと「特定のpageしか使わないもの」と「複数ページで使われるもの」を 分ける ・機能でいうと「特定の機能しか使わないもの」と「複数機能で使われるもの」を分 ける ・ルールはできるだけシンプルに、作成時に迷わせないこと

Slide 23

Slide 23 text

(C)PharmaX Inc. 2023 All Rights Reserve 23 改善後 変更後の一部抜粋(例 …… / pages  ┣ pageA  ┣ pageA  ┣ …… /components  ┣ pageA    ┣ featureA    ┣ ……      ┣ featureB        ┣ ……  ┣ pageB    ┣ ButtonB.tsx  ┣ shared   ┣ ButtonA.tsx   ┣ user   ┣ information  ┣ Header.tsx   ┣ adminUser   ┣ information ┣ Header.tsx …… ・components/の配下には、pages/のようにpageA/やpageB/があ る ・featureA/がcomponents/pageA/の配下に置かれることは下記の 意味を持つ  ・featureAという機能pageAでしか使われていない  ・featureAの修正はpageAまでしか影響しない ・featureB/がfeatureA/の配下に置かれることは下記の意味を持つ  ・featureBという機能featureAでしか使われていない  ・featureBの修正はfeatureAまでしか影響しない ・ButtonA.tsxやuser/、adminUser/がcomponents/sharedの直下 に配置されていることは下記の意味を持つ  ・これらのコンポーネントは複数箇所に使われるので、手を付ける時は 配慮する ・ファイルを作成時はこのスコープのことを考えれば置き場所は決まる

Slide 24

Slide 24 text

(C)PharmaX Inc. 2023 All Rights Reserve 24 今は全体的にどんな感じになった? ・依存関係が混乱なコンポーネントを紐解いて、コードからの仕様把握が容易になり、プロダクトの 機能追加・改修サイクル速くなりました! ・Unit Testを書くことができて、カバレッジが 0% → 50%超えになりました!!! ・ディレクトリ構成「これ!」といったルールが言語化され、チーム内での共有ができました。

Slide 25

Slide 25 text

(C)PharmaX Inc. 2023 All Rights Reserve 25 まだ完璧とは言えないが、 本来の「放置された空き家」と比べて、 一応「誰かがそこに住んでなんかやってる」 という生活感を出しているようになりましたw ご清聴ありがとうございました! 最後