62

我有兴趣了解 Python 中的大规模开发,尤其是如何维护大型代码库?

  • 当您对方法的签名进行不兼容更改时,如何找到调用该方法的所有位置。在 C++/Java 中,编译器会为你找到它,你如何在 Python 中做到这一点?

  • 当您在代码深处进行更改时,您如何找出实例提供的操作,因为您没有要查找的静态类型?

  • 你如何处理/防止打字错误(错别字)?

  • UnitTest 是否用作静态类型检查的替代品?

你可以猜到我几乎只使用静态类型语言(C++/Java),但我想尝试使用 Python 来处理更大的程序。但是我在很久以前使用clipper (dBase) 语言时有过非常糟糕的体验,该语言也是动态类型的。

4

8 回答 8

69

不要用螺丝刀当锤子

Python 不是静态类型的语言,所以不要尝试那样使用它。

当您使用特定工具时,您将其用于已构建的内容。对于 Python,这意味着:

  • 鸭子打字:没有类型检查。只有行为很重要。因此,您的代码必须设计为使用此功能。一个好的设计意味着通用签名、组件之间没有依赖关系、高抽象级别。因此,如果您更改任何内容,则无需更改其余代码。Python 也不会抱怨它的构建目的。类型不是问题。

  • 庞大的标准库。如果您使用自己未编码的标准功能,则无需更改程序中的所有调用。Python 随附电池。我每天都在不断地发现它们。当我开始尝试重写现有的东西时,我不知道我可以使用多少个模块。没关系,你不能从一开始就做好。

您不会以相同的方式编写 Java、C++、Python、PHP、Erlang 等等。它们是为什么有这么多不同语言中的每一种都有空间的很好的理由,它们不做同样的事情。

单元测试不是替代品

必须使用任何语言执行单元测试。最著名的单元测试库 ( JUnit ) 来自 Java 世界!

这与类型无关。你再次检查行为。你避免了回归的麻烦。您确保您的客户在轨道上。

用于大型项目的 Python

语言、库和框架无法扩展。架构可以。

如果你设计了一个坚实的架构,如果你能够让它快速发展,那么它就会扩展。单元测试帮助,自动代码检查也是如此。但它们只是安全网。还有小的。

Python 特别适合大型项目,因为它强制执行了一些良好的实践,并且内置了许多常用的设计模式。但同样,不要将其用于未设计的用途。例如:Python 不是 CPU 密集型任务的技术。

在一个巨大的项目中,无论如何你很可能会使用几种不同的技术。作为SGBDDBMS的法语)和模板语言,或者其他。Python也不例外。

您可能希望将 C/C++ 用于需要快速的代码部分。或 Java 以适应Tomcat环境。不知道,不在意。Python 可以很好地处理这些。

作为结论

我的回答可能有点粗鲁,但不要误会我的意思:这是一个非常好的问题。

很多人带着旧习惯来到 Python。我把自己搞砸了,试图像 Python 一样编写 Java。你可以,但永远不会得到最好的。

如果你玩过/想玩 Python,那就太好了!这是一个很棒的工具。但只是一个工具,真的。

于 2008-10-25T14:46:30.577 回答
38

我有一些修改“Frets On Fire”的经验,这是一个开源的python“吉他英雄”克隆。

在我看来,python 并不真正适合真正大规模的项目。

我发现自己花费了大部分开发时间来调试与分配不兼容类型相关的问题,静态类型语言在编译时会毫不费力地揭示这些问题。此外,由于类型是在运行时确定的,因此尝试理解现有代码变得更加困难,因为您不知道当前正在查看的参数的类型是什么。

除此之外,__getattr__在 Python 中使用内置函数的名称字符串调用函数通常比在其他编程语言中更常见,因此使调用图到某个函数有点困难(尽管您可以在某些静态类型语言也是如此)。

我认为 Python 在小型软件、快速原型开发以及将现有程序粘合在一起方面确实很出色,但我不会将它用于大型软件项目,因为在这些类型的程序中,可维护性成为真正的问题,在我看来,python那里比较弱。

于 2008-10-25T14:01:28.907 回答
24

由于没有人指出 pychecker、pylint 和类似工具,我将:pychecker 和 pylint 是可以帮助您找到错误假设(关于函数签名、对象属性等)的工具。它们不会找到编译器可能在静态类型语言——但他们可以找到此类语言的编译器也找不到的问题。

Python(以及任何动态类型语言)在您可能导致的错误以及如何检测和修复它们方面有着根本的不同。它有明显的缺点和优点,但许多人(包括我)会争辩说,在 Python 的情况下,编写代码的便利性(以及使其结构合理的便利性)和在破坏 API 兼容性的情况下修改代码(添加新的可选参数) ,提供具有相同方法和属性集的不同对象)使其非常适合大型代码库。

于 2008-10-25T15:05:10.720 回答
16

我的 0.10 欧元:

