Slide 1

Slide 1 text

Rust、何もわからない… #4 Rust、何もわからないので頑張らないWeb開発 …とこれから頑張るために 門田見 侑大

Slide 2

Slide 2 text

● 読み方は「かどたみ」 ○ 世界に20人の絶滅危惧種、イジメ、ダメ、ゼッタイ ● 出戻りテックリード ○ 創業時はインターンでフロントエンド開発 ○ 新卒でメガベンチャーからの出戻り ● 社会人ではもっぱらレガシー改善 ○ 前職でもレガシー改善 😭 ○ 現職でもレガシー改善 😭 ○ 最近モダン化リプレース 🎉 ■ Rustで認証認可基盤開発 門田見 侑大

Slide 3

Slide 3 text

● 「IT × 統計 × コンサル」 で日本の経済を成長させるサービス ○ コストカット・効率化ではなく「 企業の事業成長のお手伝い 」 ● 自身・仲間の経験(キャリア、履歴書)をより豊かに ○ チャレンジ推奨 ○ チームで働く ● Actix Web, NestJS, Ruby on Rails, Angular, GCP, AWS ● ちょっとでも気になったらカジュアル面談にぜひ! ○ estieさんと同じビルなので estieさんに行くついででも! 株式会社エモーションテック

Slide 4

Slide 4 text

今日のお話 ● エモテクでのRustの立ち位置 ● 開発方針について ● なんで頑張らなかったのか ● これから頑張るためにやっていること

Slide 5

Slide 5 text

Rust、何もわからない... #4 エモテクでのRustの立ち位置

Slide 6

Slide 6 text

エモテクでのRustの立ち位置 ● バックエンド初の静的型付け言語 ● 2021年6月頃から利用 ● 既存プロダクトの認証認可基盤の移管PJとして立ち上げ ○ 切り出しから作り直しへシフト ○ ABAC と RBACを合わせた認可制御 ● Web Frameworkは Actix Web ● DB crateは sqlx

Slide 7

Slide 7 text

Rust、何もわからない... #4 エモテクでのRust開発

Slide 8

Slide 8 text

設計方針 ● シンプルなレイヤードアーキテクチャ Presentation層 Application層 Domain 層 Infrastracture層

Slide 9

Slide 9 text

設計方針 ● cargo workspace を利用し、各層をcrateに分ける Presentation層 Application層 Domain 層 Infrastracture層

Slide 10

Slide 10 text

設計方針 ● 各層で依存crateを指定できるので思わぬ設計破りは防げる( DomainからInfra呼ぶみたいな) Presentation層 Application層 Domain 層 Infrastracture層

Slide 11

Slide 11 text

Rust、何もわからない... #4 小ネタ

Slide 12

Slide 12 text

小ネタ ● 各層で同じ外部crateを利用するとき、愚直に全部書いてた Presentation層 Application層 Domain 層 Infrastracture層

Slide 13

Slide 13 text

小ネタ ● 同一アプリ内でバージョンが異なる危険 & アップデートめんどくさい Presentation層 Application層 Domain 層 Infrastracture層

Slide 14

Slide 14 text

小ネタ ● 最下層に書いて、re-export Presentation層 Application層 Domain 層 Infrastracture層

Slide 15

Slide 15 text

小ネタ ● 他の層で利用できるし、アップデートも最下層だけで済む Presentation層 application層 Domain 層 infrastracture層

Slide 16

Slide 16 text

こんな感じで ● 所有権が〜 ● みたいな基本的な記事はいっぱい見かける ● web開発Tipsの記述はあまり見かけなかった ● re-exportも本当に正しい解決なのかはわからない ● 前の問題を解決して、「現状、困ってない」程度

Slide 17

Slide 17 text

