关于模块长度推理和文档字符串与代码行比率的 Pylint 消息

Pylint message about module length reasoning and ratio of docstrings to lines of code

我知道这可能会因为基于意见而被驳回,但谷歌搜索没有找到我希望的资源,我正在寻找指向 Python 中任何已建立和商定的最佳实践的链接社区。

我是一名中级 Python 程序员,所在组织的历史非常糟糕,曾用有史以来发明的每种语言编写混淆代码。我真的很想树立良好编程风格和实践的榜样。为此,我遵循 PEP 8,运行 pylint 我写的所有东西,并深入思考它的每一个建议,而不是简单地驳回它们。我已将较长、复杂的方法分解为较短的方法,部分原因是它的建议。我还按照这种风格编写了详细的文档字符串:http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html

我面临的一个挑战是,虽然我不是组织中唯一的 Python 程序员,但我似乎是唯一认真对待这些事情的人,而我的同事们似乎并不例如,注意未记录的重复代码,其命名不遵循任何特定模式。所以我不认为让他们审查我的代码或向他们学习是我最好的选择。

我刚从 pylint 收到第一条 "Too many lines in module" 消息。我还没有写完这个模块——我想在现有的 class 中至少再添加一个 class 和几个方法。我知道这个想法是模块应该 "do one thing" 但 "thing" 尚未完全实现。

以下是 pylint 给我的一些统计数据:

+---------+-------+-----------+-----------+------------+---------+
|type     |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module   |1      |1          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|class    |3      |3          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|method   |27     |27         |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|function |2      |2          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+

+----------+-------+------+---------+-----------+
|type      |number |%     |previous |difference |
+==========+=======+======+=========+===========+
|code      |266    |24.98 |266      |=          |
+----------+-------+------+---------+-----------+
|docstring |747    |70.14 |747      |=          |
+----------+-------+------+---------+-----------+
|comment   |41     |3.85  |41       |=          |
+----------+-------+------+---------+-----------+
|empty     |11     |1.03  |11       |=          |
+----------+-------+------+---------+-----------+

我真的不认为 266 行代码对于一个模块来说太多了。我的文档字符串占模块中行的 75% - 这是标准吗?我的文档字符串非常重复,因为我的方法是对数据的小操作。每个文档字符串都倾向于声明,例如,一个参数是一个 pandas 数据框,并列出数据框的必需和可选列及其含义,并且在对数据框执行任何操作的每个方法或函数中重复.

我似乎在这里犯了某种系统性错误吗?是否有阅读指南以改进我的代码?我的文档字符串太长了吗?是否存在过长的文档字符串之类的东西?我应该简单地禁用 pylint 模块太长消息并继续我的生活吗?

哇,好问题。想要编写高质量代码的愿望真的不那么普遍。不过,关于您的同事的一些建议。不要否定他们的观点。他们可能无意做坏事,但你必须以某种方式将软件质量的理念与他们的价值理念联系起来。花时间与人们谈论您编写的代码并不仅仅是您从经验中获得的东西。影响组织尊重和追求软件质量对于您对公司绩效产生任何持久影响是必要的。否则,你写的代码再好也无济于事。抱歉,顺便说一句;我知道这不是你的问题。

在某些语言中,例如 Java,一个文件中只有一个 class 并且将该文件命名为与它包含的 class 相同的名称是正常的。这在 Python 中是不正常的,但我认为它提供了一些很好的指导。您希望代码易于浏览,这需要在尽可能紧密地将事物放在一起和组织它们之间取得平衡,这是我们将事物分开的主要原因。因此,您可以首先回顾与您的问题 space 相关的这两个问题,以及您的代码中的想法与您的问题 space.

中的想法的一致性如何。

我使用文档字符串,但我没有尝试使用 sphinx 或 restructured 或 latex 来制作它们。我在一个使用 Doxygen 的大型代码库中工作,但老实说,我并没有在评论中投入太多精力来使用该工具的功能,尽管我偶尔会查看 Doxygen 文档以查看是否缺少某些内容。我以前使用过类似表单的编码风格,但我并没有真正相信文书工作会带来价值。在您的评论中所追求的重要事项与您在设计和实施中所追求的相同,那就是理解。每个评论中的每个词对理解有什么帮助。我不想要像 Name、Parameter、Return 这样无价值的填充词……我的意思是,我想要,但只是不情愿地因为我希望人们预先告诉我他们的界面是什么。我将所有这些填充词视为我愿意容忍的文书工作。我认为这是一个陷阱,让人们觉得好的注释会产生好的代码。他们有帮助,但通常,如果我觉得我必须发表评论,就会发生以下两种情况之一:它是一个界面或它是一个设计缺陷。如果我必须评论一些不是接口的东西,那可能意味着我的设计不是很清楚,或者我的实现变得混乱,因为我懒得弄清楚如何让每个函数做一件事。如果我再来这里,我可能会把它清理干净。

没有看到你的代码,我无法就如何使其高质量提供太多建议,但考虑一下你如何定义可能会有所帮助 "software quality." 我将其定义为 "how easy the code is to change." 这个取决于代码可能需要的更改类型,这意味着评估代码的质量确实必须包括对可能需要的内容的一些预期。与直觉相反,实际上让您的代码更容易更改通常涉及不尝试实现现在不需要的任何东西。即便如此,我也经常会在稍有挑衅的情况下实施一些事情,尤其是在Python。对于 example,实现 str 方法是个好主意;通过实现 eqnehash 使您的对象可散列甚至更酷,因为这允许您可以将您的对象用作字典中的键或集合的成员。

另一个(有点随意)的建议是要警惕面向对象的思维。它有很多好处,但也有一些陷阱。例如,不要创建像 get_thing(self) 这样的函数。最好有一个属性,如果你需要做额外的工作,你可以做一个@属性 getter setter,这仍然会给调用者留下一个简单的属性访问,更简洁。我发现刚刚学习了一些面向对象思想的人倾向于认为制作大量的 get 和 set 方法是一件好事,但我更喜欢将状态完全排除在设计之外,如果可以的话,所有这些 get 和 set方法暗示对象的状态。

@ChipJust 在评论中给出了很好的回答,所以我将求助于列表:

  • 注释很棒,但是一旦您需要那么多注释,代码结构可能会出现问题

  • 通常,您需要在任何模块入口点中使用详细的文档字符串,例如记录您向其他人公开的 API,但不一定是整个代码

  • 单元测试在您的组织中扮演什么角色?你不能只用文档字符串来争取质量,测试也很有用。当测试失败、文档字符串死亡或 missed/outdated 静默时,测试也会很明显。