【问题标题】:Everything is a flow?一切都是流?
【发布时间】:2009-04-30 13:34:55
【问题描述】:

我最近从事的一些 Web 项目使用流引擎作为演示和/或(或多或少)业务层的中心抽象。回顾我的经历,老实说,我不喜欢以流程为中心的方法。甚至相反。我看到在使用流作为中心抽象的项目中会出现相同的症状。

  • 一切都是流程。您不只是启动一个应用程序,不,您“进入主流程”,即使它只是显示一个带有巨大调度程序的菜单它。我并不反对这样的流动。一些用例不断出现,需要在其他用例(LookupCustomer,...)的各个点包含,但对于以流程为中心的人一切都是一个流程,即使是事情也是如此。 .. 不流动。

  • 碎片化。 基于流的应用程序倾向于将许多逻辑片段(操作、命令、用于准备视图的代码片段...)分散在整个代码中。映射进出这些动作会增加开销、乏味且使代码膨胀。尽管遵循抽象流程很容易,但实际上弄清楚这些小(或大)代码块中发生了什么是另一回事。虽然每种风格的应用程序都允许人们编写糟糕且不一致的代码,但以流程为中心的应用程序让这变得特别容易。

  • 配置文件。 大多数应用程序使用某种 XML 格式来声明伴随状态变化的流和动作。编写应用程序的语言(比如 Java、C#、Ruby 等)可能比 XML 格式更丰富、更具表现力。何必呢?

  • Flows break encapsulation.如果你给我一个有一定内嵌流逻辑的组件,那么流应该是组件的一部分,而不应该是外部抽象。换句话说:流是组件的一部分,组件是自包含的。这是一个细节。当然,它可以参数化和填充,但组件应该“正常工作”。编写 Swing、GWT 或任何胖或丰富的接口应用程序的人不会为显式流抽象而烦恼。为什么我的 Web 应用程序应该有一个?给我GMail的流程图。

  • (编辑)流程是程序化的。如果您查看像 MVC 这样的“丰富”模式,其中包含事件和所有内容,相比之下流程就显得苍白无力。您正在使用现代且富有表现力的语言来实现您的应用程序,对吧?因此,您可以比打孔卡和汇编器流行时那种死板的“做这个,然后那个,那个,然后……”做得更好。

促进以流为中心的开发的框架示例有 Struts、BTT、Spring Webflow 和 JSF。我还遇到过基于普通 servlet 构建的国产流引擎。

这也是一篇有趣的文章:http://chillenious.wordpress.com/2006/07/16/on-page-navigation/

您(仍然)认为对 Web 应用程序(前端)采用以流为中心的方法是个好主意吗?

【问题讨论】:

  • 我认为,如果您对“流程”给出更具体的定义,或者至少链接到我们这些没有接触过以流程为中心的设计的人可以感受它的资源,那将会有所帮助。这就是你在说的:en.wikipedia.org/wiki/Flow-based_programming
  • 别看得太远。像 Struts 和 Spring Webflow 这样的东西也符合以流为中心的条件。
  • 我认为“流”是指 MVC 框架使用的路由或操作。

标签: language-agnostic


【解决方案1】:

一般来说,对于一个相对简单的问题,流似乎是一种不必要的企业化方法:我们希望确保用户通过我们的应用程序采用多个特定路径之一。更有启发性和洞察力的是检查为什么我们需要这条路径发生。是不是因为……

  • ...我们不希望它们与我们的应用程序交互,除非以严格预定义的方式?然后我们限制了应用程序的实用性,使我们的应用程序更难更改和使用。

  • ...如果人们偏离常规,我们担心我们的应用程序处理意外输入或处理我们没有预料到的状态的能力?这充分说明了我们对验证框架的技术选择。

  • ...除了预定义的场景之外,我们无法想象有人会使用该网站的场景?然后我们隐含地假设只有我们知道如何最好地使用它;我们限制了用户控制其交互的能力。

请注意,这些问题中的每一个都强调了应用程序开发和团队成员所固有的问题,并且不是用户的错。所以我支持你的一般前提,即基于流程的方法往往存在许多问题。

主要问题是流程不必要地增加了已经被其他机制更好地抽象的脆弱性。例如,要实现“您需要在确认结帐之前填写订单”之类的规则,不做工作流;有一个更好的CustomerOrder 模型,它知道什么时候它没有允许OrderConfirmation 所需的所有信息。如果您尝试跳过,您的模型和控制器应该注意在下一个 POST 上验证失败。

本质上,流会提取每个参与控制器的不同片段,并将它们收集到特定于每个流的新“流控制器”中。这不一定是一个坏主意,但它表明如果这种路径很容易单独定义,那么最初的控制器可能已经承担了太多的责任。例如,如果您之前有 OrderConfirmationCustomerOrderOrderCheckout 控制器,并且您正在考虑使用 Order 流程将所有三个链接在一起,您可能应该考虑的是Order 控制器而不是

【讨论】:

  • 流程不是关于“确保路径”、“严格预定义”、“处理意外输入”或“实现规则”——这就是验证框架和业务规则的用途。流程只是明确定义(或配置)您的应用程序如何工作,这是您在控制器和随附的控制器配置代码中隐式执行的操作。
  • 我的观点是,配置最好留给我们已经发明的更有效、更简单的东西(约定优于配置往往具有优势)。此外,我注意到流的实际实现(例如 Spring WebFlow)往往是非 REST-ful 的。这并不是说您不能编写 RESTful 流,但框架似乎并不鼓励这样做。
【解决方案2】:

我认为定义流在 Web 应用程序中很有用。回答您的主要观点:

一切都是流。

这并没有本质上的错误,它只是赋予某些东西的名称。流程可以是短的也可以是长的——我同意有一个“主”流程来启动一切有点奇怪,但在实践中它并没有真正引起任何问题。

碎片化

您在这里有一些有效的观点,尽管我觉得对此做出最大贡献的是 DSL 的设计。例如,Spring WebFlow v2 在可读性和可理解性方面比 SWF v1 有了巨大的改进。

配置文件

我强烈反对这一点。我觉得xml表达这段代码最好的方式。如果您考虑一下 - 管理控制器、视图、状态更改和操作实际上只是“配置”而不是“代码”。而xml(在我看来)是表达配置的最佳方式。想想“控制器”这个词。控制器所做的只是直接和配置事物 - 调用服务、返回视图和模型等。不需要任何 Java 的丰富性或表现力来定义基本上只是 Web 应用程序的配置。

流打破封装

GMail 可以用一系列流来表示。想想撰写和发送电子邮件所需的步骤数。流实际上只是定义了应用程序如何工作的连线——当然,您可以拥有许多相互交互的组件,但是您将它们配置为一起工作的方式本质上是您在应用程序中定义的流。在我看来,在单独的 DSL 中明确显示这个流程似乎是个好主意,因为从根本上说它独立的。

【讨论】:

    【解决方案3】:

    应该回答的第一个问题是流框架是否真的是您特定 Web 应用程序的最佳工具。我自己是 Spring Web Flow 的粉丝,但我只会在我的 Web 应用程序可以轻松分解为流并且应该严格控制导航的情况下使用它。如果导航非常松散,您几乎可以从任何其他页面到达任何页面,那么 SWF 就不是适合这项工作的工具。

    正如您所提到的,流框架还有其他缺点。它们通常不是 RESTful,因此不可收藏。如果这与您对应用程序的需求相冲突,那么 SWF 可能不适合您。

    也就是说,SWF 和其他一些流框架提供了一些其他 Web 框架很少提供的功能。这包括双重提交问题和浏览器后退按钮和历史处理的完整解决方案。 SWF 对这些功能的实现提供了一些额外的安全性。由于每个页面的流执行 ID 会随着应用程序的使用而变化,因此您可以免受强制浏览和跨站点请求伪造的一些保护。

    在我看来,流的概念非常好,因为流倾向于反映用例。将数据范围限定为流或对话可以免除开发人员清理数据的责任,我认为这是一件非常好的事情。这就像手动内存管理和垃圾收集之间的区别。它不仅减少了我的工作量,而且消除了在我忘记清理属性时引入错误的可能性。我讨厌 Struts 的一件事是我需要在多个操作中复制我的清理代码以确保正确性。将数据范围限定为用例要容易得多。

    流还为相关的操作和视图提供了上下文。如果我查看一个 struts-config 或 faces-config 文件,我可以看到各种导航规则或操作映射,但是我没有直接的上下文来将相关项目组合在一起。我必须手动跟踪配置,即使这样有时我也会卡住。使用 Struts,我需要查看特定的网页,以确定可以从视图中调用哪些操作。

    使用 SWF,我可以清楚地看到与流程相关的所有操作、视图和模型。使用 Eclipse 插件,我可以将其视为状态图。即使您不使用 eclipse,也很容易将流定义转换为状态图。这些图表对我自己、我的项目经理以及几乎任何想要了解用例如何执行的高级别的人都很有用。简而言之,将相关的事物分块在一起可以更容易理解,并且学习曲线更浅。这就是 OOP 如此受欢迎的原因之一。对于网络应用,将这些元素组合在一起形成一个用例的想法很自然。

    【讨论】:

      【解决方案4】:

      一切都是流

      一切都是流动的。计算机程序一直是一个流程,并且将永远是一个包含这些过程的流程:

      输入 -> 过程 -> 输出

      MVC 设计模式其实与此相对应..

      控制器 -> 模型 -> 视图

      碎片化

      你是对的。但我认为这个“问题”可能会因 IDE 的良好支持而减少。

      配置文件

      毫无疑问,xml 是表达配置的最佳方式。

      流打破封装

      我不同意这一点。您可以使用流程制作黑盒,然后在其他流程中使用这些黑盒。

      【讨论】:

      • 哇...我认为 XML 是表达配置的最佳方式存在很多疑问。在某些环境中,它是阻力最小的路径,但它不像 YAML 那样可读,也不像代码那样清晰。
      • MVC 不是一个很好的例子来说明你的观点。正如您所说,每个程序都有数据和控制流,但 MVC 本身从未表示为“以流为中心”的模式。好的 MVC 是一组具有独立职责的交互对象,它们必须合作,但没有总体流概念。在 MVC 中,通常没有“开始”或“结束”。
      • 没错。我指出,即使在 MVC 中,也必须存在这 3 个主要进程,并且可以将它们“映射”到上面所写的模型、视图和控制器。
      【解决方案5】:

      恕我直言,最好将网络应用程序开发为独立模块,而不是“受流程约束”的模块。

      由于当今大多数 Web 应用程序都是 ajaxy 应用程序,因此在页面上拥有独立的模块会有很大帮助。

      可以通过 XML 或 JSON 文件处理配置。

      【讨论】:

        【解决方案6】:

        Web 2.0 对“一切都是流”的概念提出了严峻挑战。当表示层完全转换到客户端层时,我们将回到基于事件处理的坚实且熟悉的(来自过去的 GUI)的基础上。

        【讨论】:

          【解决方案7】:

          流程的出现是由于传统应用程序交互与 Web 应用程序实际工作方式之间的继承不匹配。流只是一种方便的方式来描述更传统的建模为一系列 GUI 对话框(思考向导)的方式,其方式与网页的交付和交互方式兼容。想象一下,如果您正在编写一个传统程序,但每次用户运行该程序时,您只能显示一个对话框,并且当用户单击“确定”(或“取消”、“下一步”或“ Previous") 您的程序将终止。在这种情况下,您将如何对程序的预期行为进行建模(为了使问题更加复杂,假设许多用户在不同时间运行程序)?我想你会发现你宁愿很快得到类似于流的东西。

          我想也许您真正要问的是,“为什么大多数流程框架都这么容易被滥用?”,这自然会导致后续问题“可以做些什么来解决这个问题?”。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-06-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-04
            • 2020-02-17
            • 2010-09-30
            相关资源
            最近更新 更多