こんな感じで ● 所有権が〜 ● unwrapはダメ〜 ● みたいなことはいっぱい見かける ● web開発Tipsの記述はあまり見かけなかった ● re-exportも本当に正しい解決なのかはわからない ● 前の問題を解決して、「現状、困ってない」程度 ● と、おもったら1.64からワークスペース共通の crateが定義できるようになった ● すごい、、、わからない、、、

Slide 18

Slide 18 text

スタンス わからないので、、、

Slide 19

Slide 19 text

スタンス 頑張らないで動かして後で改善しよう

Slide 20

Slide 20 text

頑張らない なにを?

Slide 21

Slide 21 text

頑張らなかった点 ● Rustらしい構文 ○ 強制したのは組み込みフォーマッターくらい ○ clippyすらあとからCIに入れた ○ ライブラリのエラー型ごとに map_errに渡す関数書いてたりしてた ● crate選定 ○ デファクトスタンダードがあるのかもわからない ○ awesome rustからとりあえず使って、比較して、直感で良かったもの ● パフォーマンス ○ to_owned()やclone()連発 ○ collect()連発

Slide 22

Slide 22 text

頑張らない なんで?

Slide 23

Slide 23 text

なんで頑張らなかったのか? ● 複数言語でのマイクロサービス開発を少人数でやる ○ らしさを求めすぎても構文的なコンテキストスイッチのコスト大 ○ sqlx で生SQL書いてるのもそのため ● toBコンポーネントのWebのバックエンドから始まった ○ toC側に比べてトラフィックが少ない ○ メモリ領域とかそこまでシビアでない (String vs &strみたいなよくある話) ○ Webの処理速度問題大抵の場合 DBのIO説…

Slide 24

Slide 24 text

なんで頑張らなかったのか? 【建前】 ● 複数言語でのマイクロサービス開発を少人数でやる ○ らしさを求めすぎても構文的なコンテキストスイッチのコスト大 ○ sqlx で生SQL書いてるのもそのため ● toBコンポーネントのWebのバックエンドから始まった ○ toC側に比べてトラフィックが少ない ○ メモリ領域とかそこまでシビアでない (String vs &strみたいなよくある話) ○ Webの処理速度問題大抵の場合 DBのIO説… 【本音】 ● らしさを追求し続けることでの開発速度・モチベーション低下 ● どこまで頑張る問題 ○ 未経験言語でどこまで頑張るか決めるの難しくないですか?

Slide 25

Slide 25 text

頑張らなかった結果 ● とりあえずRust書ける人が増えた ○ プログラミング歴1年ほどのインターン生 もRust開発に参加 ○ 直近、半年で3人Rustでの開発にjoin ● 頑張らなかった、という事実を認めて改善する意識ができた ○ #random_rust チャンネル開設・情報共有 ○ githubにリファクタリングリスト PR ■ 方向転換期にリファクタを決行

Slide 26

Slide 26 text

では... これからどうする?

Slide 27

Slide 27 text

スタンス 頑張らないで動かして後で改善しよう

Slide 28

Slide 28 text

後で改善 必要なものは?

Slide 29

Slide 29 text

必要なもの テスト

Slide 30

Slide 30 text

RustのUnit Test ● 基本はユニットテストを本番コードと同じファイルに記述

Slide 31

Slide 31 text

RustのIntegration Test ● 結合テストは各createのtestsディレクトリ以下に書く

Slide 32

Slide 32 text

エモテクでは うまく行かなかった

Slide 33

Slide 33 text

Rust、何もわからない... #4 エモテクでのテスト

Slide 34

Slide 34 text

エモテクのテスト ● 結論から言うと、、、 Presentation層 Application層 Domain 層 Infrastracture層

Slide 35

Slide 35 text

エモテクのテスト ● ドーン!!!!!!!!!!!!! Presentation層 Application層 Domain 層 Infrastracture層 testcase

Slide 36

Slide 36 text

エモテクのテスト ● ドーン!!!!!!!!!!!!! Presentation層 Application層 Domain 層 Infrastracture層 testcase

Slide 37

