2017-10-15 151 views
0

我有一个非常大的解决方案,由超过50个项目(Windows服务,网站,类库)组成,使用服务框架&存储库并使用Telerik DataAccess ORM构建。经过与Telerik的架构师进行了长时间的讨论后,他们提出了上述设计,因为它们应该符合我们当时的需求并提供可测试的代码框架。几年后,现在我们的服务类已经长到数千行,使得它们更难以维护和测试。CQS文件和命名空间组织

在阅读和研究我们的代码中的一些问题后,我遇到了CQS(命令查询分离),这在我们的项目中对我更有意义,因为它会将我们庞大的服务类划分为更小的可测试类。我已经成功地实现了这个概念的一个小教授,但我现在想知道如何将我的代码移动到CQS命名空间中时将我的代码组织起来(现在将注意力集中在我想象中的命令的组织方式上) - 显然会把所有查询,处理程序和结果每个都在自己的文件夹中,每个文件夹都会有1000个以上的文件,这对于找到一些东西是一个巨大的麻烦。

到目前为止,我有这个文件夹结构

Model 
     Customer 
    Queries 
     CustomerNameByIdQuery 
     CustomerNameByTextSearchQuery 
    QueryHandlers 
     CustomerNameByIdQueryHandler 
     CustomerNameByTextSearchQueryHandler 
    QueryResults 
     CustomerNameQueryResult 

两个查询返回的只有编号和Value属性

现在成像我需要查询完整的客户记录相同CustomerNameQueryResult也让我将需要CustomerByIdQuery,CustomerByIdQueryHandlerCustomer型号的结果。而目前还有大约10个针对不同需求的其他用户查询。

数百个表中的这种模式会使很多查询类和处理程序很难找到我需要在代码中的特定位置使用的内容(如果可能的话,促进代码重用)。

我正在寻找一些已经在大型生产应用程序中使用CQS的退伍军人的建议,这些应用程序涉及项目中查询的命名空间/文件的组织方式,以及您的解决方案是如何组织查询/处理程序/结果的?例如,你是否将查询&处理程序放在同一个文件中?单独的文件是不同的目录?你对同一个对象进行多个查询是做什么的?保存所有查询或多个文件的单个文件?您是否将查询与命名空间分开以便于编码?您是否有任何问题与您的结构有关?

我知道这里没有单个“正确”的答案,但是一些人一直建议使用这种方法的人会帮助我和其他人陷入你遇到的任何问题,并在文件/文件夹结构中解决。

回答

0

我们不使用CQS,但我们有许多项目的大型解决方案,其中一个项目是存储库层。

我们每个模型库类,所以以下的例子中,我们尽量让相对客户模式客户库所有查询。实际上,这来自我们使用的图层中的Model/Proxy/Service/Repository架构。 技巧部分带有像联系人。我们有该模型,并且该存储库充满了使用Contacts表的查询。 那么来自Customeres查询的联系人在哪里?它取决于功能性,它实际上是客户的功能,因此它被放置在客户信息库中。请注意,我们可以选择客户,然后在循环中为每个客户调用联系人,但通常我们会避免由于性能问题。

相对于许多GetCustomerXXX方法。

是的,我们已经有很多方法,我们也有相同方法的重载,以允许使用大量不同参数进行更好的搜索,并且还有一个Paged Query Wraper,因此每次用户滚动时都会加载一个搜索屏幕(所以我们根据你的要求改变答案)。所有这些查询都位于客户存储库中。

相对于域组织。

每个模型都可以被任何项目/域中的许多功能使用。例如,客户位于核心域和金融域中的账单。当然,您可以查询客户的所有账单,以便客户模型可以被任何项目/域使用。所有使用客户和账单的项目将具有相同的域和几乎相同的文件夹层次结构。

简历: 我们有一个模型项目它被所有其他项目引用。它包含许多域和一个复杂的文件夹hyerarchy。

所有项目(服务和存储库除外)都引用代理项目,代理引用服务,服务引用存储库。

这样我们就不会得到循环引用,管理复杂性并保持理智。 注意事项(使用代理一些UI项目,即使在不同的语言和用于实现不同的用户体验(网络/ WinForm的/远程/离线)。

编辑

有些服务可以长到像monolithc怪物。恕我直言,任何超过300线大,一些服务的数量增加最多不超过2k行。

一个因素帮了我们很多的地方已经建立的基础类来处理最常见的情况。

例如我们HAV e存储库基类中的IEnumarebale<BaseModel> GetAll(GenericFilter filter)方法,这意味着所有模型都会自动实现该方法。 事实上,大部分repositoy类都是空的,因为基本已经被覆盖了,我们只需要编写自定义逻辑。

此外,我们避免从另一个服务调用存储库,在一般服务调用服务,从而避免几乎任何代码重复。例如,Base Crud类具有CustomValidation方法,并且在插入/删除/更新事件之前/之后,我们可以根据需要进行覆盖。

继上一个例子。客户和联系人都有他们的CustomValidation。插入新客户(通过联系人)将自动调用两个验证。

所有自动化测试调用基本方法可以节省大量时间。

+1

让,感谢您的详细解答。你基本上是描述我目前的架构。与此相关的“问题”在于,由于服务包含连接到相同问题域的许多不同存储库,因此服务会变得非常长。这就是我试图用CQS简化(它应该将服务分成小块) –

+0

@DaniAvni看到我的使用基类的编辑帮助了很多工作,以最大限度地减少服务和特殊存储库。某些服务很复杂,服务调用其他模型服务,我们尽量避免调用其他存储库。 – jean

+0

Jean,我们也尽量不要从其他服务中调用服务,并且我们的大部分代码都在工作。仍然我的服务是巨大的。例如我的任务服务具有任务的CRUD方法,任务类型的CRUD,预约任务的方法以及许多其他方法,如果我没有记错的话,会产生巨大的文件3K +行。这是我试图与CQS分离的这些文件,因为我的服务中的每种方法都会转化为命令或查询,因此它应该将大文件分解成更小的可管理块 –