見出し画像

Funds というサービスの開発を続けて感じる、持続可能な開発に必要なこと

この記事は Funds Advent Calendar 2021 14日目の記事です!🎄

ファンズ株式会社 CTO の若松と申します。弊社のアドベントカレンダーではみんな楽しそうな記事を書いている中、なんだか文字ばかりの無味乾燥な記事を書いており「あれ?もしかして空気読めてない…??」と感じています。。

リアルではもっと気さくな人間のつもりなので(?)、もし少しでも関心持っていただけそうであれば、あるいはただ雑談してみたい人も、ぜひカジュアル面談リクエストしていただけるとうれしいです! 

前置きはこのくらいにして…今回の話です。

最近は自分で開発をすることはあまりないのですが、もともとローンチ時のシステムの設計や実装を主導的に進めていたことも踏まえ、ローンチ時の設計指針とそこからの反省などを綴っていきたいと思います。

2017年の設計時に考えていた、持続可能性のあるシステム

もともと Funds の開発以前にも、自分自身が中心となって新規のシステムを開発したことも、先行して開発されていたシステムの運用を引き継ぐ経験もありました。

こうした中、いかに技術的負債を残さず運用しやすいシステム・メンテナンスしやすいシステムにできるかは、その八割方がアーキテクチャなど開発初期段階における技術選定や設計により決まると感じてきました。

そのため、スピードを重視するスタートアップの開発であっても、初期段階のアーキテクチャや技術選定は決定的に重要だと考えていました。 

開発当時のシステム要件

開発を始める当時、具体的な機能以外でシステムとして必要だと考えていた要件は、次のようなものでした(以下は当時の社内ドキュメントからそのまま引用しました)。

  • スケジュール通りのプロダクトリリースができること

  • 安定して運用できること

  • システムとして3年〜5年は継続的に運用可能なこと

    • リリース後も継続的な機能改善が可能なこと

    • パフォーマンスにおいても見込みの使用想定で劣化が生じないこと

技術選定の方針

上記のシステム要件のうえで、具体的な How として採用した主な方針は、次のような方針です。

  • 少なくともコアな機能においては、強力な型システムを持つ静的型付け言語を採用すること

  • 問題を予測しやすい、ある程度自分達の利用経験や実績のある技術を採用すること

  • Twelve-Factor App などの設計方針や、クリーンアーキテクチャなど変更可能性のあるアーキテクチャを採用すること

  • IaC や CI/CD Pipeline などはできるだけ初期段階から整備すること

解決するべき課題や選択肢によっては、必ずしも自分達のチームにおいて造詣やノウハウがないものもありました。そのようなケースでは、すでに同種の技術を使われている方に話を聞いたり、環境構築を手伝っていただくなども含めて整備をしていきました。

主な技術スタック

こうした中で結果的に使用していた(使用している)のは、以下のような技術スタックです。

  • フロントエンド: React, Redux, redux-saga, Webix

  • バックエンド: Scala + Play Framework

  • インフラ: AWS, Terraform

    • 当初は AWS EC2 (Packer + Ansible で AMI 構築) + ASG という構成を取っていましたが、 EKS (Kuberenetes) ベースの運用に切り替えました(詳しくは EC2からEKSにシステムを載せ替えしている話 をご参照ください。なお現在は載せ替えも全て完了しています)。

当時とは変更されているものもありますし、フロントエンドなど現在リプレイスを進めている点もありますが、やはり一度プロダクションリリースされたアプリケーションを書き換えるというのはかなりの投資が必要で、あらためて初期段階での技術選定や設計の重要性を感じます。

4年ほど経過して感じること

さて、 Funds の開発自体は2017年末頃から始めており、ローンチまでの開発期間も含めると、現在までおおよそ4年に渡り開発・運用を進めています。

そのような中で、やはり想定が甘かったなぁ…という点もいろいろとあり、個人的に感じている反省点をいくつか述べてみたいと思います。

正しいドメインモデルの理解は難しい

Funds というサービスは、資産運用をしたい個人と資金調達をしたい企業を結ぶマーケットプレイスで、これは創業当初からの既定路線です。

一方で、スタートアップとしてサービスの成長を目指す上では、ローンチ当初は想定していなかったような商品を取り扱えるようにすることが必要となった場面もあります。

事業の要請を受けてシステムを変更する中で、これまで理解していたドメインモデルが、金融や法律上の本来の概念に照らし合わせれば表現できるべきモデルのうち、実はその一部しか表現することのできないモデルであったことに気づいたこともありました。

たとえば、金融という事業の性質上、金融商品取引法をはじめとする法令に基づき運営する必要があり、各種帳簿類の整備も必要になります。各帳簿類において記載しなければならない項目は決まっているので、それ自体は記述すべきルールさえ分かれば実装すること自体は可能です。

ただこうした帳簿の記録は、会計の知識があれば、より汎用性のあるモデルで取り扱うことが可能であると後から気づき、ドメインについての知識をより正確に理解できていればなぁ…と感じています。

冪等性を徹底することがリカバリーを楽にする

一般的に、バッチ処理は冪等性をもたせるべきだと言われます。その通りなのですが、冪等性を担保するための絶対的な方法はなく、すべての処理における冪等性を保証するというのは、実は意外と難しいことだと感じています。