Slide 37 text

Rust、何もわからない... #4 なんでこうなった?

Slide 38

Slide 38 text

開発最初期は基本に則っていた Presentation層 Application層 Domain 層 Infrastracture層 ● そのまま本番コードの下に書いていた ● Domain層はファイル自体が短めだったため C2カバレッジを意識しても 300行ほどだった ● 認証認可を制御する契約組織のドメインから開発 ● 単純なCRUDしかないのでシンプルに書けた

Slide 39

Slide 39 text

辛くなってきた Presentation層 Application層 Domain 層 Infrastracture層 ● infra層のテストを書く上で辛くなった ● sqlxで生SQLを書くので本番コード自体が長くなる ● テスト合わせるとかなりファイルが巨大になり 辛さが出てくる

Slide 40

Slide 40 text

ファイルを分けたくなったのでtestsへ Presentation層 Application層 Domain 層 Infrastracture層 ● infra層のテストを書く上で辛くなった ● sqlxで生SQLを書くので本番コード自体が長くなる ● テスト合わせるとかなりファイルが巨大になり 辛さが出てくる ● 全部testsディレクトリへ tests dir tests dir tests dir tests dir

Slide 41

Slide 41 text

新たな課題 Presentation層 Application層 Domain 層 Infrastracture層 ● DB含めてテストを全部並列で動かすには テスト毎に影響しないデータが必要 ● infra層のunitテストとpresentation層の結合テストでは特に複雑 なステータスのデータが必須となる ● 例 ○ 招待済みだが、有効化されてないユーザー ○ ユーザーとアクセス許可されていないリソース ○ そもそも普通のユーザーもトークンチェックとかある から作成面倒 tests dir tests dir tests dir tests dir

Slide 42

Slide 42 text

欲しい物 ● 複雑な工程のデータの作成をラップする処理置き場 ○ 右のようにユースケースをまたいで 作成されるデータを簡単に作りたい ○ 開発初期で仕様の変更も激しいので テスト毎に本番の関数を呼ぶのはきつい

Slide 43

Slide 43 text

欲しい物 ● 複雑な工程のデータの作成をラップする処理置き場 ○ 右のようにユースケースをまたいで 作成されるデータを簡単に作りたい ○ 開発初期で仕様の変更も激しいので テスト毎に本番の関数を呼ぶのはきつい ユーザー招待時の処理 ユーザー有効化処理 (製品ではメールの招待 リンクを踏む)

Slide 44

Slide 44 text

欲しい物 ● 複雑な工程のデータの作成をラップする処理置き場 ○ 右のようにユースケースをまたいで 作成されるデータを簡単に作りたい ○ 開発初期で仕様の変更も激しいので テスト毎に本番の関数を呼ぶのはきつい ● 層をまたいでcrate間で共有できる ○ infra層のテストでも使えるし presentation層の結合テストでも使えてほしい

Slide 45

Slide 45 text

欲しい物 ● 複雑な工程のデータの作成をラップする処理置き場 ○ 右のようにユースケースをまたいで 作成されるデータを簡単に作りたい ○ 開発初期で仕様の変更も激しいので テスト毎に本番の関数を呼ぶのはきつい ● 層をまたいでcrate間で共有できる ○ infra層のテストでも使えるし presentation層の結合テストでも使えてほしい どこで作ろう!?

Slide 46

Slide 46 text

Rust、何もわからない... #4 試行錯誤

Slide 47

Slide 47 text

案1: tests dirにfactory作る Presentation層 application層 Domain 層 infrastracture層 ● infra層のtestsの中にUserDataFactoryを作ってみた ● データの作成が1箇所にまとめられ、 仕様変更にも耐えやすくなった tests dir tests dir tests dir tests dir user_data_factory.rs

Slide 48

Slide 48 text

