$30 off During Our Annual Pro Sale. View Details »

Rust、何もわからないので頑張らないWeb開発 …とこれから頑張るために

Rust、何もわからないので頑張らないWeb開発 …とこれから頑張るために

Rust、何もわからない登壇資料
https://estie.connpass.com/event/259713/

yuta kadotamai

October 06, 2022
Tweet

More Decks by yuta kadotamai

Other Decks in Technology

Transcript

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

  2. • 読み方は「かどたみ」 ◦ 世界に20人の絶滅危惧種、イジメ、ダメ、ゼッタイ • 出戻りテックリード ◦ 創業時はインターンでフロントエンド開発 ◦ 新卒でメガベンチャーからの出戻り

    • 社会人ではもっぱらレガシー改善 ◦ 前職でもレガシー改善 😭 ◦ 現職でもレガシー改善 😭 ◦ 最近モダン化リプレース 🎉 ▪ Rustで認証認可基盤開発 門田見 侑大
  3. • 「IT × 統計 × コンサル」 で日本の経済を成長させるサービス ◦ コストカット・効率化ではなく「 企業の事業成長のお手伝い

    」 • 自身・仲間の経験(キャリア、履歴書)をより豊かに ◦ チャレンジ推奨 ◦ チームで働く • Actix Web, NestJS, Ruby on Rails, Angular, GCP, AWS • ちょっとでも気になったらカジュアル面談にぜひ! ◦ estieさんと同じビルなので estieさんに行くついででも! 株式会社エモーションテック
  4. 今日のお話 • エモテクでのRustの立ち位置 • 開発方針について • なんで頑張らなかったのか • これから頑張るためにやっていること

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

  6. エモテクでのRustの立ち位置 • バックエンド初の静的型付け言語 • 2021年6月頃から利用 • 既存プロダクトの認証認可基盤の移管PJとして立ち上げ ◦ 切り出しから作り直しへシフト ◦

    ABAC と RBACを合わせた認可制御 • Web Frameworkは Actix Web • DB crateは sqlx
  7. Rust、何もわからない... #4 エモテクでのRust開発

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

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

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

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

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

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

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

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

  16. こんな感じで • 所有権が〜 • みたいな基本的な記事はいっぱい見かける • web開発Tipsの記述はあまり見かけなかった • re-exportも本当に正しい解決なのかはわからない •

    前の問題を解決して、「現状、困ってない」程度
  17. こんな感じで • 所有権が〜 • unwrapはダメ〜 • みたいなことはいっぱい見かける • web開発Tipsの記述はあまり見かけなかった •

    re-exportも本当に正しい解決なのかはわからない • 前の問題を解決して、「現状、困ってない」程度 • と、おもったら1.64からワークスペース共通の crateが定義できるようになった • すごい、、、わからない、、、
  18. スタンス わからないので、、、

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

  20. 頑張らない なにを?

  21. 頑張らなかった点 • Rustらしい構文 ◦ 強制したのは組み込みフォーマッターくらい ◦ clippyすらあとからCIに入れた ◦ ライブラリのエラー型ごとに map_errに渡す関数書いてたりしてた

    • crate選定 ◦ デファクトスタンダードがあるのかもわからない ◦ awesome rustからとりあえず使って、比較して、直感で良かったもの • パフォーマンス ◦ to_owned()やclone()連発 ◦ collect()連発
  22. 頑張らない なんで?

  23. なんで頑張らなかったのか? • 複数言語でのマイクロサービス開発を少人数でやる ◦ らしさを求めすぎても構文的なコンテキストスイッチのコスト大 ◦ sqlx で生SQL書いてるのもそのため • toBコンポーネントのWebのバックエンドから始まった

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

    toBコンポーネントのWebのバックエンドから始まった ◦ toC側に比べてトラフィックが少ない ◦ メモリ領域とかそこまでシビアでない (String vs &strみたいなよくある話) ◦ Webの処理速度問題大抵の場合 DBのIO説… 【本音】 • らしさを追求し続けることでの開発速度・モチベーション低下 • どこまで頑張る問題 ◦ 未経験言語でどこまで頑張るか決めるの難しくないですか?
  25. 頑張らなかった結果 • とりあえずRust書ける人が増えた ◦ プログラミング歴1年ほどのインターン生 もRust開発に参加 ◦ 直近、半年で3人Rustでの開発にjoin • 頑張らなかった、という事実を認めて改善する意識ができた

    ◦ #random_rust チャンネル開設・情報共有 ◦ githubにリファクタリングリスト PR ▪ 方向転換期にリファクタを決行
  26. では... これからどうする?

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

  28. 後で改善 必要なものは?

  29. 必要なもの テスト

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

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

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

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

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

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

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

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

  38. 開発最初期は基本に則っていた Presentation層 Application層 Domain 層 Infrastracture層 • そのまま本番コードの下に書いていた • Domain層はファイル自体が短めだったため

    C2カバレッジを意識しても 300行ほどだった • 認証認可を制御する契約組織のドメインから開発 • 単純なCRUDしかないのでシンプルに書けた
  39. 辛くなってきた Presentation層 Application層 Domain 層 Infrastracture層 • infra層のテストを書く上で辛くなった • sqlxで生SQLを書くので本番コード自体が長くなる

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

    • テスト合わせるとかなりファイルが巨大になり 辛さが出てくる • 全部testsディレクトリへ tests dir tests dir tests dir tests dir
  41. 新たな課題 Presentation層 Application層 Domain 層 Infrastracture層 • DB含めてテストを全部並列で動かすには テスト毎に影響しないデータが必要 •

    infra層のunitテストとpresentation層の結合テストでは特に複雑 なステータスのデータが必須となる • 例 ◦ 招待済みだが、有効化されてないユーザー ◦ ユーザーとアクセス許可されていないリソース ◦ そもそも普通のユーザーもトークンチェックとかある から作成面倒 tests dir tests dir tests dir tests dir
  42. 欲しい物 • 複雑な工程のデータの作成をラップする処理置き場 ◦ 右のようにユースケースをまたいで 作成されるデータを簡単に作りたい ◦ 開発初期で仕様の変更も激しいので テスト毎に本番の関数を呼ぶのはきつい

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

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

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

    層をまたいでcrate間で共有できる ◦ infra層のテストでも使えるし presentation層の結合テストでも使えてほしい どこで作ろう!?
  46. Rust、何もわからない... #4 試行錯誤

  47. 案1: tests dirにfactory作る Presentation層 application層 Domain 層 infrastracture層 • infra層のtestsの中にUserDataFactoryを作ってみた

    • データの作成が1箇所にまとめられ、 仕様変更にも耐えやすくなった tests dir tests dir tests dir tests dir user_data_factory.rs
  48. 案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
  49. 案2: infra層にfactoryを作る Presentation層 application層 Domain 層 infrastracture層 • 普通に本番コードと同等の扱いにする tests

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

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

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

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

    • factoryは絶対に本番コードから参照できない • APP側でビルドすればバイナリに含まれない • CIの時間が爆増、、、 • TESTとAPP両方でbuildしないとダメ APP TEST testcase tests dir user_data_factory.rs
  54. • testのfactoryは絶対に本番コードから参照できない • 開発ビルドでバイナリに含まれない • CIでtestから実行してpresentationをbuildすると test時の結果を再利用して即終了 案4: 別crateにしてworkspaceに含める Presentation層

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

    application層 Domain 層 infrastracture層 testcase tests dir user_data_factory.rs
  56. 結果 • テストのメンテコストも比較的下がった • 結合テストも書きやすくなったのでリファクタリングもしやすい • テストがしっかりしてくるとライブラリのバージョンアップもやりやすい

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

  58. まとめ • 頑張らない理由と頑張るためのテスト構成を紹介した • 頑張らないからこそRust特有ではない部分で頑張ると Rustを頑張る投資になりそう • エモテクではテストは別 crateに分けて書いている ◦

    正解かどうかもわからないですが、困ってないです ◦ 我々こうやってうまくいってるよ!みたいなのあれば教えて下さい • みなさんも頑張りすぎず気軽に RustでWeb開発やってみませんか?