业务实体 - 列表是否应该仅作为 ReadOnlyCollections 公开?
在尝试集中如何添加项目或从业务实体类中删除项目时,我已转移到所有列表仅公开为 ReadOnlyCollections 的模型,并且提供添加和删除方法来操作列表中的对象。
这是一个例子:
public class Course
{
public string Name{get; set;}
}
public class Student
{
private List<Course>_courses = new List<Course>();
public string Name{get; set;}
public ReadOnlyCollection<Course> Courses {
get{ return _courses.AsReadOnly();}
}
public void Add(Course course)
{
if (course != null && _courses.Count <= 3)
{
_courses.Add(course);
}
}
public bool Remove(Course course)
{
bool removed = false;
if (course != null && _courses.Count <= 3)
{
removed = _courses.Remove(course);
}
return removed;
}
}
我执行上述操作的部分目标是不要以贫血数据模型(反模式)结束,并且避免在各处添加和删除课程的逻辑。
一些背景:我正在使用的应用程序是一个 Asp.net 应用程序,其中的列表以前作为列表公开,这导致了将课程添加到学生的各种方式(有些地方进行了检查)和其他人没有进行检查)。
但我的问题是:以上是个好主意吗?
In trying to centralize how items are added, or removed from my business entity classes, I have moved to the model where all lists are only exposed as ReadOnlyCollections and I provide Add and Remove methods to manipulate the objects in the list.
Here is an example:
public class Course
{
public string Name{get; set;}
}
public class Student
{
private List<Course>_courses = new List<Course>();
public string Name{get; set;}
public ReadOnlyCollection<Course> Courses {
get{ return _courses.AsReadOnly();}
}
public void Add(Course course)
{
if (course != null && _courses.Count <= 3)
{
_courses.Add(course);
}
}
public bool Remove(Course course)
{
bool removed = false;
if (course != null && _courses.Count <= 3)
{
removed = _courses.Remove(course);
}
return removed;
}
}
Part of my objective in doing the above is to not end up with an Anemic data-model (an anti-pattern) and also avoid having the logic that adds and removes courses all over the place.
Some background: the application I am working with is an Asp.net application, where the lists used to be exposed as a list previously, which resulted in all kinds of ways in which Courses were added to the Student (some places a check was made and others the check was not made).
But my question is: is the above a good idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,这是一个很好的方法,在我看来,除了装饰列表之外,您没有做任何事情,而且它比实现您自己的 IList 更好(因为您节省了许多代码行,即使您失去了更优雅的迭代方式您的课程对象)。
您可以考虑接收验证策略对象,因为将来您可能有新的需求,例如:可以拥有 3 门以上课程的新型学生等
Yes, this is a good approach, in my opinion you're not doing anything than decorating your list, and its better than implementing your own IList (as you save many lines of code, even though you lose the more elegant way to iterate through your Course objects).
You may consider receiving a validation strategy object, as in the future you might have a new requirement, for ex: a new kind of student that can have more than 3 courses, etc
我想说,当添加/删除需要按照您建议的方式进行控制时(例如业务规则验证),这是一个好主意。否则,正如您从前面的代码中知道的那样,实际上无法确保执行验证。
然而,您可能想要达到的平衡是何时执行此操作以及何时不执行此操作。对每种类型的每个集合都这样做似乎有点矫枉过正。但是,如果您不这样做,然后需要添加这种看门代码,那么这对于类来说将是一个重大更改,这可能会或可能不会令人头疼。时间。
我想另一种方法可能是拥有
IList
的自定义后代,它具有其Add()
和Remove()< 的通用看门代码/code> 通知系统正在发生的事情的方法。类似暴露在调用这些方法的内部逻辑之前引发的事件之类的事情。然后,在实例化
_courses
将业务逻辑应用于事件时,Student
类将提供一个委托或其他东西(很抱歉含糊其词,我今天非常编码)如果业务验证失败,则取消操作(我想会抛出异常)。这也可能是矫枉过正,具体取决于开发人员的处置。但至少通过像这样经过更多设计的东西,您可以获得所有内容的单一通用实现,并可以选择随着时间的推移根据需要添加/删除业务验证,而不会破坏更改。
I'd say this is a good idea when adding/removing needs to be controlled in the manner you suggest, such as for business rule validation. Otherwise, as you know from previous code, there's really no way to ensure that the validation is performed.
The balance that you'll probably want to reach, however, is when to do this and when not to. Doing this for every collection of every kind seems like overkill. However, if you don't do this and then later need to add this kind of gate-keeping code then it would be a breaking change for the class, which may or may not be a headache at the time.
I suppose another approach could be to have a custom descendant of
IList<T>
which has generic gate-keeping code for itsAdd()
andRemove()
methods which notifies the system of what's happening. Something like exposing an event which is raised before the internal logic of those methods is called. Then theStudent
class would supply a delegate or something (sorry for being vague, I'm very coded-out today) when instantiating_courses
to apply business logic to the event and cancel the operation (throw an exception, I imagine) if the business validation fails.That could be overkill as well, depending on the developer's disposition. But at least with something a little more engineered like this you get a single generic implementation for everything with the option to add/remove business validation as needed over time without breaking changes.
我过去曾这样做过,但后悔了:更好的选择是使用不同的类来读取域对象,而不是使用修改它们的类。
例如,使用行为丰富的
Student
域类,该域类小心翼翼地保护其对课程的所有权 - 如果学生对课程负责,则根本不应该公开它们 - 以及StudentDataTransferObject
(或ViewModel
),它提供了一个简单的课程字符串列表(或者当您需要 ID 时的字典)以填充界面。I've done that in the past and regretted it: a better option is to use different classes to read domain objects than the ones you use to modify them.
For example, use a behavior-rich
Student
domain class that jealously guards its ownership of courses - it shouldn't expose them at all if student is responsible for them - and aStudentDataTransferObject
(orViewModel
) that provides a simple list of strings of courses (or a dictionary when you need IDs) for populating interfaces.