需要有关分层解决方案、关注点分离等方面的建议

发布于 2024-07-09 05:59:45 字数 1706 浏览 5 评论 0原文

我们有一个分层应用程序,或者至少正在向分层应用程序过渡,细分如下:

  • 接口(用户界面或应用程序界面,即 Web 服务等)
  • 业务逻辑
  • 数据访问

使其余部分问题更具体,我来描述一个具体的例子。

我们有一个用户界面,其背后有一个控制器对象(业务逻辑层)。 该控制器通过另一个对象(数据访问层)与数据库进行通信。

在给定的上下文中,用户界面允许用户选择一名员工来绑定正在执行的操作。 由于存在关于用户(实际上是控制器之外的任何世界)可以选择哪些员工的规则,因此控制器为此提供了两件事:

  • 一个包含可用员工列表的可读属性,可从
  • 包含以下内容的读/写属性 中进行选择:当前选择的员工

用户界面可能会读取该列表并使用它来填充组合框。

在此应用程序的版本 1 中,组合框包含员工的标识号 + 员工的姓名。

一切都很好......

直到版本 1.1,修复了错误。 用户抱怨说,他无法在 Jimmy OlsonJimmy Olson 之间进行选择,因为该应用程序无法让他很容易地知道哪个是哪个。 他知道销售部门有一个吉米,开发部门有另一个,因此此 1.1 版本的修复方法是简单地在组合框中添加斜杠 + 部门名称。 在版本 2 中,我们选择将组合框替换为具有列支持的组合框,并删除斜杠,但在 1.1 中,选择这样做是为了最大限度地减少出现进一步错误的风险。

换句话说,组合框将包含:

  • 1 - Jimmy Olson/Sales
  • 2 - Jimmy Olson/Development
    • 其他人

但是,用户界面代码没有 SQL 代码,也没有任何方法可以获取该部门,因此我们必须转到控制器并查看那里的代码。 控制器不需要部门,说实话,它甚至不需要员工的姓名,识别号码就足够了,因此控制器中没有任何内容要求部门或对部门做任何事情。 所以我们必须深入到数据访问层并更改那里的SQL。

坦率地说,这个解决方案闻起来很臭。

如果该控制器有多个接口,具有不同的要求,我们有三种可能的解决方案:

  1. 更改数据访问层以满足多个接口(2 层之外)的(增加/多样化)需求,这意味着所有接口都将可能会获得他们需要的所有数据,但他们也会获得任何其他界面所需的所有数据
  2. 添加一些内容,让用户界面告诉数据访问层(仍然是 2 层)它需要什么
  3. 以某种方式创建用户界面层在不更改所涉及的控制器或访问层的情况下获取所需的数据,这听起来像是我们在某个地方需要更多的数据访问代码。

上述解决方案都感觉不好。

我想知道的是,我们是否完全偏离了轨道? 你会怎么做? 除了上面的3个之外还有第四个和第五个解决方案吗?

根据这个问题:关注点分离,接受的答案包含以下引用:

关注点分离是将每个关注点的代码分开。 更改接口不应需要更改业务逻辑代码,反之亦然。

这是否仅仅意味着控制器/数据访问层应该向我们提供完成其工作所需的一切(即员工的识别号码),然后用户界面应该与数据库对话并请求更多信息关于这些特定员工

We have a layered application, or at least is in the process of transitioning to one, broken down as follows:

  • Interface (user-interface or application-interface, ie. webservice, etc.)
  • Business logic
  • Data access

To make the rest of this question more concrete, I'll describe a specific instance.

We have a user interface, which has a controller object behind it (the business logic layer). This controller talks to the database through another object (the data access layer).

In a given context, the user interface allows the user to pick an employee to tie the operation being done to. Since there are rules regarding which employees the user (well, any world outside of the controller really) can pick, the controller provides two things for this:

  • a readable property containing a list of available employees to choose from
  • a read/writable property containing the currently chosen employee

The user interface might read the list and use it to populate a combobox.

In version 1 of this application, the combobox contains the identifying number of the employee + the name of the employee.

All is well...

... until version 1.1, a bugfix. A user complains that he can't choose between Jimmy Olson and Jimmy Olson because the application doesn't make it easy enough for him to know which is which. He knows there is one Jimmy in the sales department, and another in the development department, so the fix for this 1.1 version is to simply tack on a slash + the department name in the combobox. In version 2 we would opt for replacing the combobox with a combobox that has column support, removing the slash, but in 1.1, this is what is chosen in order to minimize the risk of further bugs.

In other words, the combobox would contain:

  • 1 - Jimmy Olson/Sales
  • 2 - Jimmy Olson/Development
    • other people

However, the user interface code has no SQL code, or any way to get hold of that department, and thus we have to go to the controller and look at the code there. The controller doesn't need the department, and to be honest, it doesn't even need the name of the employee, the identifying number is enough, so there is nothing in the controller that asks for or does anything to the department. So we have to go down to the data access layer and change the SQL there.

This solution quite frankly smells.

If there are multiple interfaces to this controller, with different requirements, we have three possible solutions:

  1. Change the data access layer to cater for the (increasing/diverse) needs of multiple interfaces (2 layers away), which means that all the interfaces will possibly get all the data they need, but they would also get all the data required for any of the other interfaces
  2. Add something that lets the user interface tell the data access layer (still 2 layers away) what it needs
  3. Somehow make the user interface layer get hold of the required data without changing either the controller or access layer involved, this sounds like we need more data access code, somewhere.

None of the above solutions feel good.

What I'm wondering is, are we completely off course? How would you do this? Are there a fourth and fifth solution below the 3 above?

Per this question: Separation of Concerns, the accepted answer contains this quote:

The separation of concerns is keeping the code for each of these concerns separate. Changing the interface should not require changing the business logic code, and vice versa.

Does this simply mean that all the controller/data access layer should provide us with is whatever it needs to do its job (ie. the identifying numbers of employees), and then the user interface should go talk to the database and ask for more information about these specific employees?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

平生欢 2024-07-16 05:59:45

在我看来,你有两种可能性:

  1. 让较低层发送全部
    他们所掌握的有关某个的信息
    person,可能是 XML 文档,
    尽管很多消费者
    这些信息并不需要全部。
  2. 为上层提供API
    层深入并获得
    他们需要的信息。 所以在
    你给出的案例,有一个方法
    界面可以询问业务
    向数据库层询问的层
    给定用户 ID 的部门。

两者都需要权衡。 第一个暴露了更多信息,可能向那些无权获得该信息的消费者公开。 第二个每笔交易传递的信息要少得多,但需要更多交易。 第一个不需要每次获得更多信息时都更改 API,而是更改 XML。 第二个保持现有 API 的接口不变,但根据需求变化提供新的 API。 等等。

The way I see it, you have two possibilities:

  1. Have the lower layers send up all
    the information they have about a
    person, possibly as an XML document,
    even though many of the consumers of
    that information don't need it all.
  2. Provide APIs for the higher level
    layers to drill down and get the
    information they need. So in the
    case you give, have a method that
    the interface can ask the business
    layer to ask the database layer for
    the department given the user id.

Both have trade-offs. The first one exposes a lot more information, possibly to consumers who don't have any right to that information. The second one passes a lot less information per transaction, but requires more transactions. The first one doesn't require a change to the API every time you have more information, but changes the XML. The second keeps the interface of existing APIs the same, but provides new APIs as needs change. And so on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文