Slide 1

Slide 1 text

密結合なバックエンドから TypeScript のコードを生成する

Slide 2

Slide 2 text

2 メイン - 2018 年新卒で freee 入社 - freee会計の開発 - 主にフロントエンド基盤 その他 - Dev Branding / Dev Relationship - freee Tech Night - freee 技術の日 - 全社イベント運営 - TSKaigi コアスタッフ SNS - X: @_kemuridama - GitHub: @kemuridama フリー株式会社 / エンジニア & DevRel kemuridama Ryo Ochiai

Slide 3

Slide 3 text

  だれもが⾃由に経営できる 統合型経営プラットフォーム。 だれもが⾃由に⾃然体で経営できる環境をつくるために、「統合型経営プラットフォーム」を開発‧提供します。 バックオフィス業務を統合することで、⾃動化と業務全体の効率化。さらに経営全体を可視化することで、 これまでにないスマートかつ最適なアクションまで実⾏できるプラットフォームへと進化させていきます。 また外部サービスとも連携したオープンプラットフォームとして、多様なビジネスニーズに対応。 ユーザーネットワークの中における相互取引の活性化も強化していきます。 プラットフォームの提供のみならず、スモールビジネスに携わる⼈の環境そのものを より良くしていく取り組みを⾏うことで、世の中の変化を促します。 Vision

Slide 4

Slide 4 text

  電⼦稟議 経費精算 債権債務 管理 ⼈事労務 電⼦契約 固定資産 請求管理 会計 ⼯数管理 販売管理 会計‧⼈事労務‧販売管理を核とした 統合型経営プラットフォーム

Slide 5

Slide 5 text

5 スモールビジネスの ⼈事管理市場において  売上⾦額シェアNo.1(3) スモールビジネス向けに統合型クラウド(1)ERPを提供 注: 1. クラウドサービス:ソフトウェアやハードウェアを所有することなく、ユーザーがインターネットを経由してITシステムにアクセスを行えるサービス 2. リードプラス「キーワードからひも解く業界分析シリーズ:クラウド会計ソフト編」(2022年8月) 3. 「freee人事労務」はITRが今年調査発行した「ITR MARKET VIEW:人事・給与・就業管理市場2022」の人事管理市場において、従業員100人未満および従業員100~300人未満の企業で売上金額シェアNo.1(2020年度)を獲得しています。 統合型クラウド会計ソフト 統合型クラウド⼈事労務ソフト その他サービス 2013年3⽉〜 請求書 経費精算 決算書 予実管理 ワークフロー 内部統制 勤怠管理 ⼊退社管理 給与計算 年末調整 マイナンバー 管理 2014年10⽉〜 2022年11⽉〜 ⽇本のクラウド 会計ソフト市場  シェアNo.1(2) 統合型クラウド販売管理ソフト 【国内初】 クラウド会計ソフトと ⼀体型で使える 販売管理サービス ⽀出管理 ⼈事労務 ⼯数管理‧労務費管理 社宅制度の導⼊ 申告書作成 ⾒積‧発注‧請求 法⼈⼿続き クレジットカード 開業⼿続き 電⼦契約

Slide 6

Slide 6 text

6 スモールビジネスの ⼈事管理市場において  売上⾦額シェアNo.1(3) スモールビジネス向けに統合型クラウド(1)ERPを提供 注: 1. クラウドサービス:ソフトウェアやハードウェアを所有することなく、ユーザーがインターネットを経由してITシステムにアクセスを行えるサービス 2. リードプラス「キーワードからひも解く業界分析シリーズ:クラウド会計ソフト編」(2022年8月) 3. 「freee人事労務」はITRが今年調査発行した「ITR MARKET VIEW:人事・給与・就業管理市場2022」の人事管理市場において、従業員100人未満および従業員100~300人未満の企業で売上金額シェアNo.1(2020年度)を獲得しています。 統合型クラウド会計ソフト 統合型クラウド⼈事労務ソフト その他サービス 2013年3⽉〜 請求書 経費精算 決算書 予実管理 ワークフロー 内部統制 勤怠管理 ⼊退社管理 給与計算 年末調整 マイナンバー 管理 2014年10⽉〜 2022年11⽉〜 ⽇本のクラウド 会計ソフト市場  シェアNo.1(2) 統合型クラウド販売管理ソフト 【国内初】 クラウド会計ソフトと ⼀体型で使える 販売管理サービス ⽀出管理 ⼈事労務 ⼯数管理‧労務費管理 社宅制度の導⼊ 申告書作成 ⾒積‧発注‧請求 法⼈⼿続き クレジットカード 開業⼿続き 電⼦契約

