一度立ち止まって自分の仕事は何だっけと考えるのが大事

とあるプロジェクトを始めたとき、まずは設計してから手を動かそうということで設計を考えていた。

DB設計を考えて、ユーザーが取りうる行動を列挙してそれぞれの行動に対して問題なく動くかどうかをプロトタイピングしてから進めようとしていた。

が、ここがこういう設計になっているとここに影響があるな… と頭を悩ませていて、あまり進みはよくなかった。

そんなとき本来のプロジェクトのスコープから外れたところまでも考えてしまっているのではという指摘を受けた。 そして、まずは変わらないところを決めてしまって、ここは後回しでもいいというふうに考えることを減らしていくと進めやすいというアドバイスを頂いた。

たしかにデバッグのときもどこまでは動いているのかを確定させてから調べるほうが確実だし早い。

ということで、自分のプロジェクトではどこまで何をやりたいんだっけということを再度考え直して確実なところから進めていこうと思う。

Xiaomi Smart Band 7 買った

前までは Garmin の vivosmart4 というスマートバンドを使っていたけどバンドが切れてしまって半年間何も付けずに暮らしていた。 vivosmart4 は body battery という自分の体力を数値化してくれる機能が面白かったけど替えのバンドが市販されてなくて困っていた。

何も付けずに暮らして困ってなかったけどある日突然めちゃくちゃスマートバンドが欲しくなってその日のうちに Xiaomi Smart Band 7 を買った。

付けて1週間ぐらい経つけど、とても7000円とは思えないというのが素直な感想。

良いポイントを列挙していく。悪いポイントは今のところ無い!!

  • 画面が綺麗
    • vivosmart4 が素朴だったというのもあるけど Smart Band 7 は普通のスマホと同じくらいきれいなディスプレイで見るたびにびっくりする
  • アプリが使いやすい
    • 直感的に扱えるしレスポンスがキビキビしている
  • 細かい設定ができる
    • ホーム画面で長押しすると watch face を変えられるのがデフォルトになっているけどこれがよく誤作動して困っていた。この機能は設定からオフにすることができて助かった
  • 振動のアラーム便利
    • 米を炊き忘れがちなので指定した時刻に振動するようにしたら炊き忘れが減った

なるべく小さいほうが普段の生活の邪魔にならないだろうと考えているので実は初め Smart Band 7 ではなく Smart Band 6 を買おうとしていた。 Smart Band 7 は 6 と比べて表示領域が 25% 増えているそうなのでその分サイズが大きくなったのだろうと推測していたから。

でもよく調べると実は、高さ(=腕の横幅方向)は 6 が 47.4mm に対して 7 は 46.5mm と何と縮んでいる! 幅(=腕の縦幅方向)は当然長くなっているけど普段困るのは高さが長くなることなので Smart Band 7 を買うことにした。

この判断は正しかったのか邪魔だと感じたことはないし、付けていることを忘れるぐらい一体化してきている。

データ移行プロジェクトで得た学び

ここ1ヶ月半ほどとあるデータ移行プロジェクトに携わっていた。

データ移行プロジェクトは初めてで難しかったがなんとか一段落することができたので、今回のデータ移行のむずかしポイントと乗り越えるためにやったことを記録しておく。

何をやったか

とある別サービス  S _ {origin} で定期課金中のユーザー数万人を自社のサービス  S _ {dest} に移行してきて課金状態を引き継ぐというのがプロジェクトのゴールだった。

つまり、 S _ {origin} を利用しているユーザーは何も操作しなくても移行日以降に  S _ {dest} でログインすると定期課金状態になっていることを目指している。

むずかしポイント

  • 課金状態を引き継ぐために移行時に課金をする必要があり、失敗するとユーザーに不利益が生じる
  • 初めて触るところ & 移行プロジェクトが初めて

むずかしポイントを乗り越えるために

課金状態を引き継ぐために移行時に課金をする必要があり、失敗するとユーザーに不利益が生じる

課金という性質上、同じユーザーに対する移行の二重実行を避ける必要がある。 さらに、移行後にユーザーからのお問い合わせで調査が必要になるかもしれない。

そこで、移行用の一時テーブルを用意することにした。 移行の処理をステップごとに分けて、ステップごとに成功 or 失敗を記録していき、ステップごとに埋めたいデータをテーブルに持つようにした。

そして、二重実行を避けるために状態遷移図に従うような処理しかできないように制御した。

