接近重构

时间:2010-01-17 16:50:52

标签: python unit-testing qt refactoring separation-of-concerns

我有一个以数据为中心的应用程序,用Python / PyQt编写。我在计划 做一些重构以真正将UI与核心分开,主要是因为 还没有任何真正的测试,显然必须改变。

已经存在一些分离,我认为我已经以正确的方式做了很多事情,但它远非完美。两个例子,向您展示困扰我的事情:

  • 当用户右键单击数据对象的表示时,上下文菜单 弹出的是由数据对象创建的,尽管这个数据对象(基本上是 数据库行的ORM表示应该与UI无关。

  • 当某些内容写入数据库时​​,但写入失败(例如,因为数据库记录是 由不同的用户锁定),向用户呈现经典的“重试/中止”消息框。这个 对话框由数据提供者*创建,尽管提供者显然不应具有任何UI功能。 显然,提供者可以提出异常或以其他方式指示失败,并且UI可以捕获 那并采取相应行动。

    *这是我用于基本上代表数据库表并进行调解的对象的单词 它的数据对象和数据库引擎之间;我不确定这是否是通常所说的 “提供者”

我没有测试经验,所以我不容易“感觉”可测性问题等,但在我开始之前,必须进行一些重组。

没有涉及复杂的业务逻辑(它主要只是CRU D ,是的,即使没有D),这将比重写更重组,所以我真的不关心引入回归错误,如this question中讨论的那样。

我的计划是开始重构这个想法,因为UI部分很容易被删除 例如,替换为Web前端或基于文本的界面而不是Qt界面。另一方面, Qt本身仍然会被核心使用,因为信号/插槽机制在很多地方使用, 例如数据对象发出changed信号,表明你知道是什么。

所以,我的问题:这是一种提高可测试性和可维护性的可行方法吗?还有其他任何评论,特别是考虑到Python吗?

4 个答案:

答案 0 :(得分:7)

如果你还没有这样做,请阅读Michael Feathers的“有效使用遗留代码” - 它正是处理这种情况,并提供了丰富的技术来处理它。

他提出的一个关键点是在重构之前尝试进行一些测试。由于它不适合单元测试,因此尝试进行一些端到端测试。我相信Qt有自己的用于驱动GUI的测试框架,因此添加针对已知数据库操作GUI的测试并验证结果。在清理代码时,您可以使用单元测试替换或扩充端到端测试。

答案 1 :(得分:2)

如果要从所有其他部分中提取应用程序的所有GUI部分以测试所有应用程序,则应使用Model-View-Presenter:您可以找到一些解释here和{{ 3}}

使用此模型,应用程序的所有服务都使用演示者,而只有用户可以直接与视图(GUI部分)交互。演示者正在从应用程序管理视图。在您想要修改GUI框架的情况下,您将拥有一个独立于您的应用程序的GUI部件。您唯一需要修改的是演示者和视图本身。

对于您想要的GUI测试,您只需为演示者编写here即可。如果要测试GUI使用,则需要创建unit tests

希望有所帮助!

答案 2 :(得分:1)

我之前已经完成了针对UI /后端分离的大型遗留代码的重构。这很有趣,也很有价值。

/赞;)

无论模式是什么模式还是MVC的一部分,拥有非常清晰的 API层都是非常宝贵的。如果可能,您可以通过调度程序路由所有UI请求,该调度程序将为您提供对UI的更好控制< - >逻辑通信,例如。实现缓存,身份验证等。

要想象:

[QT Frontend]
[CLIs]             <=======> [Dispatcher] <=> [API] <==> [Core/Model]
[SOAP/XMPRPC/Json]
[API Test Suite]

这样

  • 添加测试套件以测试API更容易。
  • 此外,它还可以更加统一地添加更多UI。
  • API文档:假设您希望通过某些RPC接口记录和公开API,则更容易生成API文档。 如果有人不同意API文档的重要性,可以随时查看Twitter API并获得成功。
  • 您可以快速将API图层导入python shell并使用它

在开始编写API层之前,API设计可能会发生。根据应用程序的不同,您可能希望获得zinterfaces等软件包的帮助。 这是我在编写非常小的应用程序时采用的一般方法,它对我来说从未失败过。

看看

这种方法的一个明显优势是,在拥有API层和新UI之后,您现在可以回到遗留代码并以更小的步骤修复/重构它。

其他建议是准备好您的测试套件。请参阅What are the first tasks for implementing Unit Testing in Brownfield Applications?上的interstar建议。

答案 3 :(得分:1)

有一点,到目前为止还没有提到,并没有真正回答这个问题,但非常重要:在你开始重构之前,你应该立即进行测试。测试的主要方面是检测你是否破坏了某些东西。

重构是指确切地看到某些操作的效果发生了变化以及同一个调用产生不同结果的位置非常有价值的地方。这就是所有这些测试的内容:你想看看你是否打破了某些东西,你想看到所有无意的变化。

因此,现在对重构后仍应产生相同结果的所有部分进行测试。测试不是为了永远保持相同的完美代码,测试是针对需要更改的代码,需要修改的代码,将被重构的代码。测试是为了确保您的重构确实按照您的意图执行。