我有几个处于“生产”状态的 python 应用程序。我们公司使用java、c++和python。我们使用 eclipse ide (pydev for python) 进行开发

单元测试是问题的关键解决方案。(也适用于 c++ 和 java)

“动态类型”的不太安全的世界将使您对代码质量不那么粗心

顺便说一句

大规模开发并不意味着您使用一种语言!

大规模开发通常使用少数特定于问题的语言

所以我同意锤子问题:-)


PS:静态类型和python

于 2008-10-25T13:44:41.253 回答
16

这里有一些项目帮助我在 python 中维护了一个相当大的系统。

  • 分层构建代码。即独立的商业逻辑、表示逻辑和你的持久层。花一些时间来定义这些层,并确保项目中的每个人都参与进来。对于大型系统,创建一个迫使您进入某种开发方式的框架也可能是关键。

  • 测试是关键,如果没有单元测试,你可能会以比使用其他语言快几倍的速度结束无法管理的代码库。请记住,单元测试通常是不够的,请确保有几个集成/验收测试可以在任何重大更改后快速运行。

  • 使用快速失败原则。为您认为您的代码可能易受攻击的情况添加断言。

  • 具有标准的日志记录/错误处理,这将帮助您快速定位到问题

  • 使用提供提前输入、pyLint/Checker 集成的 IDE(pyDev 为我工作)来帮助您立即检测常见的拼写错误并推广一些编码标准

  • 小心你的进口,永远不要做 from x import * 或做相对进口而不使用 .

  • 进行重构,带有正则表达式的搜索/替换工具通常是您进行移动方法/类类型重构所需的全部。

于 2008-10-25T15:36:01.470 回答
8

对方法签名的不兼容更改。这在 Python 中不会像在 Java 和 C++ 中那样发生。

Python 在定义方法签名方面具有可选参数、默认值和更大的灵活性。此外,鸭子类型意味着——例如——作为重大软件更改的一部分,您不必从某个类切换到接口。事情没有那么复杂。

您如何找到调用该方法的所有位置? grep 适用于动态语言。如果您需要知道使用方法的每个地方,grep(或等效的 IDE 支持的搜索)非常有用。

由于您没有要查找的静态类型,您如何找出实例提供的操作?

一种。看源头。您无需处理对象库和 jar 文件的 Java/C++ 问题。您不需要这些语言所需的所有复杂的辅助工具和工具。

湾。IDE 可以在许多常见情况下提供签名信息。您可以轻松击败 IDE 的推理能力。发生这种情况时,您可能应该检查您正在做的事情以确保它有意义。如果您的 IDE 无法推断出您的类型信息,那么它可能过于动态。

C。在 Python 中,您经常通过交互式解释器工作。与 Java 和 C++ 不同,您可以直接交互式地探索您的实例。您不需要复杂的 IDE。

例子:

  >>> x= SomeClass()
  >>> dir(x)

你如何处理/防止打字错误? 与静态语言相同:您不会阻止它们。你找到并纠正它们。Java 只能找到某一类拼写错误。如果你有两个相似的类或变量名,你可能会遇到很大的麻烦,即使是静态类型检查。

例子:

class MyClass { }
class MyClassx extends MyClass { }

这两个类名的拼写错误可能会造成严重破坏。[“但我不会把自己放在 Java 的那个位置上,”人们说。同意。我也不会把自己放在 Python 的那个位置上。你制作的课程完全不同,如果被滥用,它们会很早就失败。]

UnitTest 是否用作静态类型检查的替代品? 这是另一种观点:静态类型检查替代了清晰、简单的设计。

我曾与不确定应用程序为什么工作的程序员一起工作。他们无法弄清楚为什么事情没有编译;不知道抽象超类和接口之间的区别,也不知道为什么一个地方的改变会导致一个单独的 JAR 文件中的一堆其他模块崩溃。静态类型检查使他们对有缺陷的设计产生了错误的信心。

动态语言使程序变得简单。简单性是静态类型检查的替代品。Clarity 是静态类型检查的替代品。

于 2008-10-25T17:21:41.690 回答
3

我的一般经验法则是对小型非关键任务项目使用动态语言,对大型项目使用静态类型语言。我发现用诸如 python 之类的动态语言编写的代码会更快地“纠结”。部分原因是用动态语言编写代码要快得多,这会导致捷径和更糟糕的设计,至少在我的情况下是这样。部分原因是当我使用 Java 时,我有 IntelliJ 可以快速轻松地重构,而 python 没有。

于 2008-10-25T15:26:39.480 回答
2

通常的答案是测试测试测试。您应该拥有一个广泛的单元测试套件并经常运行它,尤其是在新版本上线之前。

动态类型语言的支持者认为您无论如何都必须进行测试,因为即使在静态类型语言中,与类型系统的粗略规则的一致性也只涵盖了可能出错的一小部分。

于 2008-10-25T14:24:17.290 回答