案1: tests dirにfactory作る Presentation層 application層 Domain 層 infrastracture層 ● infra層のtestsの中にUserDataFactoryを作ってみた ● データの作成が1箇所にまとめられ、 仕様変更にも耐えやすくなった ● しかし、testsディレクトリはexportされないため workspaceで構築しているアプリでは他の層で使えない tests dir tests dir tests dir tests dir user_data_factory.rs

Slide 49

Slide 49 text

案2: infra層にfactoryを作る Presentation層 application層 Domain 層 infrastracture層 ● 普通に本番コードと同等の扱いにする tests dir tests dir tests dir tests dir user_data_factory.rs

Slide 50

Slide 50 text

案2: infra層にfactoryを作る Presentation層 application層 Domain 層 infrastracture層 ● 普通に本番コードと同等の扱いにする ● exportできるので他の層から利用できる ● これでヨシ!って一旦なった tests dir tests dir tests dir tests dir user_data_factory.rs

Slide 51

Slide 51 text

案2: infra層にfactoryを作る Presentation層 application層 Domain 層 infrastracture層 ● 普通に本番コードと同等の扱いにする ● exportできるので他の層から利用できる ● これでヨシ!って一旦なった ● 不安との戦い、、、 ● 前述の通り本番コードとしてはありえないユースケース ○ 設計のほころびはいずれ生まれるかも? ● 開発Buildだとtestにしか使ってなくても バイナリに含まれる ○ 開発コンテナの肥大化につながるかも? tests dir tests dir tests dir tests dir user_data_factory.rs

Slide 52

Slide 52 text

案3: test projectを作る Presentation層 application層 Domain 層 infrastracture層 ● projectを分けて外部crate化 ● factoryは絶対に本番コードから参照できない ● APP側でビルドすればバイナリに含まれない APP TEST testcase tests dir user_data_factory.rs

Slide 53

Slide 53 text

案3: test projectを作る Presentation層 application層 Domain 層 infrastracture層 ● projectを分けて外部crate化 ● factoryは絶対に本番コードから参照できない ● APP側でビルドすればバイナリに含まれない ● CIの時間が爆増、、、 ● TESTとAPP両方でbuildしないとダメ APP TEST testcase tests dir user_data_factory.rs

Slide 54

Slide 54 text

● testのfactoryは絶対に本番コードから参照できない ● 開発ビルドでバイナリに含まれない ● CIでtestから実行してpresentationをbuildすると test時の結果を再利用して即終了 案4: 別crateにしてworkspaceに含める Presentation層 application層 Domain 層 infrastracture層 testcase tests dir user_data_factory.rs

Slide 55

Slide 55 text

● testのfactoryは絶対に本番コードから参照できない ● 開発ビルドでバイナリに含まれない ● CIでtestから実行してpresentationをbuildすると test時の結果を再利用して即終了 案4: 別crateにしてworkspaceに含める Presentation層 application層 Domain 層 infrastracture層 testcase tests dir user_data_factory.rs

Slide 56

Slide 56 text

結果 ● テストのメンテコストも比較的下がった ● 結合テストも書きやすくなったのでリファクタリングもしやすい ● テストがしっかりしてくるとライブラリのバージョンアップもやりやすい

Slide 57

Slide 57 text

結果 ● テストのメンテコストも比較的下がった ● 結合テストも書きやすくなったのでリファクタリングもしやすい ● テストがしっかりしてくるとライブラリのバージョンアップもやりやすい ● RustのWeb開発をあとから頑張りやすい!!!!

Slide 58

Slide 58 text

まとめ ● 頑張らない理由と頑張るためのテスト構成を紹介した ● 頑張らないからこそRust特有ではない部分で頑張ると Rustを頑張る投資になりそう ● エモテクではテストは別 crateに分けて書いている ○ 正解かどうかもわからないですが、困ってないです ○ 我々こうやってうまくいってるよ!みたいなのあれば教えて下さい ● みなさんも頑張りすぎず気軽に RustでWeb開発やってみませんか?