はじめましての方ははじめまして、そうでない方はこんにちは。社内では「じぇっと」と呼ばれています。なぜそう呼ばれているかは追々お伝えできればいいかなと思います。
はじめに
Webサービスを運用していると、ユーザーからの問い合わせが事業側の担当者に届き、そこからエンジニアに作業依頼が回ってくる、ということがあるかと思います。退会したい、登録したメールアドレスを変更したい、アカウントが二重にできてしまったので統合したい。そして、その一部は最終的に、エンジニアが本番データベースを直接操作することなどで解決されます。
これは、当たり前のことなんでしょうか。
私はこれに「少し懐疑的で、あまりよくないかも」と感じつつ、なぜよくないのかをうまく説明できませんでした。「管理画面を作ればいい」と考えてみるものの、そこに何を載せるべきなのかが分からない。引っかかっていたのは、「CS対応」という言葉が、中身を定義されないまま使われていることだったように思います。この記事では、その言葉を分解してみます。
想定読者
- toC(一般消費者向け)サービスの設計・運用に関わっているエンジニア
- 会員基盤や管理機能をこれから作ろうとしている人
- 事業側からの作業依頼を、エンジニアが手で処理している現場にいる人
なお、実際に仕組みを作った報告ではなく、調べて考えたことの整理です。より深い実装の話は、記事末尾の参考文献をあたってみてください。
「CS対応」という言葉が指しているもの
さきほど並べた依頼には共通点があります。どれも、ユーザー本人がやろうと思えばやれるはずの操作です。 退会もメールアドレスの変更も、本来はマイページにある機能です。それが問い合わせとして飛んでくるのは、何らかの理由で本人が実行できなかったからです。
つまり、CS対応の実体はこう言い換えられます。
本人以外が、本人の代わりに、ドメイン操作を実行すること。
「困っている人を助ける」という行為の裏側で、システム的には実行主体のすり替えが起きている。そして主体がすり替わった瞬間に、本人が実行するときには自動的に満たされていた前提が、宙に浮きます。
CS対応を4つに分解する
本人が実行するときは、ログインしているから本人だと分かり(本人性)、自分のデータだから権限は自明で(権限)、画面のボタンからドメインロジックを通って実行され(実行経路)、誰が何をしたかを記録できます(記録)。代理実行では、この4つがすべて、別途担保しなければならない項目になります。
| 要素 | 代理実行で答えるべき問い |
|---|---|
| 本人性 | 誰の代わりに実行するのか。その確認は、実行された操作と結びついているのか |
| 権限 | その担当者は実行してよい人か。誰が承認したのか |
| 実行経路 | 本人が実行するときと同じロジックを通るのか |
| 記録 | 誰が、誰のデータを、なぜ、何に変えたのかが残るのか |
本番データベースを直接操作するとき、何を支払っているのか
この4つを物差しにして、冒頭の「エンジニアが直接操作する」ケースを見てみます。
先に答えを書くと、4つとも同じ形をしていました。本来はシステムが担保していたものを、人が肩代わりしている、という形です。
本人性。 本人であることを確かめた、という事実は残ります。ただしそれは、実行された操作とは別の場所に残ります。「この変更は正当だった」という証明を、記録ではなく、担当者とエンジニアのあいだのやりとりが引き受けている。
権限。 実行できるのは、その操作を任された人ではなく、データベースへの書き込み権限を持っている人です。「実行してよい人だけが実行する」を、仕組みではなく、個人の分別が引き受けている。
実行経路。 アプリケーションが「退会」と呼んでいるのは、状態をひとつ変えることだけではありません。関連データの扱い、外部連携の解除、完了通知、再登録の可否。それらをどうするかという定義を、ドメインロジックではなく、実行する人の知識が引き受けている。
記録。 何が変わったかは、あとからでも追えます。追えないのは「なぜそうしたか」です。データベースは業務上の意図を知らないので、そこを埋めるのは当事者の記憶になります。
つまり支払っているのは、人の手間です。
なぜ、そうなるのか
たぶん、優先度の問題です。限られた時間のなかでは、ユーザーが直接使う機能のほうが先に作られます。本人以外が同じことをする経路は、それに比べれば優先度が落ちる。その積み重ねとして、本人が実行する以外の道が実装にない、という状態になります。
厄介なのは、本人だけが実行できる形になっていると、本人が実行できなかった時点で、システムの中に打つ手がなくなることです。そして問い合わせは、まさにそこから来ます。だから対応は、実装の外側に落ちます。
見えない、という問題もあります。「本人が実行できずに止まっている」という状態がモデルに表現されていなければ、その一覧はどんな管理画面を作っても出せません。 問い合わせが来て初めて気づくことになります。
選べる打ち手と、その前提条件
「本番データベースを直接操作する」の反対側は「管理画面」だと思っていましたが、間にはいくつも選択肢がありました。さきほどの4つのうち、どれを機械に任せるかで整理すると、こう並びます。
- 承認付きの SQL 実行基盤 … 承認を通らないと実行できないようにする。書き込み権限はツール側が持ち、作業者個人には渡さない構成が取れます。権限と記録を機械に任せる打ち手で、既存の実装に手を入れずに導入できます
- 運用手順のコード化 … 手順書のコピペをやめてスクリプトにする。実行経路の再現性が上がり、レビューの対象が「これから実行される内容そのもの」になります
- 管理画面 … 4つすべてを任せられる可能性がありますが、前提条件がいちばん重い。表示したい情報がモデルにあること、ドメイン操作が画面から独立して呼べること
- ユーザー自身が解けるようにする … そもそも代理実行を発生させない。ただし利用者の幅が広いほど、「自力で解ける」という想定は外れます
どれを選ぶかは、頻度と危険度と、判断が要るかどうかで変わります。月に一度の依頼のために管理画面を作るのは割に合わないかもしれないし、毎日来る依頼を素手で処理し続けるのも割に合いません。
並べてみて気づいたことがあります。モデルに手を入れずに導入できる打ち手ほど、届く範囲が狭い。 承認付きの実行基盤は既存の実装のままで入りますが、担保できるのは権限と記録までです。4つすべてに手が届く管理画面は、そのぶん前提条件が重くなります。
つまり、どこまで肩代わりを減らせるかの上限を決めているのは、打ち手そのものではなく、その手前にある本体実装のモデルです。
おわりに
書きはじめたきっかけは、「エンジニアが本番データベースを直接操作しているのは、まずいのではないか」という引っかかりでした。
でも調べていくうちに、見方が変わりました。それは手を抜いた結果ではなく、むしろ逆だった、ということです。QCDなどを考えて、仕組みがないなら手で解決する。目の前の人に価値を届けようとした結果として、クエリが打たれている。ユーザーへの誠実さのほうが先にあるのではないかと思っています。
問題は、その誠実さが割に合わない形で支払われていることのほうでした。「ユーザーを助ける」という目的に対して、もっと簡単で、もっと確実な手段があるはずです。そしてその手段は上で挙げたように一つではなく、どれが正解かは一律には決まらないかと思います。大事なのは、本番DBへの操作も含めて、どの選択肢を選ぶのかを意識して選べる状態にしておくことだと思っています。
ただ、調べていて一つだけ、その選択の前提になっているものが見つかりました。
本実装に手を入れずに、あとから足せるのは機能であって、モデルではない。
管理画面は、モデルにある情報しか映せません。誰が実行したのかを受け取れない処理には、あとからそれを足すコストがすべてのユースケースぶん乗ります。そして、上書きして消してしまった事実は、あとから生えてきません。CS対応の質にどこまで手が届くかは、管理画面ではなく、その手前にある本体実装のモデリングが決めている。これが、調べてみて自分なりに得た結論です。
では具体的に何を決めておくべきなのかは、書きません。サービスごとに違いますし、私自身まだ答えを持っていないからです。代わりに、これから機能を実装するときに自分へ投げてみようと思っている質問を置いておきます。
- この操作は、本人以外が実行する場面があり得るか
- あるとしたら、そのときも同じドメインロジックを通るか
- 「誰が実行したか」を、この処理は受け取れるか
- この操作で状態が変わったとき、変わる前の事実は残るか
- ユーザーが自分で名乗れる識別子で、このユーザーを引けるか