この記事は Safie Engineers' Blog! Advent Calendar 4日目の記事です。
はじめに
こんにちは。第3開発部でエンジニアをしている伊東です。今回は2024年新卒エンジニア研修における、バックエンド分野の開発についてお話しします。
セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介
セーフィーでは全体研修後、約3ヶ月のエンジニア研修があり、エンジニアとしての基礎を学びつつ、社内課題を解決するプロダクトを開発しました。課題選定から開発言語、体制まで全て自分たちで決める形式で、私たちは「isai connect」を開発しました。これは、他部署の方とランチに行くと会社がランチ代を負担してくれる「異才ランチ」制度をより活用し、活発化を図るためのプロダクトです。詳しくは以下の記事でご覧ください。
- 新卒研修の紹介とチーム開発前にやったこと
- アジャイルを実践してみる
- isai connectについて
- isai connect開発のアウトプット_サーバーサイド ←本記事
- isai connect開発のアウトプット_フロント (12/5 公開予定)
- isai connect開発のアウトプット_インフラ (12/6 公開予定)
- isai connect開発のアウトプット_デバイス (12/7 公開予定)
- 新卒研修の成果発表とその後 (12/8 公開予定)
機能
isai connectで実装した主要機能は以下の通りです。isai connect管理者にはユーザ管理機能、ユーザにはレコメンド機能とコネクト機能を提供しています。
- ユーザ管理
月一で従業員名簿からユーザを作成・更新・削除する機能です。isai connectに登録していないユーザもレコメンドし、コネクトさせる必要があるため従業員名簿からユーザを一括登録しています。
- レコメンド
一緒にランチするメンバーを指定したチームからランダムに提示してくれる機能です。「全従業員が保持している属性」「属性判別が容易」の2観点からチーム指定をまず実装しました。今後は様々な属性を指定できるようにしていきます。
- コネクト
レコメンドされたメンバーに対してランチを誘うSlack DMを送信し、ランチ参加者だけのSlackグループを作成する機能です。社内の主なコミュニケーションツールであるSlackのDM機能を使用することで、メッセージの見逃しリスクを低減し、スムーズな意思決定を促進しています。
設計
isai connectのバックエンド実装を設計書を用いて説明します。
ER図
以下にisai connect用のER図を示します。
各テーブルが管理している情報は以下の通りです。
- ユーザ情報
- 部門情報
- 部署情報
- グループ情報
- コネクト実績情報
- ユーザに関連する製品情報
- コネクト状況の情報
- コネクト参加者の情報
コネクト実績とユーザに関連する製品情報を管理するテーブルは、ユーザと多対多の関係になることから、中間テーブルを使用して効率的に管理できるようにしています。
シーケンス図
開発当初は処理ロジックを明確にするためシーケンス図を作成していましたが、API仕様書をフロントエンドと協議して作成する際に実装ロジックが明確になり、共通理解が生まれるため、途中から作成されなくなりました。開発時のシーケンス図の利用頻度は高くはありませんでしたが、参考としてレコメンドからコネクトまでのシーケンス図を掲載します。
API仕様書
1〜3スプリントでは、認識の齟齬を生まないために予めフロントエンドと協議してAPI仕様を策定し、仕様書としてドキュメント化していました。4スプリント目では協議とドキュメント化の時間削減を目的に、バックエンドが定義したAPI仕様をSwagger UIを通じてフロントエンドに渡し、必要であれば都度修正するという試みを行いました。しかしながら、この試みは都度修正の特性上、フロントエンド・バックエンド双方に手戻りを多く強いることになり、結果として多大な時間を浪費することになりました。Swagger UIをドキュメントの代替として用いたことは間違ったアプローチではありませんでしたが、事前の十分な協議なしにこの方法を導入したことが問題でした。
以下に最終的に作成したisai connectのAPI仕様書の一部を示します。
isai/random/は、部門及び部署をクエリパラメータとして指定することで、ランダムなユーザを一人取得するためのAPIです。また、isai/connectは、ホストユーザーと1~3人のゲストユーザーのIDを受け取り、コネクトを行うためのAPIです。
実装
isai connectのバックエンドの実装方法について説明します。
使用技術
配属後の学習コストを減らす目的で、実際にセーフィーで活用されている言語及びフレームワークを選定しました。使用言語、フレームワーク、主要なライブラリは以下の通りです。
- 言語
- フレームワーク
- ライブラリ
- Pydantic
- SQLAlchemy
- Alembic
ディレクトリ構成
バックエンドの1層目の主要ディレクトリ及びファイルを以下に示します。
app/
├── connect_db.py
├── cruds/
├── init_db.py
├── main.py
├── models/
├── routers/
├── schemas/
├── tests/
├── util/
このディレクトリ構成で開発を進めた結果、ビジネスロジックがcrudsに集中してしまい、ファイルの肥大化と難読化が進行、重複処理が増加するという課題が生じました。この課題を解決するため、今後の開発ではディレクトリ構成の見直しが必要だと考えています。改善策としては、crudsディレクトリ内では純粋なデータベース操作のみを許容し、ビジネスロジックは新たに作成するservicesディレクトリに移動、共通処理の抽出などが挙げられます。これらの変更により、コードの構造が明確になり、保守性と可読性の向上が期待できます。
認証
isai connectの認証では、セキュリティ面と実装の容易さから、OAuth2をベースに、JWTを認証トークンとする方式にしています。基本的な実装はFastAPI公式に従っていますが、トークンが漏洩した場合のリスクを軽減を目的に、追加でリフレッシュトークンを導入しています。また、トークンの保存にはHttpOnlyおよびSecure属性を持つCookieを使用しています。
工夫したポイント
isai connectでは、ユーザの情報取得やDM送信のためにSlack APIを使用しています。これを逐次処理でおこなうと相当な時間を要するため、処理を並行化やマルチスレッド化することが検討されました。並行化とマルチスレッド化を比較したところ、処理時間平均に大きな差異はありませんでしたが、最小と最大の処理時間の差が並行化した方が少く、安定した性能であったため、並行化が採用されました。結果として、DM送信の処理時間を逐次処理したときと比較して2.6倍ほど早めることができました。
おわりに
筆者は、インターンシップで個人でのシステム開発経験を積む機会がありましたが、チームとしてフロントエンドやバックエンドに分かれての開発経験は限られていました。個人開発の際には、設計のドキュメント化を軽視する傾向がありましたが、チーム開発を経験した現在では、チーム内共有の観点からその重要性を強く認識するようになりました。現在所属する部署では、実装だけでなく、事前の調査や事後の評価など、実装の前後のプロセスも成果物の一つとして重視されています。そのため、配属前にドキュメント化の重要性に対する意識を高められたことは、非常に有益でした。
今後、isai connectは開発フェーズから運用フェーズに移行しますが、システムの拡張を継続し、社内コミュニケーションを活発にしたいと考えています。
最後までご覧いただき、ありがとうございました。