是否可以使表示计算的长代码更易于阅读?


9

长方法通常被认为是不好的,但是在我的代码中,我有一些难以理解的长方法(超过50行)。我很难使这些方法更容易阅读,因为里面的一条语句已经超过了50行,而且难以理解的一条语句是使用ORM建立数据库查询来完成某些特定的工作在方法名称上明确指出。该语句之所以这么长是因为它在多个列上联接,应用多个wheres并选择多个不同的列以形成所需的文档化输出格式。

这样难读的代码是否被视为错误代码?同样,如果我为复杂的算法编写代码,导致难以理解的代码包装在一个清晰命名的方法中,那么该代码是否是错误代码?


您是否可以通过某种方式对查询进行参数化设置?我猜想这个查询会根据创建的方法内部发生的变化而变化。也许您可以将其分解成较小的部分,然后按几个步骤进行构造,以使其更易于阅读。
Zalomon

您的ORM是否支持视图?您可以将(一组)联接提取到视图中,然后选择视图。即使视图未在其他地方使用,也可以帮助分解一条大型SQL语句
Caleth,2015年

您的ORM是否支持类似SQL的查询语言?如果是,则可以将查询移至其自己的文件并为其启用IDE语法突出显示。在您的应用程序中,从文件中加载查询。如果您的IDE不完全支持该特定查询语言,那么您可能会喜欢SQL格式,即使这可能并不完美。但是,良好的格式可大大提高可读性。这还具有易于将查询复制到暂存器并在那里进行修改的优点。
SpaceTrucker

Answers:


17

你写了

这样难读的代码被认为是错误代码吗?

因此,您肯定会同意它是很难阅读的代码,并且如果很难阅读,则很难维护和发展-因此,我想您会以自己的方式认为该代码是“不好的”。但是,有时改进50行SQL语句之类的东西并不明显。简单的“提取方法”重构无效,并且您可能不知道从哪里开始使代码更具可读性。对于这些情况,您仍然可以尝试以下一种或全部方法

  • 向代码显示比您更有经验的其他人来清理代码。如果您的组织中没有人可以询问,请尝试codereview.stackexchange

  • 尝试谷歌的具体问题。对于您的示例,诸如“清理长的sql语句”之类的内容可能是一个好的开始。您会惊讶地发现有多少关于该主题的文章,即使您找不到适合自己的案例的死因食谱,也可能会得到一些新鲜的想法。

  • 与其为无法做的事情寻求理由,不如将精力集中在可以至少清理一点代码的事情上,例如添加适当的换行符,适当的缩进,添加一些解释性注释,使某些变量更好名称。在此过程中,强迫自己重新阅读代码的细节并非没有可能,您发现了一种将代码重构为较小单元的方法

  • 练习练习 “干净的编码”不是您一天就能学到的东西,有了更多的经验,它会变得更容易。也许您今天没有找到解决问题的方法,但是几个月后再回到代码中,对您来说,情况将有所不同。


我有点不同意注释部分,如果代码中有一个复杂的部分很复杂,因为它不能以其他方式出现,并且没有找到简化它的方法,那么注释不太可能对正在做的事情有一个大的了解。用一些图表记录它会更好。并留有引用该外部文档的注释。当然,这些情况必须是例外的,因为我们知道很少维护外部文档,因此,数量越少越好。对于其余部分,一如既往的好答案。
Walfrat

@Walfrat:我的意图是提供有关该过程的一般指南,而不是专门针对“ 50行SQL代码”,而不是作为所有潜在方法的“即开即用”解决方案。
布朗

我知道,我只是想建议,如果经过多次审查后无法简化(无论如何),注释很可能无助于使问题变得复杂,因此可能需要最少的外部文档。在数据库查询的特定情况下,通过显示一个图表显示查询的每个部分如何相互关联,这甚至更加容易。
Walfrat

4

难读并不坏-不必要地难读是不好的。

