「日」を定義するものとは?
プログラマーは、新機能の開発時にしばしば的外れなことに集中してしまいます。
バックエンドのデータ、コードの重複、あるいはパフォーマンスについて考えるかもしれません。これらは重要な問いですが、最も重要な問いではありません。
私もよくこの間違いを犯します。スマートなパターンやクリーンなコードに夢中になり、ユーザーがその機能をどのように使うのかを十分に理解する前にコーディングを始めてしまうのです。そして、自分の書いたコードがビジネスゴールと一致していないことに気づきます。
カレンダーアプリを例に挙げてみましょう。
ユーザーが祝日を記録するために3月1日をクリックします。しかし、アプリは代わりに2月28日を記録してしまいます。これはタイムゾーンが原因で起こります。
開発者は Date オブジェクトを使用しました。Date オブジェクトは、特定の時点を表します。
東京で3月1日の午前0時は、ロンドンではまだ2月28日です。日付を保存するためにコードがUTCメソッドを使用していると、日付がずれてしまいます。
このバグが発生するのは、技術的な実装がビジネスロジックと矛盾しているからです。
ユーザーは「日」単位で考えます。ユーザーはUTCオフセットやミリ秒単位のタイムスタンプで考えることはありません。彼らが考えるのは、「3月14日にしたい」ということです。
コードの信頼性を高めたいのであれば、ドメインを正しくモデル化しなければなりません。
紙のカレンダーにおいて、日付とは単に「年」「月」「日」です。そこにはタイムゾーンは存在しません。
UTCまたはローカルタイムで一貫性を持たせることでバグを修正することはできます。しかし、それは一時しのぎに過ぎません。より良い方法は、失敗し得ないデータ構造を使用することです。
Date オブジェクトの代わりに、カスタムオブジェクトを使用します:
• 年: 2026 • 月: 3月 • 日: 1
これにより、時間とタイムゾーンが計算から除外されます。その結果、バグの発生を不可能にします。
ええ、これにはより多くの手間がかかります。日付を比較したり、月末を求めたりするためのユーティリティを書かなければなりません。締め切りやスプリントのことも気になりますよね。
しかし、ドメインを正しくモデル化しておくことで、後になって怒りのサポートチケットに悩まされたり、何時間もデバッグに費やしたりすることを防ぐことができます。
エリック・エヴァンスが『ドメイン駆動設計』で述べているように:
「効果的にコミュニケーションをとるためには、コードは要件を記述するために使用されるのと同じ言語に基づいたものでなければならない。」
プログラマーとしてだけ考えるのをやめましょう。ビジネスルールについて考え始めてください。