Slide 7

Slide 7 text

7 - 2013 年 3 月リリース - 2012 年度の確定申告の直後にリリース - すでにリリースから 13 年が経過 - 巨大なモノリス - freee 社内でも最も大きなコードベース - バックエンド: Ruby + Ruby on Rails - フロントエンド: TypeScript + React - 一部 erb + Backbone.js freee会計

Slide 8

Slide 8 text

バックエンドとフロントエンドは疎結 合であるべきですよね? でも、現実はどうですか?

Slide 9

Slide 9 text

9 ● バックエンドとフロントエンドで言語が異なる ○ 基本的にはバックエンドの変更にフロントエンドが引っ張られる 状態 ○ Ruby (Sorbet) と TypeScript の型をそれぞれ管理する必要がある ● 一般的な解決方法: OpenAPI Schema からのコード生成 ○ 取り組んでいるが、コードベースが大きすぎてなかなか進まない のが現状 ○ API 経由だけではなく erb に直接値を埋め込んでいる箇所が存在する freee会計における課題

Slide 10

Slide 10 text

10 ● バックエンドとフロントエンドで言語が異なる ○ 基本的にはバックエンドの変更にフロントエンドが引っ張られる 状態 ○ Ruby (Sorbet) と TypeScript の型をそれぞれ管理する必要がある ● 一般的な解決方法: OpenAPI Schema からのコード生成 ○ 取り組んでいるが、コードベースが大きすぎてなかなか進まない のが現状 ○ API 経由だけではなく erb に直接値を埋め込んでいる箇所が存在する freee会計における課題 Ruby (バックエンド) の実装を SSoT (Single Source of Truth) として TypeScript (フロントエンド) のコードを生成するのはどうだろう

Slide 11

Slide 11 text

11 ● バックエンドの変更が即座にフロントエンドに反映される状態 を作る ○ 無理に疎結合を作り出すのではなく良い密結合を達成する ○ フロントエンドは TypeScript なので影響がある場合は型エラーとして検出できる ■ 特に field/value の削除や rename はこれまでもバグの温床となっていた 目指すべき姿

Slide 12

Slide 12 text

どうやって実現する?

Slide 13

Slide 13 text

13 ● バックエンド解析 ○ Prism ■ Ruby の新しい標準パーサー ■ Web Assembly が提供されていて Node.js から利用可能 ■ https://www.npmjs.com/package/@ruby/prism ● フロントエンドのコード生成 ○ TypeScript Compiler API ■ 依存を増やしたくなかったので ts-morph や Alloy の採用は見送った 実現方法

Slide 14

Slide 14 text

14 ● Prism を使って Ruby のコードから AST (抽象構文木) を抽出 ● Ruby AST から TypeScript Compiler API で TypeScript のコード生成 ○ 型・定数・それらに関連する utility method を生成 ● この仕組みを使って約 1,000 ファイルのコードが作成されている 実現方法 module FlagHelper def flags { flag_1: hogehoge_method, flag_2: hogehoge_method, flag_3: hogehoge_method } end end type Flags = { flag_1: boolean, flag_2: boolean, flag_3: boolean } const defaultFlags: Flags = { flag_1: false, flag_2: false, flag_3: false }

Slide 15

Slide 15 text

15 ● 複雑な型の生成 ○ Ruby は型がない ○ インターフェースを整理して型を自明にすることでマッピングを楽にしている ■ 基本的にすべてのフィールドが 1 つの primitive 型になるように ○ 変換ロジックが肥大化して今後のメンテナンスが困難になることを避けた やらなかったこと

Slide 16

Slide 16 text

16 ● Sorbet の型アノテーションを元にした TypeScript の型のマッピング ○ 複雑な型の生成はやっぱり欲しくなる ○ Sorbet の公式サイトに TypeScript と Sorbet の変換表がある 今後の展望

Slide 17

Slide 17 text

まとめ

Slide 18

Slide 18 text

18 ● バックエンドの実装を SSoT としてフロントエンドのコードを生成した ● バックエンドとフロントエンドの両方の型をメンテナンスする必要がなくなった ○ ある程度の変更漏れを TypeScript の型エラーで検出可能 ○ 変更漏れが起因となっていたバグを減らすことができた ● Prism/TypeScript Compiler API を使って Ruby AST を TypeScript AST に変換した ○ 飛び道具感はあるが言語の壁を超えて現時点での依存の最適化ができた まとめ

Slide 19

Slide 19 text

19 6/9 (火) に M3 さんとアフターイベントやります! 告知

Slide 20

Slide 20 text

スモールビジネスを、世界の主役に。