Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Connect × Server-Side Kotlinで実現する!スキーマ駆動開発と品質改...

SansanTech
December 09, 2024

Connect × Server-Side Kotlinで実現する!スキーマ駆動開発と品質改善の実践

■ イベント
Sansan VS サイボウズ - 品質向上Tips冬祭り
https://sansan.connpass.com/event/335070/

■ 発表者
技術本部 Bill One Engineering Unit
市川 達裕

■ Bill Oneエンジニア 採用情報
https://media.sansan-engineering.com/billone-engineer

■ Sansan Tech Blog
https://buildersbox.corp-sansan.com/

SansanTech

December 09, 2024
Tweet

More Decks by SansanTech

Other Decks in Technology

Transcript

  1. Sansan株式会社 部署 名前 Connect × Server-Side Kotlinで実現する! スキーマ駆動開発と品質改善の実践 Sansan技術本部 Sansan

    VS サイボウズ - 品質向上Tips冬祭り Sansan株式会社 技術本部 Bill One Engineering Unit 市川 達裕
  2. アーキテクチャ Email Cloud Load Balancing Backend Cloud Run Database Cloud

    SQL Static Files Cloud Storage Cloud Tasks API Gateway Cloud Load Balancing API Client User Logging Error Reporting Cloud Build Bill One Entry Management / Developer Tools Cloud Functions Monitoring Authentication Auth0 Login Screen Frontend / BFF Cloud Run Pub/Sub
  3. - Large Scale Scrum (LeSS) Huge をベースとした開発体制 - プロダクト領域ごとに、複数の機能開発チームが紐づく 開発体制

    プランニング リファインメント 開発 テスト リリース Area PB デモ ⁃ Area PdM ⁃ Designers ⁃ Engineers ⁃ Area PdM ⁃ Designers ⁃ Engineers ⁃ Area PdM ⁃ Designers ⁃ Engineers Product Backlog (PB) Area PB Area PB Area PB
  4. - 開発着⼿のタイミングでEvent Stormingやドメイン・API設計を実施 - Backend / Frontendの実装は同⼀チーム内で進⾏ - Bill One

    のエンジニアはフルスタックエンジニア - 複数⼈で並⾏実装するケースも多い - APIスキーマ未導⼊のため、情報共有の⼿段はチームごとに様々 ⽇々のチーム開発 Event Storming 設計 Backend 実装 Frontend 実装 開発開始 デモ
  5. - Frontend - Backend間のAPIスキーマがズレる - チーム内の連携が上⼿く取れていないと頻発 - 最悪の場合、バグやインシデントに繋がるケースも存在 - Request

    Validationを都度実装している - ⼀定の実装コストがかかる - 後からAPIの仕様を知るには、実装を読み解く必要がある - 個々⼈のコードを読む⼒に⼤きく依存 - 今後、開発組織を更に拡⼤していくうえでの障壁になりかねない 課題 スキーマ駆動開発を実践すれば解決するのでは!
  6. - Buf Technologies, Inc. により開発 - gRPC互換のHTTP APIを実装するためのフレームワーク - HTTP/1.1で通信可能

    - Proxy不要でWeb Frontendから直接呼び出せる - gRPCと同じようにProtocol Buffersを⽤いてAPI定義 - Protobufのエコシステムが活かせる - 2024/4 CNCF Sandbox Projectに採択 - Go, TypeScript, Swift, Kotlinサポート - Swift, KotlinはClient対応のみ Connectとは
  7. 提供されているもの - Connect Client (主にAndroid App想定) - Protobuf MessageのSerializer ⾜りていないもの

    - Connect Server - Unary RequestをProtoc⽣成ClassへDeserialize - Unary ResponseをJSON Serializeして返却 Connect-Kotlin MessageのSerialize / Deserializeさえ扱うことができれば、 Ktor ServerでもConnect ProtocolのUnary Requestを受けられそう
  8. Connect-Ktor (https://github.com/ichizero/connect-ktor) - Ktor Content Negotiation Plugin向けのProtobuf Serializerを提供 - Accept

    / Content-Type Headersを元にRequest / Responseを処理 - ProtobufからKtorのRouting定義を⽣成するProtoc Pluginを提供 Connect-Ktor public interface ElizaServiceHandler { public suspend fun say(request: SayRequest, call: ApplicationCall): ResponseMessage<SayResponse> public object Procedures { @Resource("/connectrpc.eliza.v1.ElizaService/Say") public class Say } } public fun Route.elizaService(handler: ElizaServiceHandler) { post<ElizaServiceHandler.Procedures.Say, SayRequest>(handle(handler::say)) } object ElizaServiceHandlerImpl : ElizaServiceHandler { override suspend fun say(request: SayRequest, call: ApplicationCall): ResponseMessage<SayResponse> = ResponseMessage.Success( sayResponse { sentence = request.sentence }, emptyMap(), emptyMap()) } fun main() { embeddedServer(CIO, port = 8080) { install(Resources) routing { install(ContentNegotiation) { connectJson() } elizaService(ElizaServiceHandlerImpl) } }.start(wait = false) } ⽣成コード 実装コード
  9. - 既存のREST APIと共存可能 - スキーマ駆動開発の段階的な導⼊が可能 - 既存APIを置き換える際、APIテストがほぼそのまま再利⽤できる Connect-Ktorのメリット fun main()

    { embeddedServer(CIO, port = 8080) { install(Resources) routing { route(“/connect”) { install(ContentNegotiation) { connectJson() } elizaService(ElizaServiceHandlerImpl) // Using Connect Protocol } route(“”) { install(ContentNegotiation) { json() } post<ElizaSayResource> { … } // Using REST } } }.start(wait = false) }
  10. 品質⾯でのメリット Event Storming 設計 ⽣成コード API スキーマ Backend 実装 Frontend

    実装 - Frontend - Backend間のAPIスキーマのズレを防げる - バグやインシデントの可能性を低減 - Protocol Buffersによる安全なAPI定義 - 静的型付け - 前⽅互換性・後⽅互換性を保つための仕組み - 暗黙知を形式知に変えられる - 新規に参画したメンバーのキャッチアップコストの低減 - QAエンジニアのE2Eテスト設計に活⽤ 開発開始 デモ
  11. 品質⾯でのメリット - Request Validation実装の簡略化 - protovalidate (https://github.com/bufbuild/protovalidate) - ProtobufのCustom OptionsにValidationルールを書くだけで、

    Runtime Validationが⾏えるスグレモノ - Go, C#, Java, Python サポート ※ protobuf-es v2にてCustom Optionsが扱えるように。 TypeScriptがサポートされる⽇は近いのかも? syntax = "proto3"; import "buf/validate/validate.proto"; message User { // User's name, must be at least 1 character long. string name = 1 [(buf.validate.field).string.min_len = 1]; } 参考: https://github.com/bufbuild/protovalidate APIスキーマ定義するだけで、 Always-ValidなRequest / Responseが実現できる