maeda-m / employmate

病気やケガで退職した後、働く意思がある60歳未満の方向けの、雇用保険の失業等給付(基本手当)がいつ頃になるかがわかるWebサービスです。
https://employmate.jp
MIT License
3 stars 0 forks source link

技術選定・技術検証をする #12

Closed maeda-m closed 1 year ago

maeda-m commented 1 year ago

書式「〇〇よりも△△△を選択する、それは(どんな状況の問題・課題を解決しようとした技術)だからだ。」で結論をコメントする。

https://bootcamp.fjord.jp/practices/226


参考情報

https://speakerdeck.com/toricls/you-wont-be-in-the-team-forever?slide=24


以下、検討項目。

システムアーキテクチャ

モノリシックモノリスかマイクロサービスか?

開発言語・フレームワーク

バックエンド

バックエンドはRubyを前提とします。また REST 前提であるため GraphQL は使用しません。

Rails かそれ以外か

永続化レイヤーをどうしたいか?で判断する。

テストをどうしたいか?

テスティングフレームワークの RSpec か Minitest を選ぶ。

基本的に受け入れテストを多めにして、単体レベルのパターン網羅が必要な場合は単体テストを網羅的に書く方針としたい。 というのも、プロジェクトではなく、プロダクトであるため、変更を受け入れやすくするため、E2Eでテストしておけば最低限の品質は担保できるだろうという判断です(変更を受けれにくくする単体テストは書かない)。

また受け入れテストを自然言語で表現し、裏ではテスティングフレームワークで頑張る方針にしたいが、E2E で Turnip などを選択している場合は RSpec 一択になる。

本体のコードベースをより少ないコードにするには?

必要そうな機能を Gem で実現できるかを検討する。‘もしなかったら開発時に lib 配下に実装してから Gem に分離する。

フロントエンド

バニラJSかライブラリか

Hotwire で十分かもしれない。

認証

Googleアカウントの識別子を使用したい。 API とサービス – Google Cloud コンソール から OAuth の設定をして検証用のコードで試す。

https://developers.google.com/identity/openid-connect/openid-connect?hl=ja より

Google の OAuth 2.0 API は認証と認可の両方に使用できます。

アプリケーションサーバー

本番環境をマネージドサービスでなく自前で用意する場合は検討が必要。 PumaPassenger かを選ぶ。

ウェブサーバー

本番環境をマネージドサービスでなく自前で用意する場合は検討が必要。

NginxApache かを選ぶ。

データベースサーバー

PostgreSQL か MySQL かを選ぶ。もし永続化としてふさわしければ sessionStorage も検討する。 なお 私の古い知識としては MySQL は order by で index が効かないパターンがある認識です。

maeda-m commented 1 year ago

システムアーキテクチャ

マイクロサービスよりもモノリシックモノリスを選択する。

それはマイクロサービスはコンテキストや Frontend と Backend で独立してリリースする目的であるため、 ひとりで開発するのであればモノリシックモノリスがよいと判断しました。

技術名 どんな状況の どんな問題・課題を どのようにして解決しようとする技術
モノリシックモノリス PoSA本にヒントがあるかと思いざっと読んだがよくわからなかった - アプリケーションを1つのコード ベースで構築する
マイクロサービス 大きくなりすぎてスケーリングが困難なモノリシックアプリケーション 1つの機能に小さな変更を加えるために、全体をコンパイルしてテストする必要がある
機能を更新することで無関係な機能にバグが入るリスクがある
データベースの分割やシステムのコンテキストで分割することでコード管理、認知コスト、デプロイを容易にする
maeda-m commented 1 year ago

データベースサーバー

MySQL よりも PostgreSQL を選択する。

今回のような小規模アプリケーションであれば性能的な差や用途による選定は難しいため、次の2点で判断した。

  1. gem の人気度
  2. 最新のRubyへの対応状況(どちらとも対応済みのようだ)
maeda-m commented 1 year ago

アプリケーションサーバー

