Slide 1

Slide 1 text

Full TypeScriptで新規プロダクトを 立ち上げた際に実践した設計と反省 株式会社カケハシ 小室 雅春

Slide 2

Slide 2 text

小室雅春 (コムロ マサハル) ● WEBソフトウェアエンジニア ● 経歴 ○ 某新聞社(2016 ~ 2022/05) ○ 株式会社カケハシ(2021/06~) ● TypeScript, SPA, Express, AWS CDK ● 患者さんの服薬をサポートする新規プロダクトの立 上げを担当 自己紹介 @_hedrall hedrall https://blog.hedrall.work

Slide 3

Slide 3 text

1. 背景 2. 技術選定と設計 ● 言語 ● レポ管理 ● アーキテクチャー ● フロントエンド ● バックエンド ● テスト 3. まとめ アジェンダ

Slide 4

Slide 4 text

カケハシとは? https://www.kakehashi.life/

Slide 5

Slide 5 text

● 21年6月入社した当時、新規プロダクトの立上げの話があった ○ => 患者さんの服薬を薬局がサポートするための業務システム ● 明確なDeadLineはないが、概ね3, 4ヶ月くらいでMVP版をリリースした い ○ その後、正式リリース => スケールしていく前提 ● リソースは、私 + 兼業メンバー2, 3名のサポート 新規プロダクト開発の背景 スピーディにプロダクトを立ち上げて、 PMFに向けたサイクルを回したい!

Slide 6

Slide 6 text

● 薬局がWindows Desc/Tabで利用するJamstackな業務WEBアプリ ○ SPAアプリ (SSR不要) ● 患者の個人情報が含まれる ○ (クライアント証明書による制限が必要) ● 薬局が患者をサポートした履歴など、書き込みが必要 ● (ログインセッションは既存の別システムと共有化する(SSO)) ● 将来的に実装されうる機能が特定しきれていない ○ 既存にない業務、今までになかったプロダクト 構築するシステムの特性

Slide 7

Slide 7 text

● 開発速度 ○ 軽量な技術スタックでTryErrorのサイクルを短縮 ○ 効果の高いツールは、新興ツールでも利用する ■ 捨てられる事が前提 ● シンプルさ ○ 兼業のメンバーや、今後加わるメンバーが理解しやすい ● 属人化しない ○ 一般的な技術 or 可換な技術 or 使いやすい技術 ○ 整理されつつ、複雑化しないアーキテクチャー 技術選定・設計方針

Slide 8

Slide 8 text

2. 技術選定・設計

Slide 9

Slide 9 text

● WEBフロントエンドを開発する以上必ず使う ● 全部TypeScriptで無理なく開発可能 ○ AWS CDK (2019 ~) により、IaC もTypeScriptで簡単に ● 立ち上がり期、フルスタックなメンバーの多い環境 ○ (周辺エコシステムを含む) コンテキストスイッチの最小化 ■ 他の言語を導入する場合はコストを考慮する必要がある ● (バックエンドに重い集計などはない) ● TSの良さ ○ 型によるドキュメンテーション効果の向上 ■ 構造的部分型による人に優しい型 (情報量・可読性) 2.1 言語 => Full TypeScript!!

Slide 10

Slide 10 text

● 最近のエディターは複数のtsconfig.jsonに対応 ● フロント・バックが一体のシステム ● 一部コードを共有したい ○ Domain Model, DTO, コアロジック, 共通関数 ○ FullTS環境では大きな利点 ● cons ○ コード共有は循環参照に気をつける ○ precommit hook, eslintの設定などは工夫する 2.2 レポジトリ管理 => モノレポ Github Repository frontend backend infra package.json tsconfig.json ・・・ package.json tsconfig.json common

Slide 11

Slide 11 text

● クリーンアーキテクチャー(CA)、DDDの手法を漸進的に導入する ● CA ○ ロジックの置き場を整理 ○ コンポーネントを差し替えできるようにしておく ■ β版からプロダクトのスケールの準備 ● DDD ○ ドメインモデルを整備する ■ ビジネス要件をコードに反映しやすくする ■ ドキュメンテーションとしての価値 ● 週2回 (+ 都度)、PdMと要件を整理 2.3 アーキテクチャー

Slide 12

Slide 12 text

実装にあたって参考にする物 出典: https://github.com/esakik/clean-architecture-python Clean Architecture 図22-2 典型的な例

Slide 13

Slide 13 text

バックエンド(API) フロントエンド(SPA) Controller UseCase Repository DB MySQL HTTP Request

Slide 14

Slide 14 text

バックエンド(API) フロントエンド(SPA) Controller UseCase Repository DB HTTP Request MySQL データモデルをどうするか?

Slide 15

Slide 15 text

バックエンド(API) フロントエンド(SPA) Controller UseCase Repository DB MySQL HTTP Request Domain Model DAO DTO TypeORM (DynamoDBなら省略可能? ) ドメインモデルの改修サイクルで APIに破壊的な変更が入る事があ る 変換 変換

Slide 16

Slide 16 text

Domain Model DAO TypeORM (DynamoDBなら省略可能? ) ドメインモデルの改修サイクルで APIに破壊的な変更が入る事があ る バックエンド(API) フロントエンド(SPA) Controller UseCase Repository DB MySQL HTTP Request リリース時の ダウンタイムを 許容するか? 変換 変換 DTO

Slide 17

Slide 17 text

バックエンド(API) フロントエンド(SPA) Controller UseCase Repository DB MySQL 変換 UIComponent (View) Repository Hooks 変換 変換 Domain Model DAO DTO API Request

Slide 18

Slide 18 text

