我们有一个分层的应用程序,或者至少正在过渡到一个,分解如下:
- 接口(用户接口或应用程序接口,即webservice等)
- 商业逻辑
- 数据访问
为了使这个问题的其余部分更加具体,我将描述一个具体的例子。
我们有一个用户界面,它背后有一个控制器对象(业务逻辑层)。该控制器通过另一个对象(数据访问层)与数据库通信。
在给定的上下文中,用户界面允许用户选择一个员工来绑定正在执行的操作。由于有关于用户(实际上是控制器之外的任何世界)可以选择哪些员工的规则,控制器为此提供了两件事:
- 一个可读的属性,其中包含可供选择的可用员工列表
- 包含当前选择的员工的读/写属性
用户界面可能会读取列表并使用它来填充组合框。
在此应用程序的版本 1 中,组合框包含员工的识别号 + 员工的姓名。
一切都很好...
...直到版本 1.1,一个错误修复。用户抱怨他无法在Jimmy Olson和Jimmy Olson之间进行选择,因为该应用程序无法让他轻松地知道哪个是哪个。他知道销售部门有一个 Jimmy,开发部门有另一个,所以这个 1.1 版本的解决方法是简单地在组合框中添加一个斜线 + 部门名称。在版本 2 中,我们会选择将组合框替换为具有列支持的组合框,删除斜线,但在 1.1 中,选择此选项是为了最大限度地降低出现更多错误的风险。
换句话说,组合框将包含:
- 1 - 吉米奥尔森/销售
- 2 - 吉米奥尔森/发展
- 其他人
但是,用户界面代码没有 SQL 代码,也没有任何方法可以控制该部门,因此我们必须到控制器那里查看代码。控制者不需要部门,说实话,连员工的名字都不需要,身份证号码就够了,所以控制者里面没有任何东西向部门索要或做什么。所以我们必须深入到数据访问层并在那里更改 SQL。
坦率地说,这个解决方案很臭。
如果这个控制器有多个接口,有不同的要求,我们有三种可能的解决方案:
- 更改数据访问层以满足多个接口(2 层之外)的(增加/多样化)需求,这意味着所有接口都可能获得它们需要的所有数据,但它们也将获得任何所需的所有数据其他接口的
- 添加一些东西,让用户界面告诉数据访问层(仍然是 2 层)它需要什么
- 以某种方式使用户界面层获得所需的数据,而无需更改所涉及的控制器或访问层,这听起来像是我们需要更多的数据访问代码,某处。
以上解决方案都感觉不好。
我想知道的是,我们完全偏离轨道了吗?你会怎么做?在上述 3 之下是否有第四和第五种解决方案?
根据这个问题:Separation of Concerns,接受的答案包含以下引用:
关注点分离就是将每个关注点的代码分开。更改接口不应该需要更改业务逻辑代码,反之亦然。
这是否仅仅意味着所有控制器/数据访问层应该为我们提供完成其工作所需的一切(即员工的识别号),然后用户界面应该与数据库对话并询问更多信息关于这些特定的员工?