技術設計でのプレモーテムでプロダクトもチームもレベルアップさせる
こんにちは、ダイニーの Feature team でソフトウェアエンジニアをしている @ta21cos です。
最近は新規事業である決済関連の機能開発を担当しています。
今回は決済に関連する機能開発を題材に、弊社のエンジニアリングチームで技術設計時に行っている「プレモーテム」について紹介したいと思います。
プレモーテムとは
「プレモーテム」という言葉で検索するとプロジェクトマネジメントの単語が出てきます。意味としてそのうちの一つを引用します。
プロジェクトチームはプロジェクトの終わりを見据え、失敗した場合を想定します。失敗から逆算して考えることで、チームはプロジェクトのリスク、またプロジェクトが進む中でそういったリスクを回避する方法について理解を深めることができます。(https://asana.com/ja/resources/premortem)
今回はこれを技術設計の文脈で利用し、次のような意味として扱います。
「その設計におけるリスクを洗い出すことで、設計の問題点を見つけ出し改善を行うか、その対策を考える」
インシデントが発生したときにその原因を振り返る「ポストモーテム」が行われますが、その逆の言葉として「プレモーテム」と呼んでいます。これにより、設計段階でリスクを把握し、対策を打つことが可能になります。
ダイニーのエンジニアリングチームでは、このプレモーテムを「設計レビュー」の一環として取り入れ、実装中・後の手戻りを減らし、問題が起きたときの対応をチームで共有・同意できるようにしています。
モバイル決済での事例
今回例にするモバイル決済とは、ダイニーのモバイルオーダー上で食事の会計を済ませることができるサービスです。
サービスの特性を理解する
プレモーテムではまずサービスの特性を理解することが重要です。
ダイニーでは飲食店の運用のコアを担うモバイルオーダー、レジ、ハンディ etc. の安定性を高めるため、決済サービスはサーバを分けて運用しています。
加えて決済部分は決済代行サービス(PSP)を連携をしているため結果的に
- POS サーバ
- 決済サーバ
- 外部決済サービス
という複数システム間の連携が必要になります。
いわゆる分散システムとなっているので、これらが持つデータが矛盾を起こさないようにすることが求められます。
(↓システム間の通信のイメージ図)
起こり得るケースを考える
「もし、決済リクエストが途中でタイムアウトしたらどうなる?」
「複数端末から同時にリクエストがあったら?」
こうした「起こりうるパターン」を洗い出していき、整合性が崩れないか、またはオペレーションによって回復可能かなどを考えていきます。
あらゆるパターンを想定し、設計を練り直し、レビューを受け、また修正…と地道なサイクルを回します。
この記事では具体的な課題とそれをどう技術的に解決するか(または何を諦めるか)については深堀りしません。こちらはいつか記事にできたらと思っています。
モバイル決済は「決済」なので、重要なのは「二重決済を防ぐこと」と「実は決済できていなかった」を防ぐことです。
それが起こる状況と、その解決策を考えていきます。
ここで実際のプレモーテムを載せたかったのですが、積極的に外に出せない情報も含んでおり加工が大変でした…。そのかわりに、特に私を悩ませたコメントを次に挙げます。
- いずれかのサーバでタイムアウトが発生したケース
- 決済リクエストが成功したのか失敗したのかどうかがわからない
- 複数の端末から同時にリクエストが来たケース
- 二重決済にはならないか?
- 処理中に Google Cloud のインスタンスが落ちたケース
- 処理途中で何らかの理由で止まってしまってもリトライにより復旧可能か?
- 冪等になっているかの確認
- 二重決済を防ぐために、またタイムアウト時にリトライをできるように冪等性を持つように設計した。本当にすべてのケースで冪等になっているか?
プレモーテムを通じて、これらの「もしも」を事前に想定することで、対策や設計上の検討ポイントを明確にし、実際の実装フェーズで余計な迷いを減らすことができました。
良かったこと
このアプローチを取り入れることで、いくつかの恩恵がありました。
チーム
- ロジックに集中できる
- コードレビューも重要ですが、実装の方法とロジックがどうしても混ざってしまいます。文章として書くことで、リスクに集中した設計およびレビューが行えます。
- チームで見れる
- ダイニーではコードレビューはコードオーナーが行いますが、設計書はそれに限らずレビューを行うようにしています。これにより直接関わらないメンバーも交えて、チーム全体で潜在的な問題点を洗い出せます。
- 運用目線も観点になる
- モバイル決済の設計では、実装難易度・コストが非常に大きいという理由で、いくつかのケースにおいては手作業での対応を許容しています。こういった運用作業はコードには現れませんが、設計書であればこの対応方針についてもレビューが行えます。
- (このあたりの意思決定については同僚である kadota の記事 もぜひご覧ください!)
個人
- コードを書くときにリスクへの感度が高まる
- プレモーテムを一度経験した結果、普段書いているコードでもそれに潜むリスクに対して敏感になったと感じます。設計力だけでなく、実装力も上がった実感があります。
おわりに
この時設計しリリースしたモバイル決済は、1年以上大きな問題なく稼働しています。
フロントエンド出身の私にとって、バックエンドのシステム設計におけるリスクの評価は大きな学びになりました。
ダイニーでは、重要な開発を行う前には設計書を書くという文化があり、その1ステップであるプレモーテムによって、考慮漏れを防ぐ努力がされています。
特に決済関連の機能は、少しの不備がユーザーへの印象に大きく影響します。だからこそ、個人、チーム全体でプレモーテム的なアプローチを浸透させ、設計段階で抜け漏れやリスクを潰していくことが大事です。
その積み重ねにより、より良いプロダクトとエンジニアとしての確かなレベルアップをもたらしてくれると感じています。
ダイニーでは新規メンバーを募集しています。プレモーテムを積極的に行っているチームで働くことに興味がある方は、ぜひ一度お話しましょう。
Discussion