こんにちは。AnyLogでTechLeadを務めているShao Hongです。この記事では、先日リリースさせていただいたAnyLogiについて技術的な観点からご紹介出来ればと思います。
Anylogiについて
AnyLogiはD2Cビジネスを支える物流管理プラットフォームです。 主な特徴としては、海外の物流パートナーと連携することで、D2C及びEC事業者の越境展開をサポートしていることです。 複数拠点のECプラットフォームや倉庫管理システム(warehouse management systems: WMS)と連携することで、どの企業も、AnyLogiがサポートする地域で商品を扱うことが出来るようになります。
全体設計
ECプラットフォームと倉庫管理システムの仲介役になるのは簡単なことではありません。
適切なドメインとビジネスの境界がないと、不要な実装詳細があるコンポーネントから別のコンポーネントに漏れることになります。 したがって一般的な考え方として、それぞれのコンポーネントを独自のものとして扱い、同じコードベース内で異なるコンポーネントを混在させないことです。 これにより、次の図のようにAnyLogiのコアドメインと、それらを束ねてシステムとして外界とやりとりするコンポーネントとの間の境界と関係性を明示できます。
技術スタック
System architecture
フロントエンドとバックエンドがお互いに干渉されるのを防ぐために、開発の早い段階でAPIゲートウェイを使用することを選択しました。 APIゲートウェイを緩衝材として使用することで、フロントエンドは利用するスキーマを自由に設計する権限を持ち、バックエンドも同様にスキーマを自由に生成する権限を持ちます。 これにより、両方のチームが使用するテクノロジーも切り離せます。
Languages and frameworks
Front-end、Back-endそれぞれで、ビジネス要件にあった技術スタックを自由に組み合わせています。
- Front-end
- Typescript
- Angular
- Typescript
- Back-end
- Go
- Echo
- NodeJS
- NestJS
- KoaJS
- Go
ここで取り上げた言語以外にも、より安定し、よりスケーラブルなシステムを作るのに役立ちそうであれば、積極的に新しい言語を取り入れることも検討しています。(Java, Elixir, Rust, など)
Event driven architecture
AnyLogiは多くのデータソースから、それぞれで異なる粒度、頻度でデータを取得しています。 そのため、我々はEvent driven architectureを採用し、システムのどの部分もスケール可能でボトルネックにならないようにしました。
Event driven architectureを導入したため、システムのコアロジックには同様にEvent sourcingを導入しています。 Event sourcingは一種のデータ状態管理手法であり、とあるデータがその存続期間を通じて異なる状態を持つ可能性がある場合に最も役立ちます。
注文のライフサイクルの例
ORDER_CREATED
ORDER_UPDATED
ORDER_ACCEPTED
ORDER_PAID
ORDER_DELIVERY_INITIATED
ORDER_DELIVERED
Event sourcingは、従来のドメインオブジェクトまたはエンティティではなく、イベント自体を信頼できる情報源としてフォーカスします。 イベントを辿っていくことで、通常のアプリケーションでのユースケースで使われるドメインオブジェクト/エンティティ(集約)のコピーを作成できます。 これは、状態変化の扱いが重要であるようなドメインに大きなメリットをもたらします。
Command Query Responsibility Separation (CQRS)
Event sourcingの欠点の1つは、クエリの実行にすぐに使用できるデータベーススキーマがないことです。 Event sourcingの性質上、すべてのクエリでイベントからオブジェクトを再生すると、場合によっては長期間・多くのイベントを集約する必要があり、優れたアイデアではありません。 もしページネーションが必要な場合、フロントエンドに数行を表示するためだけにイベントストア全体を再生する必要が出てくるため、さらにパフォーマンスが悪化します。
イベントソーシングと共にCQRSを導入することで、クエリ用のビューを生成出来ます。 新しいイベントがイベントストアに追加されると、ワーカーはそれを取得して、対応するビューを更新します。
ビジネス要件に対する挑戦
数年後にシステムがどのように進化していくかを把握せずにシステムを開発することは困難です。 さまざまなECプラットフォームや倉庫管理システムは、それぞれ独自のドメインロジックやワークフローを持ち、しばしば互いに矛盾する可能性があります。 我々のビジネスロジックは、統合する最初のいくつかのシステムのロジックに簡単に影響を受ける可能性があり、彼らの長所と短所も短所もAnyLogiに受け継がれてしまいます。 彼らのシステムに影響を受けつつ開発することは、短期的な観点からはAnyLogiの開発を早く進めることが出来るため有益ですが、将来的には既存のビジネスフローによって、スケールさせにくかったり、機能追加しにくくなるといったダメージを負う可能性があります。
したがって、連携するシステムのビジネスロジックに適応させる前に、他のシステムと異なる点を徹底的に評価する必要があります。 これは将来のために今のうちから準備をしておくということで、これによって、長期的には他システムをどんどん連携していってもAnyLogi内のロジックは安定して動き続けられるようになります。 またDDDの観点からは、AnyLogi内では一貫したドメインロジックが組まれるため、知識の伝達とオンボーディングが容易になります。
一つ具体的な例を上げましょう。ステータスフラグについてです。 これはデファクトスタンダードと言えるような基準がなく、各システムで独自に管理されています。 我々は開発中に、とある外部システムが7つの異なる変数を使用して注文のステータスを管理していて50を超える可能な組み合わせがあることに気付きました。 AnyLogi内でも同じようなステータス管理を採用すると、他システムとの連携時にステータスを変換することは困難になりますし、さまざまな組み合わせの全てにおいてドメインロジックを組むことになり理解するのも困難です。 この問題に対処するためにAnyLogi内でのロジックを見直した結果、2つの異なる変数のみを含む単純化されたバージョンのステータスで管理出来ることを見出し、組み合わせを11に減らしました。 これによって、新しく連携するシステムのステータスがどれほど異なっていても、このステータスにマッピングすることで各システムの差異を最小限に抑えることが出来ます。
(※この例については、外部システムが不必要に多くのステータスを扱っているというわけではなく、「AnyLogiのユースケースにおいては省略して良いステータスがあった」という形です。)
まとめ
指数関数的に成長していくことが予想されるシステムを新規に開発する際には、後から容易にスケール・機能拡張出来るように始めから基礎をしっかり整えることが必要です。 また、プロダクトの長期戦略に重点を置き、MVPを急いで作ることとのバランスを取ることも考慮することも大切です。
この記事が、既存の市場や未開拓の市場に関係なく、新プロダクトを始めようとしているすべての人に役立つことを願っています。
Thank you for reading. (訳:柴田)
AnyMindでは引き続き新プロダクトの立ち上げや、ビジネス要件に合わせた柔軟な技術選択を行っていきます。 AnyMindの開発に興味を持って頂けた方は、こちらのページから「Product Development」を選択して募集職種をご覧ください。
https://anymindgroup.com/career/
また、こちらはAnyMindのエンジニア達が書いているブログです。よろしければこちらもご覧ください。