如何处理怪异的Struts动作?

时间:2008-10-16 17:28:27

标签: java struts design-patterns anti-patterns

我使用Struts 1.2.4继承了这个巨大的遗留Java Web应用程序。我有一个关于行动的具体问题。大多数页面只有一个Action,而且processExecute()方法是可怕的怪物(非常长并且基于请求参数的嵌套if语句很多)。

鉴于Actions是命令模式的一个实现,我正在考虑将这些Actions拆分为每个用户手势一个Action。这将是一个很大的重构,我想知道:

  1. 这是正确的方向吗?
  2. 是否有一个我可以采取的中间步骤,一个处理整体行动中的混乱的模式?可能是Action中的另一个命令模式?

7 个答案:

答案 0 :(得分:9)

我处理这个问题的方法是:

  • 不要马上做'一切'
  • 每当你改变任何东西时,都要比你发现它更好
    • 用单独的Action实现替换条件是一步。
    • 更好的是:将您的实现与Action类分开,以便在更改框架时可以使用它
    • 保持新的Command实现绝对而不引用Struts,在这些实现中使用新的Actions作为Wrapper。
    • 您可能需要为Struts ActionForms提供接口,以便在不复制所有数据的情况下传递它们。另一方面 - 您可能想要传递除ActionForms之外的其他对象,这些对象通常是一堆字符串(请参阅关于Struts 1.2 ActionForms的其他问题)
  • 开始将部件迁移到更新的部件更好的技术。 Struts 1.2出现时很棒,但绝对不是你想要永恒支持的东西。现在有几代更好的框架。

肯定会有更多 - 抱歉,我的时间不多了......

答案 1 :(得分:5)

在我看来,Struts Actions根本不应该包含很多代码。它们应该直接与请求和响应交互 - 从表单或请求参数中获取一些数据,将该信息传递给服务层,然后将一些内容放入Response对象中,或者可以在用户的​​会话中保存一些数据。

我建议不要使用动作类进行继承。一开始听起来是个好主意,但我想迟早你会意识到你的事情比实际使代码库强大得多。 Struts有足够的基本动作,如果你正在创建新的动作,你可能在Web层中得到了不应该存在的代码。

这只是我个人的经历。

答案 2 :(得分:2)

我以前处理过这种事情。一个好的第一步是在Action和一个原始的怪异动作类之间的继承链中插入另一个基类(让我们称之为ClassA)。特别是如果你没有时间一次做所有事情。然后,您可以开始将功能部分分成较小的并行Action类(ClassB,ClassC)。原始ClassA和新重构类之间的任何共同点都可以被提升到新的基类中。层次结构现在看起来像这样:

Original Hierarchy:      New Hierarchy:

     Action                   Action
       |                        |
       |                      BaseA
  (old)ClassA                   |
                       +--------+----------+
                       |        |          |
                   ClassB (new)ClassA   ClassC

答案 3 :(得分:2)

  1. 一次一个方法
  2. 记录一些您可以稍后播放的测试用例。 Example here(确保尽可能多地浏览代码中的路径,即调用此操作的页面上的所有用户手势)
  3. 通过创建较小的方法来重构该方法以降低其复杂性。
  4. 在您执行此操作时重新运行测试
  5. 此时,您已经重构了巨大的烦人方法。 现在您实际上可以开始创建特定的操作。

    您可以将新重构的类用作基类,并使用这些重构的小方法将每个特定操作实现为子类。

    完成此操作后,您应该对类之间共享的逻辑有一个很好的了解,并且可以根据需要提取或推送这些方法。

    这并不好玩,但是如果您将在代码库上工作一段时间,它将为您节省时间和麻烦。

答案 4 :(得分:1)

难题但是早期Web应用程序开发的典型问题。

首先,您需要首先考虑哪种逻辑构成业务行为,哪种逻辑构成“流程”(即用户看到的内容),以及哪种逻辑获取他所看到的内容。

您不必沿着工厂和接口的路线走下去;追溯实现远没那么有用......但是将业务逻辑和数据检索逻辑整合到某种代理中......并留下struts动作来确定基于该逻辑成功/失败的页面流。

从那里你只需要几个星期就把它磨出来

答案 5 :(得分:1)

一个长方法永远不会好,除非碰巧是单个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);
}

如果你可以走得那么远,那么你的逻辑很干净,你可以做任何想要的重构。

困难的部分是让你的逻辑清晰,你可以逐步完成。不要选择一个模式,直到你明白你的问题是什么。

答案 6 :(得分:1)

如果您计划重构代码,则应首先确保为现有代码编写测试,以便在开始重构后确定没有更改其功能。