【发布时间】:2013-10-17 16:23:35
【问题描述】:
我是 Jeff Bay 的 Object Calisthenics 练习的粉丝:
http://www.xpteam.com/jeff/writings/objectcalisthenics.rtf
通过创建对象来封装集合的实现以及对象集合的迭代,我在实现一流的集合方面取得了很好的成果。
这意味着我有一个 EmployeeList 对象,而不是一个 List。
通常,当我创建这些对象时,我不会实现任何集合接口,因此外部用户无法枚举内部集合,因为我认为这就是重点。然而,一位同事提出了相反的建议 - 实现 ICollect 接口以使其更灵活。
这个重构站点似乎在同一个方向,虽然它并没有完全删除对内部集合的访问:http://sourcemaking.com/refactoring/encapsulate-collection
// Foreach method
foreach (var employee in employees)
{
if (employee.IsManager)
{
managers.Add(employee);
}
}
// Linq method
managers = employees.Where(e => e.IsManager);
// Encapsulated iteration method
managers = employees.GetAllManagers();
public IEnumerable<Employee> GetAllManagers() // Inside Employees class
{
return employees.Where(e => e.IsManager);
}
我是否说最后一种方法是有利的?例如,您何时希望通过实现 IEnumerable 来公开您的内部集合?
【问题讨论】:
-
GetAllManagers()确实有意义,但无论如何它都会返回IEnumerable。换句话说,它只是一种方便的方法;它提供了过滤,如果客户有权访问原始集合,客户无论如何都可以自己完成过滤。如果您不希望客户端访问整个集合,这些方法也可用于安全性。 -
它看起来只是一种(仅仅)方便的方法,上面的(简单)实现。如果实现更复杂,并且您发现多个地方在您的代码库中粘贴了相同的实现行,那么这将违反 DRY,对吗?同样,如果内部集合的实现发生了变化,例如如果它必须去数据库来获取信息,你会希望确保客户端首先批量获取所有员工,而不是对每个员工进行 1 次 sql 调用。这个细节最好包裹在列表对象上,而不是强加给客户端,确定吗?
-
这取决于您的用户有多成熟。尽管 DRY,您的最后一个带有
Where子句的示例是存储库对象中非常常见的模式。如果过滤是必要的,这不是多余的。
标签: c# .net oop encapsulation