Passenger よりも Puma を選択する。 それは少ないメモリのサーバーで、マルチスレッドにより I/O 待ちの応答時間が短縮されるからだ。

Puma 公式サイト を見ると圧倒的にパフォーマンスがいいことがわかります。

また Heroku が推奨するプロセス数とスレッド設定 を見ると Heroku - Standard-2X Dyno では 2 プロセス、 5 スレッド となりました。

Passenger の OSS 版では 1プロセスあたりの最大使用スレッド数の計算式 が用意されているため、Heroku - Standard-2X Dynoのスペックで計算しました。

計算式:
((1024 * 2 * 0.75) - (2 * RAM_PER_PROCESS * 0.9)) / (RAM_PER_PROCESS / 10) / 2

RAM_PER_PROCESS を 100 とすると計算結果は 67.8 となりました。 上記の計算結果から、もしスレッド数が多くなりすぎてスワップが頻発すると、レスポンスの遅延が発生しそうです。

maeda-m commented 1 year ago

ウェブサーバー

Apache よりも Nginx を選択する。

今回のような小規模アプリケーションであれば性能的な差(DDos対策なども含める)や用途による選定は難しいため、人気度で判断した。

比較サイト Nginx Apache
GitHub スター数 18.3k スター数 3.2k
Docker Hub スター数 10K+ スター数 4.4K
2022 Ruby on Rails Community Survey Results 人気度 1位 人気度 3位
maeda-m commented 1 year ago

フロントエンド

Hotwire で十分と判断した。 それは、今回のような小規模アプリケーションでは反応性が必要なところがあまりためだ。

必要であればバニラJS(ES2022 の構文)または Stimulus で実装するため、TypeScript などのトランスコンパイルは不要(もし大規模になるのであれば jsbundling-rails + esbuild で考え直す)。バンドリングは importmap で代替 する。

なおミニファイルや使われていないコードの自動削除については極力しておきたいが、実際にブラウザの読み込みを計測してから考える。

方針としては次のとおり。

  1. 質問ページ、結果ページ
    • 単純なページ遷移で Turbo Frames や Turbo Streams も使用する必要はなさそう
  2. 予定ページ、チェックリストチェック時の挙動
    • Turbo Frames で予定日、未完了チェックリスト、完了分チェックリストを表示する
    • Turbo Streams でアクションに応じて必要な箇所を update する URLを変えたい場合は data: { turbo_frame: "_top" } でTurbo Drive の挙動にする
    • Broadcast(Action Cable 経由で WebSocket を利用する) を使用しない あちこちで Stream を開始してしまいそうなので。。。
  3. Stimulus 経由では Turbo.renderStreamMessage(streamActionHTML) をすると Turbo Streams でアクションを実行する
  4. 状態の管理はバックエンド側で管理する
    • 遷移先は必要に応じて formactionform 属性によって振り分ける
    • 会員登録するまでは極力DBに保存せず、入力内容の保持は sessionStorage で保存する

また CSS は Tailwind を暫定導入とします。デザインの都合で差し替えるかもしれません。

maeda-m commented 1 year ago

認証

OpenId Connect で Google アカウントのID、メールアドレスを取得できた。 ボタンについては下図のようにHTMLの内容によってテキストを変えられるようだ。

Image

あとは取得したアカウントIDを bcrypt でハッシュ化し、DBに保存すればよさそう。

maeda-m commented 1 year ago

開発言語・フレームワーク

バックエンド

バックエンドはRuby 、 REST 前提とします。

永続化レイヤーをどうしたいか?

Rails かそれ以外か

テストをどうしたいか?

テスティングフレームワークは RSpec か Minitest か

議題に書いていた理由(以下、抜粋)により RSpec を利用する。

基本的に受け入れテストを多めにして、単体レベルのパターン網羅が必要な場合は単体テストを網羅的に書く方針としたい。

あわせて https://github.com/jnicklas/turniphttps://github.com/microsoft/playwright 1https://github.com/danmayer/coverband を導入する。

また必要に応じて次の Gem も導入する。

本体のコードベースをより少ないコードにするには?