提问人:Federico Rotoli 提问时间:11/14/2023 更新时间:11/20/2023 访问量:46
干净的架构和存储库
Clean architecture and repositories
问:
最近,对于我一直在从事的 Flutter 项目,我决定采用使用 Clean Architecture 的功能驱动架构。通过非常详细的软件设计,它非常适合逻辑划分。
然而,这些天来,我出现了一个关于存储库使用的问题。在使用 Firestore 且存储库是我与此类数据交互的层的应用程序中,在各种功能上对它们进行划分,同时仍然要处理相同的集合是否正确?(不同的部分由不同的特征组成,但接触相同的数据集合)。在工作结束时,我可能会发现几个具有相同代码的存储库类,即使它们属于不同的功能。
澄清将不胜感激!提前致谢
答:
存储库是从外部数据源检索/管理数据的绝佳模型。
此模型是面向实体的。也许这就是促使你问这个问题的原因。 我认为功能驱动的设计并不意味着一切都以功能为导向。 我的意思是,这种设计决定了你的领域层分类,但不是全部。 仅仅因为每个功能都有一个处理程序并不意味着您必须多次重新编码存储库。 存储库是基础结构层的一部分。如果您的应用程序上有多个域,则其接口可以由多个项目/模块共享。
在属性域图层(在要素类管理器中)的某个位置,您将使用资料档案库来加载一些数据。 你需要确保的是你使用一个接口,而不是依赖于存储库的实现(也许这对你来说已经很清楚了,只是给其他读者一点)。
例如,可以在 OrderReservationHandler 中使用 IClientRepository 来加载客户数据。
无论您使用哪种设计,您都将面临的困难是:
- 此存储库将返回什么结果?
- 我应该只加载实体本身,还是只加载它的关系?
关于第一点,有几种方法:
- 第一个也是我最喜欢的是返回一个 DTO 对象(只包含属性,不包含方法的类)。如有必要,将这些类转换为域模型(域层下的类)。
- 第二:一些开发者更喜欢直接返回领域模型,以减少数据映射。
对于第二点,我认为无论使用什么设计,它总是相同的难度:
- 我是否应该加载实体及其关联的实体?
- 我是否应该只加载关联实体的标识符并进行延迟加载?
- 是否可以加载实体聚合(任意联接)以减少数据加载时间并使事情更简单?
我的观点是,这取决于上下文。 设计是用来使事情变得简单,而不是使事情复杂化。 如果我完全在系统中使用存储库模型,并且面对使用许多过滤器进行数据搜索的屏幕实现,我将 随意使用自定义查询或存储过程来加载聚合数据,我不会因为模型而使实现复杂化或使加载速度非常慢。 我认为这里非常重要的一点是知道何时打破规则。没有一个模型可以解决所有问题。 此外,一个模型通常只能解决一个问题。
结论是,在软件项目中,我们总是需要:
- 实体的完全加载 => 慢速模式
- 加载没有关联数据的实体(仅关系标识符)=>快速模式
- 自定义数据加载(任意联接)=>自定义模式
好的设计将帮助您轻松区分这 3 种用途。
评论