Clojure的重构技术

时间:2011-10-03 04:17:05

标签: refactoring clojure

我熟悉在C#和Java中重构相当大的代码库,但Clojure是一种不同的野兽,特别是因为它:

  • 在典型代码中混合使用宏和函数(即您可能希望从宏重构为函数,反之亦然?)
  • 在大多数情况下使用动态类型(因此您不会对重构代码的正确性进行编译时检查)
  • 功能而非面向对象
  • 对当前IDE中的重构支持较少
  • 对代码库中的循环依赖性不太宽容(使得更难移动代码/定义块!)

鉴于上述情况,在Clojure中进行代码重构的最佳方法是什么?

3 个答案:

答案 0 :(得分:8)

"Working effectively with legacy code"中,Michael Feathers建议添加单元测试以在代码中创建人为的“拐点”,您可以重新考虑它们。

关于他为非结构化代码添加顺序的方法的一个超级简短且完全不完整的概述:

  • 将代码分为“Legacy”(无测试)和其余部分。
  • 创建测试
  • 重复两半。

递归方法似乎与我在思考Clojure时使用的心理过程很吻合,所以我来联想它们。甚至新语言都可以拥有遗留代码吗?

这是我在阅读那本书的同时考虑到clojure时得到的。所以我希望它作为一般指导方针是有用的。也许你的代码库已经有了很好的测试,在这种情况下你已经超出了这个阶段。

答案 1 :(得分:6)

我不是专家。但无论如何:

  • 远离God功能。如果你有一个很大的功能,把它分解成更小的功能,这些功能中的每一个都做了一件事,它做得很好。
  • 如果您发现使用Java数组(并且没有必要使用它们),请将它们转换为Clojure序列。
  • 拥抱defrecorddefprotocol
  • 远离宏,除非你真的无法在不编写宏的情况下继续。
  • 如果可能,请将延迟序列置于递归之上。
  • 创建服务时,将契约放在自己的命名空间中,并将实现放在自己的命名空间中。
  • 实现依赖注入,将函数作为参数传递给另一个函数。
  • 在可能的情况下对函数的arglist使用desctructuring。这将使得更容易理解函数的实现。
  • 考虑使用Prismatic Sc​​hema项目。

另外,看看CursiveClojure。我认为这很有希望。

我不是CursiveClojure的创建者。

答案 2 :(得分:1)

熟悉在C#或Java中重构相当大的代码库,但是这里有。

Clojure的:

  • 混合了宏和函数:我可能错了,但我认为你会发现重构很少会在宏和函数之间移动接口

  • 使用动态类型(因此您不需要对重构代码进行编译时检查):...也不使用任何其他代码:在任何一种情况下都需要更多测试。

  • 功能而非面向对象重构以OO术语表示,但通常可以在简单的转录中存在:方法功能,类到功能或闭包或映射。

  • 对当前IDE中的重构支持较少 True:更多繁忙工作。

  • 对代码库中的循环依赖性的容忍度较低两种情况:命名空间/文件中的相互递归应该比它更容易处理;但名称空间/包之间的循环依赖会导致混淆和模糊。我认为Java只允许它们,因为C ++确实如此,而C#也是如此。

我发现通过Martin Fowler catalogue of refactorings查看它很有用。大多数人都能从OO翻译成功能性术语。一些(例如Change Value to Reference)消失了。