状態遷移図

今回はお問い合わせを見越して各ステップごとのログが重要となると考えたので更新していくのではなくて追記していく方式にした。

また、エラーによってはリトライすれば治るもの(通信時エラーなど)もあればリトライしても治らないもの(クレジットカードの有効期限切れなど)がある。 そこで、エラーコードを細かく分けて記録することで調査をしやすくしたり、治る見込みのあるものだけをリトライできるようにした。

移行テーブルを作っておくことで並列処理がしやすくなるというメリットもあった。 あるユーザーが複数の定期課金をしていた場合に同時に移行されると想定しない問題が発生する可能性があった。 移行自体はユーザーと定期課金の商品の組み合わせごとに行うので、移行テーブルでユーザー単位でロックを取ることで1ユーザーの複数の定期課金が同時に移行されることを防ぎながら並列処理が可能になった。

エラーに倒れるようにするほうがいい。 本来エラーになるべきデータが正常に移行されるのは困る。 バリデーションを頑張る & 意図した条件でなければエラー とすることでエラーに倒すことはできる。 移行当日にエラーに対処することにはなるが異常なデータが移行されるよりはまし、ということで頑張る。

テストはやっぱり重要。 データ移行に限った話ではないけど1回きりのスクリプトだからといってテストなしだったらきっと破滅していた。 今回は特に課金ということもあって検証できる機会が少なかったので、その分テストでエッジケースをしっかり確認できたのは良かったと思う。

関係者の少ない検証環境もあるとよい。 関係者が少ないとデプロイしないでとか操作しないでとお願いすることができる。 今回はこの環境を使ってさらに安全目には倒しながら一時的に検証環境から課金サービスの本番につなげることで検証を行った。

初めて触るところ & 移行プロジェクトが初めて

今回のプロジェクトに携わるまで課金周りを触ったことがなかったのと移行プロジェクト自体が初めてだった。

当初のアサインではこの移行プロジェクトと別のプロジェクトを並行して進めるということになっていたが、明らかに厳しくてこういう状況で困っていますとか慣れていないので不安ですというエントリを社内に書いていたら移行プロジェクトの専任にさせてもらえて、ヘルプの体制を組んでもらえた。 このとき声を上げていなかったらプロジェクト後半で破滅していたかもしれない。

プロジェクトを進めるにあたってはとにかく記録を残していった。 やろうとしていること、やったこと、困っていることを記録していると相談もしやすいので便利。

タスク管理はちゃんとしたほうがいい。 ちゃんとするというのは、タスクの期日を入れて見積もりポイントを振って依存関係をつけるということ。 見積もりポイントが入っていたらバーンアップチャートが見れるので今のベロシティでは間に合わないので助けてください! と説得材料になる。 依存関係をつけているとこのタスクは依存がないので別の人にお願いできるなとか判断しやすくなる。

手順書は作ったほうがいい。 特に深夜作業なら頭が働かない前提で手順書は書いたほうがいい。 つまり、何をやるのか・期待される結果は何なのか・このエラーの場合にはどう対処するか を手順に盛り込む。 やることと期待される結果はペアで書いたほうが手順書としては見やすくなるのでオススメ。

事前に移行作業のタイムラインを考えて問題ないかを脳内シミュレーションするといい。 理想的には何時に終わるのか、エラー対処などを含めて落ち着けるようになるのは何時かなどを考える。 移行プロジェクトは関係者が多いはずなので、各関係者に必要な確認が漏れていないかを確認するのが重要。

dry run は実装したほうがいい。 コマンドを実行する前に何件実行されるのかを出すぐらいでも事故は防ぎやすくなると思う。

振り返り

移行プロジェクトは3人以上は必要

移行プロジェクトは別サービスを運用している会社などとの連携が必要になり関係者は自社に閉じている場合と比較して多くなる。 なので関係者とのコミュニケーションや仕様のすり合わせなどを行う人が1人は必要になる。

となると実装するエンジニアの人数は? となるけど2人以上じゃないと難しいんじゃないかと思う。 別サービスで運用されていたデータを自社のサービスに持ってくるのは特殊な対応が必要になることが多く、エッジケースが多い。 1人でエッジケースを全部カバーするのは自社のサービスを完全理解していないと難しい。 また特殊な対応をするために工数はどんどん増えていくので1人じゃ捌ききれなくなってくると実感した。