Motivation
既存システム開発案件に参画して急遽、退会機能を実装しなければいけませんでした。ですが、その機会のおかげで様々な学びがありました。自分の力が及ばなかったところを反省し次に活かすための振り返りをしておこうと思ったのが動機です。
システムの観点
データの状態が表す意味は一意となるように
システムのデータ削除方針とし物理削除ではなく、論理削除を採用しました。FW は Laravel を使っていて、標準で削除機能を実装しているので簡単に導入することができました。
「退会機能」としてだけ見れば問題なかったのですが、考慮し忘れていたのは、ユーザーに紐づくデータの削除方針です。当初私が行なっていた実装としては、ユーザーが退会したときはそのユーザーに紐づく投稿データも一緒に削除するものでした。
ここに問題点がありました。将来的に投稿の削除機能が実装され、以下のフローをとる場合を考えてみます。削除フラグだけで管理する方法を採用してしまうと
- ユーザが自身の投稿を削除する(投稿の削除フラグを true に)
- ユーザーが退会する
- 投稿も論理削除される(投稿の削除フラグを true に)
となります。そしてユーザが利用再開するとします。利用再開したときにそれまでの投稿も再度表示される仕様となっている場合、削除フラグを false にしてあげる必要があるので、ユーザーが過去に削除した投稿も一緒に表示されてしまいます。
反省点としては、実装するときは将来的にどのような機能が実装されるか、仕様がどのように変わるかを確認できるなら確認しておくことです。
ユーザが意図的に削除したのか又は、ユーザが退会したことによって副次的に削除されたかをデータの状態から判別できるようにする必要があります。
また、フラグを多用しすぎると条件分岐が増えてしまい処理が複雑になってしまうので、status カラムを使用しデータの状態を表現させてあげることをお勧めします。
テーブルはなるべく共通化しない
例えば、顧客(clients)や管理者(admins)などを別テーブルで管理していた時、その時点でプロフィールの項目が同じだからといって一つのテーブル(profiles)に関連付けすると将来の仕様変更に耐えられなくなってしまいます。
仕様によって「顧客」「管理者」間の項目は変わってくる可能性があるので、別テーブルで管理することをまず考えます。
無駄な処理はなるべく実行しない
特定の状態の時に不必要な処理をしないようにしましょう。
早期リターンや break 文などで無駄な処理を省くことができます。
とはいえ、複雑化したコードだと、無駄を完全に省くことは難しいと思うので、パフォーマンスへの影響が大きい箇所のみで大丈夫だと思います。
APIから直接実行できないようにする
ユーザーの権限・役割によって、特定のアクションを禁止する / アクション実行ボタンやリンクを非常時にする / フォームを無効化するなどはよくある実装だと思います。
ブラウザ側の操作ではそれで目的を達成できますが、API に対して直接リクエストされてしまうケースを考慮して、フロント側だけでなく、バックエンド側にバリデーションを実装することを忘れないようにしましょう。
SQL の実行計画を見ること
必要なデータを DB から取得する際は SQL を書くかと思いますが、ちょっとした記述の違いによって実行計画が大きく変わってしまい、処理量がかなり変わってくることがあるので、なるべく処理が重くならないような SQL を書くことを心がけましょう。
条件を肯定文で書く
メソッド名やフラグを名などに否定系をあまり多用しすぎると、理解に時間がかかってしまうので、肯定文で書くことを心がけましょう。
コミュニケーション編
仕様に関する質問は徹底する
既存システムの案件に新たに参画した場合は、コードだけでは、それが意図することや、背景を完全に読み取れない時が多々あります。また、ドキュメントが完備されてない現場も往々にしてあります。
その時は、シンプルに前任者、または、チームメンバーに聞きましょう。聞かないで自分なりの解釈で進んでいくことのほうが危険です。
曖昧な言葉を使わない
お互いの認識の齟齬に気がつかないまま開発が進んでいくと、あとで大事になりかねません。そんな事態にならないためにも「相手が何を意図しているか」「認識は合っているか」を頻繁に擦り合わせる必要があります。
会話に厳密性を求めることは、人によっては「しつこい」と思われてしまうかもしれませんが、曖昧な状態で進んでいくことのほうがより危険です。