スパゲッティ VBA コードを使用して数年前の MS Access アプリを C# および OOP に移植しようとしていますが、ドメイン ロジックをドメイン クラスに配置する最善の方法を見つけるのに苦労しています。
Country
簡単な例としてクラスを使用します。ビジネス ルールが異なる 3 つのプロパティがあります。
CountryCode
国が作成されると、国を使用するサードパーティのアプリで問題が発生するため、変更できなくなりますCountryName
基礎となるロジックやビジネス ルールなしで、いつでも変更できます。IsoCode
いつでも変更できますが、正確に 2 文字の長さでなければなりません
(IsoCode
実際にはもっと多くの規則がありますが、この例では、単純にするために「正確に 2 文字でなければならない」が唯一の規則であると仮定します)
クラスのわずかに異なる 2 つのバージョンを作成しました。
私はオブジェクト指向プログラミングの経験がまったくないので、次のことを決めるのに助けが必要です:
- どのアプローチを使用するかは重要ですか?
- それらの 1 つ (または両方) に、私が見ていない問題がありますか?
- さらに良い別の方法はありますか?
私のアプローチは両方とも今は良さそうに見えますが、後で問題が発生するかどうかはわかりません (問題のアプリは 10 年前のものであり、おそらく長い間存続するでしょう)。
バージョン 1:
public class Country1
{
public string CountryCode { get; private set; }
public string CountryName { get; set; }
public string IsoCode { get; private set; }
public Country1(string countryCode, string countryName, string isoCode)
{
this.CountryCode = countryCode;
this.CountryName = countryName;
SetIsoCode(isoCode);
}
public void SetIsoCode(string isoCode)
{
if (isoCode.Length != 2)
{
throw new ArgumentException("must be exactly 2 characters!");
}
this.IsoCode = isoCode;
}
}
バージョン 2:
public class Country2
{
public Country2(string countryCode, string countryName, string isoCode)
{
this.countrycode = countryCode;
this.CountryName = countryName;
this.isocode = isoCode;
}
private readonly string countrycode;
private string isocode;
public string CountryCode
{
get { return this.countrycode; }
}
public string CountryName { get; set; }
public string IsoCode
{
get { return this.isocode; }
set
{
if (value.Length != 2)
{
throw new ArgumentException("must be exactly 2 characters!");
}
this.isocode = value;
}
}
}
なぜ私がこれを求めているのか、そして私が知りたいことについて、もう少し背景を説明します。
「正しい OOP の方法」について、さまざまな意見を読みました。
ゲッターとセッターをまったく公開すべきではないと言う人もいます。これがセッターの悪い考えである理由を理解していCountryCode
ます。そのため、コンストラクターからのみ設定できます。
getter と setter を使用する代わりに、GetXXX
andSetXXX
メソッドを使用する必要があると言う人もいます。場合によっては、これが理にかなっていることがわかります (たとえば、SetXXX
一緒に設定する必要がある複数の値がある場合に、複数のパラメーターを持つメソッド)。
しかし、多くの場合CountryName
、私の例のような単純な値があります。これは、ロジックのない「ダム」値です。1 つのクラスにこれらのものが 10 個ある場合、それぞれのメソッドを作成GetXXX
したくありません。SetXXX
次に、 のようなものがありIsoCode
ますが、これは他のどのプロパティにも接続されていません (そのため、SetXXX
メソッドを使用して別のプロパティと一緒に設定する必要はありません)。ただし、いくつかの検証が含まれているため、メソッドを作成SetXXX
するか、setter で検証を実行する (何か問題がある場合は例外をスローする) ことができます。
例外をスローすることは、呼び出し元にエラーを通知する最良の方法ですか? 大丈夫だと言う人もいれば、「例外的な」場合にのみ例外をスローするべきだと言う人もいます。
IMO 誰かが無効な ISO コードを入力しても例外ではありませんが、エラーが発生したという情報 (人間が読めるエラー メッセージを含む!!) をクライアントに取得するにはどうすればよいですか? ErrorMessage
エラー コードと文字列プロパティを持つ応答オブジェクトを使用する方がよいでしょうか?