有些事情困难的。在这种情况下,您需要完全理解问题,编写代码并对其进行尽可能详尽的注释,以便下一位开发人员有机会。

但是有些事情仅是困难的,因为您使它们变得困难。如果可以简化问题并简化问题,请简化它。如果很难理解,但可以合理地分解为子问题,则将其分解为子问题以简化它。


究竟。尽力使代码自我记录,然后使用注释来填补空白。(编辑:发表评论后,我意识到OP是指ORM数据库查询,而不是SQL。)
Kyle A

1

ORM创建报告?认真吗 学习一些SQL,伙计。程序语言在这种情况下很糟糕。

SQL是一种设计得更好的语言,可以处理复杂的联接和选择。即使您无法使SQL看起来漂亮,也可以使用各种可视化工具,在其中可以将数据库对象拖放到图表上,然后将为您生成SQL。更不用说您将能够调整和优化查询,查看其查询计划,获得平台建议其他索引选项的方法,等等。这只是更加灵活。

我确定这里有些人会不同意我的观点,但是ORM不适用于复杂的报告目的。如果有可能的话,我会考虑远离它,而转向结构化查询语言。


2
老实说,您不喜欢ORM的事实与该问题完全无关。
布朗

我喜欢ORM很好。我要说的是,当代码“在多列上连接,应用多个wheres并选择多个不同的列以形成所需的文档输出格式”时,它们不是一个好工具,这是本​​主题的主题。
John Wu

0

通常,在任何地方都很难阅读代码,即使您是唯一的维护者,也不是一个好主意。我已经发生过几次返回某些代码年甚至几周后的事情,发现很难动弹了。

如果您需要在单个查询中做很多事情,请尝试将其与带有嵌入式注释的行分开:

query(join(map(condition1, condition2), blah, blah, something(bah, blah, blah))) 

成为:

// Why are we doing such an awful single query rather than a sequence of selects?
query( // Description of query
  join( // Why are you doing a join here
    map( // Why a map
      condition1, // What is this
      condition2  // And this
   ), // End Map
   blah, // What, Why?
   blah, // What, Why?
   something( // What does this do?
      bah, // What, Why?
      blah, // What, Why?
      blah // What, Why?
      ) // End Something
   ) // End Join
) // End Query

我对你的榜样含糊不清。注释应解释代码为何如此。在什么应该由标识符表示...
蒂莫西脚轮

@TimothyTruckle我同意标识符应该清楚地标识它们是什么,但是通常在标准代码中它们都不清楚—在记录字段名称的情况下,由于历史的限制,常常缺乏清晰度。我遇到的情况是字段名称限制为5个字符,所有字符均必须为大写ASCII字母,并且由于兼容性要求(例如,使用MDs最喜欢的报告工具)
Steve Barnes

0

除了@DocBrown的出色回答外,我认为值得认识到没有人一直都在编写“好的”代码。编码在权衡取舍,通常最好接受您编写的内容比您想写的要少一些的内容,然后再回来讨论。重构是随着时间的推移改进代码的过程-以我的经验,那才是一个好的代码基础,而不是“第一时间正确”。

然后您在应用程序级别而不是单个方法/代码行级别评估代码。因此,如果您有一个复杂的方法,但是它的名称很明确,只要该方法具有内聚性,我认为您就不会有“不好的”代码。

命名是使代码易于理解的最大武器-为您的方法命名,以便人们在阅读您的代码时可以跳过主体。命名变量等,这意味着读者无需阅读赋值语句就可以看到它们的含义。

接下来的事情是确保您的方法确实只做一件事-副作用使代码难以理解。因此,如果您的方法返回输出格式的数据,那么它也不应将数据库的状态更新为“已打印”或其他任何形式。

下一步是分层/组件化-如果您有一堆生成ORM结果的复杂方法,请将它们捆绑在一起,以便您的代码阅读器可以假定它们的行为均相同,没有副作用等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.