是否有更好的方法来限制对职业和雇主财产的访问?
本课程旨在收集一个人(潜在客户)的就业信息。 EmploymentStatus可以就业,自雇,失业,退休等......
我只希望这个班级的用户能够设置雇主和职业,如果这个人确实受雇了。
public class EmploymentInformation
{
private const string _EmploymentStatusNotEmployedMessage = "Employment status is not set to employed";
private string _occupation;
private Company _employer;
/// <summary>The person's employment status<example>Employed</example></summary>
public EmploymentStatus EmploymentStatus { get; set; }
/// <summary>The person's occupation<example>Web Developer</example></summary>
public string Occupation
{
get
{
if (IsEmployed)
{
return _occupation;
}
throw new ApplicationException(_EmploymentStatusNotEmployedMessage);
}
set
{
if (IsEmployed)
{
_occupation = value;
}
throw new ApplicationException(_EmploymentStatusNotEmployedMessage);
}
}
/// <summary>The person's employer</summary>
public Company Employer
{
get
{
if (IsEmployed)
{
return _employer;
}
throw new ApplicationException(_EmploymentStatusNotEmployedMessage);
}
set
{
if (IsEmployed)
{
_employer = value;
}
throw new ApplicationException(_EmploymentStatusNotEmployedMessage);
}
}
private bool IsEmployed
{
get
{
return EmploymentStatus == EmploymentStatus.Employed
|| EmploymentStatus == EmploymentStatus.SelfEmployed;
}
}
/// <summary>
/// Constructor for EmploymentInformation
/// </summary>
/// <param name="employmentStatus">The person's employment status</param>
public EmploymentInformation(EmploymentStatus employmentStatus)
{
EmploymentStatus = employmentStatus;
}
}
答案 0 :(得分:2)
如果没有设置值,只返回null
有什么问题吗?这是相当普遍的做法。如果Employer
不存在,则其值为null。为什么它null
可能不相关。此外,强制将就业状态设定在班级本身的范围内。
答案 1 :(得分:2)
强制开发人员按特定顺序设置属性是一个危险的设计:它会使界面误导并鼓励错误。
相反,请考虑使EmploymentInformation
个对象不可变:
// Constructor for retired / unemployed people
public class EmploymentInformation(EmploymentStatus status) {}
// Constructor for self-employed people - we know their status
public class EmploymentInformation(string occupation) {}
// Constructor for people employed by others - we know their status
public class EmploymentInformation(string occupation, Company employer) {}
public bool IsEmployed { get; }
public string Occupation { get; }
public Company Employer { get; }
答案 2 :(得分:1)
首先,如果没有EmploymentInformation
,为什么可以构建Employer
的对象?
尽可能不允许将对象构造为无效状态。您可以使用Guard Clauses或Code Contracts在对象的构造函数中表达这些约束。
public class EmploymentInformation
{
public EmoloymentInformation(Employer employerInstance)
{
if(employerInstance == null)
throw new ArgumentNullException();
}
其次,您可以使用Null Object模式,这样您就不必抛出异常。只需为EmptyEmployer
创建适当的类并返回它们,如下所示。
public Company Employer
{
get
{
return IsEmployed ? _employer : Employer.Empty;
// Employer.Empty is static property which return an instance of EmptyEmployer just like string.Empty.
}
答案 3 :(得分:1)
新答案:
鉴于该对象严格保存有关用户CURRENT员工状态的数据,它仍然是错误的。
正如@Jeff Sternal所说,你不应该强迫开发人员根据特定的顺序分配参数。如果对象需要序列化/反序列化,最终可能会出现很多错误。
相反,您应该提供验证功能。像bool IsValid();
之类的东西当调用该方法时,执行业务逻辑验证以确保对象处于可接受的状态。如果没有,你可以简单地返回一个假,抛出一个异常(请不要),或让它发回一个状态代码,说明对象当前无效的原因。
通常,您将数据抛出到对象中,然后在持久性之前验证对象是否良好。以上只是这样做的一种方式。其他人包括一个业务逻辑库,它将逻辑与数据类完全分开(个人而言,我从来不明白为什么要这样做,但很多人都会发誓。)。
答案 4 :(得分:0)
我没有任何经验,但我认为在某处我会考虑代码合约。
看看这些链接:
http://social.msdn.microsoft.com/Forums/en/codecontracts/thread/1ca2d371-4b85-479d-9e00-64c84e372f02
http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx
您可以使用适合您应用的“要求”来装饰您的属性。看起来很酷,它似乎是IDE的一半集成。
答案 5 :(得分:0)
从逻辑角度来看,这看起来是错误的。
该对象名为“EmploymentInformation”,并且具有名为“EmploymentStatus”的属性
这似乎要么允许就业信息处理活跃或定期雇员的情况;或者,允许就业历史。
如果其中任何一个都是真的,那么在我看来,你可以拥有一个职业但是因为任何原因而拥有像“非雇用”这样的就业状况。
毕竟,让我们看看记录最初是在使用EmploymentStatus的地方创建的。然后,状态将更改为“NotEmployed”下次加载对象时,您将丢失数据。
答案 6 :(得分:0)
如果你是严格的,你可能会说失业的人没有职业或雇主,所以一个人的对象不应该有这些财产。这导致了这样的事情。
class Person
{
public EmploymentStatus EmploymentStatus { get; set; }
}
class EmployedPerson : Person
{
public string Occupation { get; set; }
public Company Employer { get; set; }
}
然而在实践中,这种不可原谅的对象模型使用起来会很麻烦,因为在实例化对象之前,您需要知道某个人是否受雇。在就业和失业之间进行转换也很困难,因为您必须创建一个新对象并复制所有内容。
临床区别不值得。我认为这是正确的,事实上更合乎逻辑的是,向失业者询问他们的雇主是什么,并且他们回答“我没有一个人”,而不是首先无法提出问题。
对我来说,这将是一个更灵活的人。
class Person
{
public Person()
{
this.EmploymentStatus = EmploymentStatus.Unemployed;
}
public void Hire(Company employer, string occupation)
{
this.Occupation = occupation;
this.Employer = employer;
this.EmploymentStatus = EmploymentStatus.Employed;
}
public void Fire()
{
this.Occupation = null;
this.Employer = null;
this.EmploymentStatus = EmploymentStatus.Unemployed;
}
public EmploymentStatus EmploymentStatus { get; private set; }
public string Occupation { get; private set; }
public Company Employer { get; private set; }
}