新機能開発
プロダクトグループに在席。 新規施策の設計、実装、リリース。 (以下は特に印象深かったプロジェクトを列挙しております) # 法人機能の実装 法人機能とよばれる、新たなユーザーグルーピング機能と新しい支払方法の実装 ## チーム編成 - バックエンドエンジニア 1名 (私) - フロントエンドエンジニア 1名 - デザイナー 1名 - プロジェクトマネージャー ## 使用した技術やバージョンなど - Ruby on Rails(5系) - CakePHP - MySQL ## 要件 - 以下のチーム機能が使えるようになること - チームメンバー管理機能 - 管理画面からメンバーを招待できること (メール経由) - 管理画面からメンバー除外機能 - 購入データがチーム内で共有できること - CSVで出力できること - 請求書払いができるようになること - 源泉徴収の支払ができること ## 役割 - バックエンド側の設計、実装、テスト、リリース - 請求書払いにはPaidのシステムを利用 ## リリースまでの課題やストーリー ### 請求書払い機能の実装(Paidとの連携) 外部サービスとの決済連携ということで以下の点に注意して設計・実装を行いました。 「外部サービス(Paid)が障害を起こしていてもココナラ内ではサービスを継続できること」 ココナラでは購入した後に取引が始まり、役務提供が完了した後に「クローズ」を行うと収益が計上されます。 この「クローズ処理」が外部サービスに影響を受けないように設計しました。 (購入時の外部サービス障害は与信確認・確保などの要件があるため、エラーにして止めることで合意) ECの決済周りはどこも非常に複雑だと思いますが、ココナラも例外でなくかなり複雑で古い処理です。 ひとつひとつ読み解き、全体の構造を丁寧に把握してゆくことを心がけました。 決済処理は単体テストが存在しないCakePHP内に実装されているため、コードを追う & デバッガを使いつつ動かしてみて追うという手しか使えず非常に苦労しました。 この時に決済処理を一通り理解したため、以後は「決済処理に強い人」と評価いただき、お金周りでは必ず声をかけられるようになりました。 ### チーム機能の実装 チーム機能はさほど苦労しなかったのですが、強いて言えば(単体テストが存在しない)Cake部分の実装が非常につらかった記憶があります。 # 法人機能の実装 法人機能とよばれる、新たなユーザーグルーピング機能と新しい支払方法の実装 ## チーム編成 - バックエンドエンジニア 1名 (私) - フロントエンドエンジニア 1名 - デザイナー 1名 - プロジェクトマネージャー ## 使用した技術やバージョンなど - Ruby on Rails(5系) - CakePHP - MySQL ## 要件 - 以下のチーム機能が使えるようになること - チームメンバー管理機能 - 管理画面からメンバーを招待できること (メール経由) - 管理画面からメンバー除外機能 - 購入データがチーム内で共有できること - CSVで出力できること - 請求書払いができるようになること - 源泉徴収の支払ができること ## 役割 - バックエンド側の設計、実装、テスト、リリース - 請求書払いにはPaidのシステムを利用 ## リリースまでの課題やストーリー ### 請求書払い機能の実装(Paidとの連携) 外部サービスとの決済連携ということで以下の点に注意して設計・実装を行いました。 「外部サービス(Paid)が障害を起こしていてもココナラ内ではサービスを継続できること」 ココナラでは購入した後に取引が始まり、役務提供が完了した後に「クローズ」を行うと収益が計上されます。 この「クローズ処理」が外部サービスに影響を受けないように設計しました。 (購入時の外部サービス障害は与信確認・確保などの要件があるため、エラーにして止めることで合意) ECの決済周りはどこも非常に複雑だと思いますが、ココナラも例外でなくかなり複雑で古い処理です。 ひとつひとつ読み解き、全体の構造を丁寧に把握してゆくことを心がけました。 決済処理は単体テストが存在しないCakePHP内に実装されているため、コードを追う & デバッガを使いつつ動かしてみて追うという手しか使えず非常に苦労しました。 この時に決済処理を一通り理解したため、以後は「決済処理に強い人」と評価いただき、お金周りでは必ず声をかけられるようになりました。 ### チーム機能の実装 チーム機能はさほど苦労しなかったのですが、強いて言えば(単体テストが存在しない)Cake部分の実装が非常につらかった記憶があります。 # 出品者検索機能の実装 既存のサービス検索機能とは別に「出品者を探す」機能を新規に実装 ## チーム編成 - バックエンドエンジニア 1名 (私) - フロントエンドエンジニア 1名 - デザイナー 1名 - プロジェクトマネージャー ## 使用した技術やバージョンなど - Elasticsearch(6系) - Ruby on Rails(5系) - GoLang - gRPC - MySQL ## 要件: マイクロサービス化により分割された2つのDBの内容で1ユーザーを絞れること ## 役割: - 新規検索エンジンの選定 - 選定エンジンの導入資料作成、全エンジニアとの導入合意取得 - protoベースでAPI設計 & フロントエンドエンジニアとすり合わせ - 設計、実装、テスト、リリース - リリース後の課題整理、改善 ## リリースまでの課題やストーリー ### CloudSearchからElasticsearchへ 既に「サービスを探す」ための検索エンジン(AWSのCloudSearch)が導入されていました。しかし当時のCloudSearchには以下の問題がありました。 「一部だけUPDATEが行えない」 今回期待する内容は以下のようなものでした。 - アプリケーションA(DB1)からuser_id=1の「name」を取得 - アプリケーションB(DB2)からuser_id=1の「得意分野」を取得 - app Aからuser_id:1, name:taro をアップロード - app Bからuser_id:1, 得意分野:数学 をアップロード - 上記の結果、検索エンジン上では以下のようになってほしい - { user_id: 1, name: taro, 得意分野: 数学 } 当時のCloudSearchは後勝ちのデータに全て書き換わるようになっていました。 ※上記の例だとapp Bからのアップロード { user_id: 1, 得意分野: 数学 } に差し替わり、app Aからのアップロード内容は消えてしまいました。 Elasticsearch(ES)だと期待した挙動になるため導入することになりました。 なお別案として「別途集約アプリケーションを作り、その中でデータ集約してアップロードするのはどうか?」という手もありましたが - マイクロサービスの垣根を破壊すること - 管理すべきアプリケーションが増えること - 各サービスが知っていること(データ)はそれぞれのサービスが責任をもってアップロードすべき との考えから集約アプリケーション新設の案はボツになりました。 ### 初のgRPC このプロジェクト(と関連プロジェクト)からgRPCが導入されました。 - 誰もが慣れない実装 - デバッグの方法はどうやる? - コンパイル通らない!! - NULLを表すことができない? などなどひたすら苦労が多かったのですが、どうにかこうにかリリースまでたどり着きました。 ### Elasticsearchのチューニング 単純にCloudSearchから置き換えただけではなく、検索結果のチューニングも行いました。 どういったユーザーを上位に持ってきたいか、落とすべきかなどを他部署と連携、相談を実施。 各ユーザーについてスコアリング機能を別途実装したり、検索クエリのチューニング(特定のカテゴリを持つ人はブーストなど)を行いリリースへこぎつけました。 ### その他 このプロジェクトでElasticsearchのよさ(チューニングのしやすさ、資料の豊富さetc)が注目され、この後に作る検索システムは全てElasticsearchになりました。 (サービス検索もAWS CloudSearchからElasticsearchに置き換わりました)