我正在尝试将带有意大利面条 VBA 代码的旧 MS Access 应用程序移植到 C# 和 OOP,并且我正在努力寻找将域逻辑放入我的域类的最佳方法。
我将使用一个Country
类作为一个简单的例子。它具有三个具有不同业务规则的属性:
CountryCode
一旦创建了国家,就无法再更改,因为这会导致使用国家/地区的第三方应用程序出现问题CountryName
可以随时更改,无需任何底层逻辑或业务规则IsoCode
可以随时更改,但长度必须恰好为 2 个字符
(IsoCode
实际上有更多规则,但在此示例中,为了简单起见,我们假设“必须正好为 2 个字符”是唯一规则)
我创建了两个略有不同的课程版本。
我在面向对象编程方面非常缺乏经验,所以我需要帮助决定:
- 我使用哪种方法有关系吗?
- 其中之一(或两者)是否有我看不到的问题?
- 有没有更好的方法?
我的两种方法现在对我来说都很好,但我不知道它们以后是否会引起问题(有问题的应用程序已经使用了十年,并且可能会存在很长时间)。
版本 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 方式”的不同意见。
有人说你根本不应该暴露 getter 和 setter。我理解为什么这对设置器来说是个坏主意,这就是为什么CountryCode
只能从构造函数中设置。
有人说,你应该使用GetXXX
和SetXXX
方法,而不是使用任何 getter 和 setter。我可以看到这在某些情况下是有意义的(例如,SetXXX
当您有多个需要一起设置的值时,具有多个参数的方法)。
但通常有像CountryName
我的示例中的简单值,这是一个没有任何逻辑的“愚蠢”值。当我在一个类中有十个这样的东西时,我不想为它们中的每一个创建GetXXX
和SetXXX
方法。
然后是类似 的东西IsoCode
,它也与任何其他属性都没有联系(因此无需使用SetXXX
方法将其与其他属性一起设置)。但它包含一些验证,所以我可以创建一个SetXXX
方法,或者只是在 setter 中进行验证(并在出现问题时抛出异常)。
抛出异常甚至是通知调用者错误的最佳方式吗?有人说这很好,有人说你应该只为“异常”情况抛出异常。
IMO 当有人输入无效的 ISO 代码时,这并不是什么特别的情况,但是我应该如何向客户端获取发生错误的信息(包括人类可读的错误消息!!)?使用带有错误代码和ErrorMessage
字符串属性的响应对象会更好吗?