あなたが定義しているクラスは、値のランダムなグラブバッグのように見え、明確に定義されたクラスのようには見えません。これらすべての値は、実際には何を表しているのでしょうか?
public string StartYear;
public string EndYear;
public string Year;
public DateTime StartDate;
public DateTime EndDate;
public string StartMonth;
public string EndMonth;
public DateTime StartDay;
public DateTime EndDay;
たとえば、 と の違いは何StartDate
ですかStartDay
? StartYear
ととは何StartMonth
ですか? このクラスは実際に何を定義していますか? DateTime
値をコンポーネントに分割しようとしているようです。その必要はありません。必要な情報は単純なDateTime
値で十分に格納され、その値からコンポーネントを直接取得できます。
public DateTime StartDate;
public DateTime EndDate;
たとえば、月を知る必要がある場合は、その値から取得できます。
myObject.StartDate.Month;
クラスを改善し続けるには、パブリック メンバーの代わりにプロパティを使用する必要があります。C# では、これらは次のようになります。
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
これらは特に自動実装プロパティと呼ばれます。これらは、完全なプロパティのコンパイラの省略形です。
private DateTime _startDate;
public DateTime StartDate
{
get { return _startDate; }
set { _startDate = value; }
}
// repeat for EndDate
プロパティの利点は、クラスがその内部構造について少ししか公開していないことです。また、ロジックをクラスに追加する必要がある場合 (StartDate が過去にないことを確認するなど、日付の特定の境界をチェックするなど)、クラスのバイナリ互換性を損なうことなくプロパティに追加できます。そのため、コードを消費する際に違いを知る必要はありません。例えば:
private DateTime _startDate;
public DateTime StartDate
{
get { return _startDate; }
set
{
if (value < DateTime.Now)
throw new ArgumentException(string.Format("Start Date must not be in the past: {0}", value.ToString()));
_startDate = value;
}
}
このクラスの動作を定義し続けることで、これをさらに進めることができます。これらのプロパティを公開しても、クラスは「オブジェクト」というよりも「データ構造」に近いものになります。(データ/オブジェクトの反対称についてさらに読むには、Robert Martin による Clean Code をお勧めします。) 適切なオブジェクト指向設計の目標は、オブジェクトがそのデータを隠し、そのデータに対してステートフルなアクションを内部的に実行するメソッドを公開することです。 .
たとえばEndDate
、1 日延長する必要がある場合は、次のようにします。
myObject.EndDate += new TimeSpan(1, 0, 0, 0);
しかし、よりオブジェクト指向のアプローチ (「教えて、尋ねるな」という原則に固執する) は、データに時間を延長するように直接指示するのではなく、オブジェクト自体に時間を延長するように指示することです (それによって、オブジェクトに時間を「尋ねる」処理中のそのデータは、間違いなくデメテルの法則にも違反しています):
myObject.ExtendEndDate(new TimeSpan(1, 0, 0, 0));
あるいは:
myObject.ExtendEndDateInDays(1);
オブジェクトにそのようなメソッドを実装するだけでよく、そのメソッドはの値を内部的に拡張しますEndDate
。
クラス自体は、それが表す概念に必要なすべての機能をカプセル化する必要があります。絶対に必要な場合は、内部メンバーへのパブリック読み取りアクセスを提供できますが、設計の観点から、オブジェクトのデータに対して実際にどのような種類のクエリを実行する必要があるかを自問し、直接アクセスするのではなく、それらのクエリに対してよりターゲットを絞ったメソッドを提供することを検討する価値があります。クラスのデータメンバーに。