如何应对可怕的Struts Actions?
-
03-07-2019 - |
题
我使用 Struts 1.2.4 继承了这个巨大的遗留 Java Web 应用程序。我有一个关于行动的具体问题。大多数页面只有一个 Action,并且 processExecute() 方法是可怕的怪物(非常长且基于请求参数的大量嵌套 if 语句)。
鉴于操作是命令模式的一种实现,我正在考虑将这些操作拆分为每个用户手势一个操作。但这将是一次大规模的重构,我想知道:
- 这是正确的方向吗?
- 我是否可以采取中间步骤,一种处理整体操作内部混乱的模式?也许动作中还有另一个命令模式?
解决方案
我处理这个问题的方法是:
- 不要“一次做所有事情”
- 每当你改变任何东西时,让它比你发现它时更好
- 用单独的 Action 实现替换条件是第一步。
- 更好的是:将您的实现与 Action 类分开,以便在更改框架时可以使用它
- 保留新的命令实施 绝对地 如果不引用 Struts,请使用新的 Actions 作为这些实现的包装器。
- 您可能需要为 Struts ActionForm 提供接口,以便在不复制所有数据的情况下传递它们。另一方面 - 您可能想要传递除 ActionForms 之外的其他对象,这些对象通常是一堆字符串(请参阅关于 Struts 1.2 动作表单)
- 开始将零件迁移到更新更好的技术。Struts 1.2 刚推出时非常棒,但绝对不是您想要永远支持的。现在有几代更好的框架。
肯定还有更多 - 抱歉,我的时间不多了......
其他提示
在我看来,Struts Actions 中根本不应该包含太多代码。他们应该直接与请求和响应交互 - 从表单或请求参数中获取一些数据,将该信息传递给服务层,然后将一些内容放入 Response 对象中,或者可能在用户会话中保存一些数据。
我建议不要使用操作类进行继承。乍一看,这听起来是个好主意,但我认为您迟早会意识到,您是在硬塞东西,而不是真正使代码库变得健壮。Struts 有足够的基本操作,如果您要创建新的操作,您可能在 Web 层中获得了不应该存在的代码。
这只是我的个人经历。
Original Hierarchy: New Hierarchy:
Action Action
| |
| BaseA
(old)ClassA |
+--------+----------+
| | |
ClassB (new)ClassA ClassC
- 一次一个方法
- 记录一些您可以稍后播放的测试用例。 此处示例(确保尽可能多地浏览代码中的路径,即调用此操作的页面上的所有用户手势)
- 通过创建较小的方法来重构该方法以降低其复杂性。
- 在您执行此操作时重新运行测试 醇>
此时,您已经重构了巨大的烦人方法。 现在您实际上可以开始创建特定的操作。
您可以将新重构的类用作基类,并使用这些重构的小方法将每个特定操作实现为子类。
完成此操作后,您应该对类之间共享的逻辑有一个很好的了解,并且可以根据需要提取或推送这些方法。
这并不好玩,但是如果您将在代码库上工作一段时间,它将为您节省时间和麻烦。
难题但是早期Web应用程序开发的典型问题。
首先,您需要首先考虑哪种逻辑构成商业行为,哪种逻辑构成“流动”。 (即用户看到的内容),以及哪些逻辑获取他所看到的内容。
您不必沿着工厂和接口的路线走下去;追溯实现远没那么有用......但是将业务逻辑和数据检索逻辑整合到某种代理中......并留下struts动作来确定基于该逻辑成功/失败的页面流。
从那里你只需要几个星期就把它磨出来
一个长方法永远不会好,除非碰巧是单个switch语句,其中case很短(令牌解析或类似的东西)。
您至少可以将long方法重构为具有描述性名称的较小方法。
如果可能的话,你可以通过检查表单来识别它应该做什么来启动你的方法,然后你可以通过各种选项来实现。虽然没有嵌套ifs,但这些代码往往使代码不可读。只是
enum Operation {
ADD, DELETE;
}
...
Operation operation = determineOperation(form);
if (operation == Operation.DELETE) {
doDelete(form);
} else if (operation == Operation.ADD) {
doAdd(form);
}
如果你可以走得那么远,那么你的逻辑很干净,你可以做任何想要的重构。
困难的部分是让你的逻辑清晰,你可以逐步完成。不要选择一个模式,直到你明白你的问题是什么。
如果您计划重构代码,则应首先确保为现有代码编写测试,以便在开始重构后确定没有更改其功能。