Funds のバッチ処理は、 MQ にメッセージを追加すると、自前で構成した worker が MQ からメッセージを適宜取得し、逐次処理する分散タスクキューのような機構で動作しています。

そのため MQ に必要なメッセージをリクエストすることさえできればバッチ処理の再実行は可能なものの、その際に冪等性が担保されていないと思わぬ結果を生み出す可能性があり、途端にリカバリーが難しくなります。

冪等性がなくてもシステムが正常に動作している限りは問題がないため、冪等性を徹底することは漏れてしまうこともあります。他方でいざトラブルが生じると冪等性がないことで注意深くリカバリーを進める必要が出てくるため、リカバリーの難易度には雲泥の差があります。

持続可能な開発には優れた開発体験が必須である

ここ数年、開発体験(DX)の重要さが叫ばれるようになったと感じています(正確には、こうした概念自体はあったように感じますが、開発体験というワードが登場したのは2010年代後半のように記憶しています。)

開発体験は重要ではあるものの、サービスの信頼性や可用性などシステム自体の特性に比べ、本質的に重要とまでは考えていませんでした。

しかし現在では、開発体験の良し悪しというのは、特に組織としてシステムを維持・改善していく上では決定的に重要な要素と考えを改めました。

一旦開発すれば終わり、というライブラリやシステム、アプリケーションであればいざしらず、現実にはそうした性質のアプリケーションは、クローズになるプロダクトなどを除きまずないのが現実です。

そのような中で、属人性をもつ要素ができる限り排除されており、その言語に関する知見や周辺技術への知識を持っていさえすれば苦労せずに開発を進めることができるかどうかは、開発自体をスケールさせるうえで、とても重要な要素だと感じています。

メインストリームとなる技術を選ぶことの重要性

メインストリームとなる技術を採用することは、エコシステムの厚さによってライブラリの選択肢が多い、トラブルに遭遇した際の問題を見つけやすいなど、単に多数派という以上の価値があると考えています。

ただし、メインストリームとなる技術を正しく予想するのは難しいことでもあります。

たとえば、 Funds の投資家向けサービスサイトでは、 React とともに Flow を使用しています。個人的な見識の範囲ですが、 2017年頃であれば、 Flow を使うというのも選択肢に入っていたと思うのですが、 2018年には React でも TypeScript を使うことがスタンダードとなっており、 Flow は完全に蚊帳の外となってしまった印象です。

レガシーな技術スタックでは、開発体験があまり望ましくないことが多く、仮にスキルや経験のあるエンジニアであっても成果を出しづらくなります。またそもそも開発に携わってもらえるエンジニアを採用しづらくなる、という課題もあります。

チームの規模拡大を見越したアーキテクチャの進化が必要

Funds のシステムは大きく分けてバックエンド・投資家向けサービスサイト・社内向けのオペレーション画面という形で分離されています。

レイヤーごとのアプリケーションは分割しつつも、各アプリケーション、特にバックエンドのアプリケーションにおいてはモノリシックなアーキテクチャを採用しています。

Funds の開発チームは開発当初より2年ほどは3名のみだったのもあり、少人数においては、サービスが疎結合であることによるメリットよりも、変更可能性はクリーンアーキテクチャのようなアーキテクチャパターンにより保ちつつ、凝集的であることのほうが開発効率の面で有利と考えたことがこの背景です。

他方でチームの開発体制が変わると、その体制を維持することが有利であるとは限りません。少人数のチームにおいてモノリシックを選択することは間違いではなかったと思っているのですが、少人数を前提としたアーキテクチャは、開発に関わるエンジニアが増えるに従い、開発のスケーラビリティを阻害します。

一方でマイクロサービスを選択するとサービス間の整合性などの課題もあり、モノリスに課題があるからと言って、マイクロサービスを安易に選択するべきではないと考えています。また必ずしもモノリスにはまったく開発上のスケーラビリティがないというわけではなく、モジュラモノリスのような中間的な選択肢もあります。

とはいえ開発体験を重視しようとしたときに、当初のアーキテクチャが開発体制的な側面からも課題が生じるのは避けられないと感じています。特に初期から大規模な開発チームでの開発を前提とはできないスタートアップの開発においては、プロダクトやサービスが成長し、チームの規模拡大を迎えるどこかのタイミングで、開発体制に応じたアーキテクチャの変更が必要なのだろうと感じています。

まとめ

こうしてつらつら書いていると、システムとは人間が設計・開発するものであり、アーキテクチャとそれを開発する体制は、切っても切り離せない課題だなぁと感じます。

まだまだ課題のあるファンズではありますが、別の言い方をすれば、課題を解決することに取り組むチャンスのある環境です。今後もさまざまな 遭遇することはあるだろうと思っていますが、そうした課題解決へも一緒に取り組んでいただける方を募集しております。

現在 Funds で募集しているポジションは以下のとおりです。

また繰り返しになりますが、ぜひ少しでも興味のある方は一度お話させていただけると嬉しいです! Meety でこちらからご応募ください!

それではまた、明日以降の Funds のアドベントカレンダー の記事をお楽しみに!

この記事が気に入ったらサポートをしてみませんか?