3

我们有两种域类型:用户位置

我们在LocationRepository上有一个方法:GetUserLocations()

现有实现:

var user = UserRepository.GetUser(userId);
var locations = LocationRepository.GetUserLocations(userId);

对我来说,从User类型中检索与用户关联的位置更有意义,即:

var user = UserRepository.GetUser(userId);
var locations = user.GetLocations();

我认为后一种实现读起来更清晰,作为 API 客户端,我必须处理更少的类型(即不需要LocationRepository )。另一方面,将有更多代码需要维护,因为我必须将“外观”写入LocationRepository

我应该按照自己的直觉行事并在User类型上创建LocationRepository的外观,还是应该对现状感到满意并接受让我“感觉”错误的序列图(即检索位置信息的感觉就像是从错误的“观点”检索)?

4

2 回答 2

1

我会从可维护性的角度来解决这个问题。我同意使用 LocationRepository 上的外观做这件事会“感觉不错”,并且可能会使代码更具可读性。

正如您所说,权衡将是维护更多代码。但是我们在谈论多少代码?是不是很多,你需要经常更新吗?或者你可以写一次就忘记它,让它易于单元测试吗?如果是前者,就把它吞下去,继续当前的实现,并提醒自己它不会真正影响功能。如果是后者,那么可能值得为其他地方的良好感觉和更易读的代码付出努力。

于 2010-01-22T14:18:06.403 回答
1

当然可以像这样对我们的东西建模:

Universe.Instance.Galaxies["Milky Way"].SolarSystems["Sol"]
        .Planets["Earth"].Inhabitants.OfType<Human>().WorkingFor["Initech, USA"]
        .OfType<User>().CreateNew("John Doe");

也许存储库实例不应该对“最终开发人员”可见并封装在模型中。

但是,由于我们可能无法轻松访问 . Universe.Instance,因此我们确实需要一个或多个“入口点”来实际从中获取任何数据。

更新:

我认为一方面应该将“存储库门面入口点”的数量保持在尽可能低的水平,因为这更接近现实世界,因为应该只有一个“Bing Bang”可以容纳所有东西来自并最终产生了所有现有数据 ;-) ...也就是说,另一方面,当然,今天的系统总是我们必须做出的重大妥协,因为模拟现实世界的能力是有限的,有性能影响等等……

但是,您可以在具体示例中使用的一种方法是使用您的存储库来始终检索新数据,例如:

LocationRepository.Instance.GetUserLocations(userId);

...而您使用User模型类将结果保存在属性中,例如:

var locations = myUser.Locations;

该属性将使用延迟加载技术在第一次需要时从 LocationRepository 加载数据,然后保存结果。这表明位置只加载一次,这使使用您的库的开发人员更容易。然后,您可以决定是否要让最终开发人员也可以看到 LocationRepository.GetUserLocation(userId)。请记住,在走这条路时,您还需要构建某种隐式和显式刷新机制和生命周期管理。

事实证明,这种整体方法对我非常有用。然而,Silverlight 等人的异步世界现在添加了一些新的警告,因为这些属性不能立即刷新并与一行代码中的新值同步。当我们请求刷新时,我们现在必须利用绑定技术和/或使用回调来进一步处理刷新的值。

总而言之,我相信最终目标仍然是将例如 aUserRepository视为另一种常规域类型,显然有责任创建新的单个User实例并将它们添加到用户的存储中,以及提供过滤视图(查询)对所有可用用户。这是可以接受的,myUser.LocationsmyLocations.ByUser["John Doe"]持有对相同结果的引用。这UserRepository可能只是另一个负责持有它的类的属性,CompanyStaff例如。把这个想法带到更远的地方是让我想到那Universe.Instance件事的原因。;-)

于 2010-01-22T14:23:06.067 回答