● フレームワーク(Next.js, Angularなど)に依存したくない ○ 素早くプロダクトを立ち上げる為に身軽でいたい ○ たち上がりは早い? ■ 当初知識がなくても利用しやすいが、将来的な学習コストが高い ○ 不必要なツールに依存する ■ ビルドに時間がかかる ■ TryErrorサイクルに影響 ■ 手を加えるのが大変 ● 判断のポイント ○ toCかtoBかで非機能要件が大きく異なる ■ SSR(SEO)、パフォーマンス、負荷対策 ● 大まかなトレンドは The State of JS などを参考 2.4 フロントエンド 前提

Slide 19

Slide 19 text

● React ○ 内部が全てJS ○ TSによるドキュメンテーション効果が高い => 属人化しない ○ ビルド開発環境が選びやすい => DX改善がしやすい ● ビルド ○ esbuild <= Webpackの100倍早い !! ■ 軽量かつ可換 ■ 話題のesbuildをさっくりと調査してみた ○ ローカルは、expressとbrowsersyncでホスト ■ Advent Calender: esbuild + React(TS) で実現する超軽量な開発環境 ● パッケージ: pnpm <= npm よりも高速でエコ ● Inversify.js => DIコンテナ ○ APIクライアントをstabと差替し、standaloneで起動 2.4 フロントエンド React

Slide 20

Slide 20 text

● 開発速度の向上!ドキュメント作成! ● とはいえ、活用方法は十人十色 ● TSOAを採用 ○ CodeFirstでOpenAPIスペックを生成 ○ 更にOpenAPI-generatorでAPIクライアントを生成 ● => 手間なく、フロントとバックの整合性を担保 ● => ボイラープレート部分を自動生成 詳細な活用方法 ▼ Code Firstで疲弊しないOpenAPI活用方法 2.5 OpenAPIの活用 OpenAPI

Slide 21

Slide 21 text

バックエンド コントローラを記述 import express from 'express'; import { Controller , Get, OperationId , Body, Request, Route, Security } from 'tsoa'; @Route('user') export class UserController extends Controller { constructor (private service: IUserService) { super();} /** * ユーザ一覧取得 */ @Get('list') @Security(SECURITIES.COGNITO) @OperationId ('list-user' ) public async get( @Request() request: express.Request, @Body() params: InputDto ): Promise { const res = await this .service.list( request. user, apiDtoConverter(params) ); return apiDtoConverters.user.list.serviceToOutput (res); } } Controller 後続の処理 変換 HTTP Request

Slide 22

Slide 22 text

import express from 'express'; import { Controller , Get, OperationId , Body, Request, Route, Security } from 'tsoa'; @Route('user') export class UserController extends Controller { constructor (private service: IUserService) { super();} /** * ユーザ一覧取得 */ @Get('list') @Security(SECURITIES.COGNITO) @OperationId ('list-user' ) public async get( @Request () request: express.Request, @Body() params: InputDto ): Promise { const res = await this .service.list( request. user, apiDtoConverter(params) ); return apiDtoConverters.user.list.serviceToOutput (res); } } Controller 後続の処理 変換 バックエンド コントローラを記述 GET: /user/listへのリクエストを処理 HTTP Request

Slide 23

Slide 23 text

● schemaでのvalidationなど ● Auth Middlewareの差し込み Controller 後続の処理 生成 バックエンド OpenAPI Spec  ボイラープレート 生成 HTTP Request

Slide 24

Slide 24 text

Controller 後続の処理 バックエンド OpenAPI Spec  ボイラープレート フロントエンド(SPA) Component (View) Repository Controller (Presenter) 変換 API Client 生成 生成 生成 ● schemaでのvalidationなど ● Auth Middlewareの差し込み 型の効いた API Request ! DB HTTP Request

Slide 25

Slide 25 text

● Testing Trophyを念頭に ● 静的解析を頼る ● Unitを減らして、Unitに縛られない ● 統合テストはDBをモックしない ○ https://github.com/testjavascript/nodejs-integration-tests- best-practices ● Github Actions で実行 2.6 Testing 出典: https://twitter.com/kentcdodds/status/960723172591992832?lang=zh-Hant

Slide 26

Slide 26 text

● Goods ○ 機能全体のテストができるので、安心感が ある ○ 障害が発生した場合に、修正以降の動作 を保証できる ● Bads ○ テストデータの作成が大変 ■ JSONで記述するSeeds ■ APIによるMutationを利用 ○ テストケースが網羅できない場合がある ■ 細かな文言の違い ■ 局所的に複雑なロジック ■ => UnitTestで担保できないか? ● Jestの起動が遅い? ○ Jestのテストを高速実行する自作ツール 既 存のJestで書かれたテストを爆速実行するツール、uvu-jest を作りました 2.5 Testing 出典: https://twitter.com/kentcdodds/status/960723172591992832?lang=zh-Hant

Slide 27

Slide 27 text

● 新規プロダクトの構築に際して、軽量な開発環境を工夫することで、順調 に開発・リリースすることができた 🎉 ● 現在もより多くの薬剤師にご活用頂けるように、より加速してプロダクトを 成長中! ● 次プロダクトを立ち上げるときに事前によく検討するべき事項がわかった 😆 まとめ

Slide 28

Slide 28 text

エンジニア採用中 ● 医療分野にて社会的意義のある開発をしたい方 ● アプリケーション構築に興味がある方 ● フルスタックに開発をしたい方 ● データの利活用に興味がある方 まずはカジュアル面談をご利用下さい! 採用ページ

Slide 29

Slide 29 text

以上です! ありがとうございましたmm 採用ページ