是什么让 Perl 代码变得可维护?
我已经编写 Perl 好几年了,它是我首选的文本处理语言(我研究的许多遗传学/基因组学问题很容易简化为文本处理问题)。 Perl 作为一种语言可以非常宽容,并且可以用 Perl 编写非常糟糕但实用的代码。就在前几天,我的朋友说他称 Perl 为一种只写语言:编写一次,理解一次,完成后永远不要尝试回去修复它。
虽然我有时确实因编写糟糕的脚本而感到内疚,但我觉得我也用 Perl 编写了一些非常清晰且可维护的代码。但是,如果有人问我什么使代码清晰且可维护,我将无法给出自信的答案。
是什么让 Perl 代码变得可维护?或者也许更好的问题是是什么让 Perl 代码难以维护?让我们假设我不是唯一维护代码的人,并且其他贡献者(像我一样)不是专业的 Perl 程序员,而是具有编程经验的科学家。
I've been writing Perl for several years now and it is my preferred language for text processing (many of the genetics/genomics problems I work on are easily reduced to text processing problems). Perl as a language can be very forgiving, and it's possible to write very poor, but functional, code in Perl. Just the other day, my friend said he calls Perl a write-only language: write it once, understand it once, and never ever try to go back and fix it after it's finished.
While I have definitely been guilty of writing bad scripts at times, I feel like I have also written some very clear and maintainable code in Perl. However, if someone asked me what makes the code clear and maintainable, I wouldn't be able to give a confident answer.
What makes Perl code maintainable? Or maybe a better question is what makes Perl code hard to maintain? Let's assume I'm not the only one that will be maintaining the code, and that the other contributors, like me, are not professional Perl programmers but scientists with programming experience.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
是什么导致 Perl 代码难以维护?几乎任何使其他程序无法维护的事情。假设除了旨在执行明确定义的任务的简短脚本之外的任何内容,这些是:
$c
不好。$count
更好。$token_count
很好。doWork
的子例程或方法不执行任何操作use MyModule qw(list of import) 显式导入使用的每个符号
。严格
并且不使用警告
等等。
基本上,如果您认为 Perl 是
-f>@+?*<.-&'_:$#/%!
,并且您渴望在生产代码中编写类似的东西,然后,是的,你就会遇到问题。人们往往会将 Perl 程序员为了好玩而做的事情(例如,JAPH、高尔夫等)与优秀的 Perl 程序应该是什么样子混为一谈。
我仍然不清楚他们如何能够在头脑中分离 代码 为IOCCC 来自可维护的 C.
What makes Perl code unmaintainable? Pretty much anything that makes any other program unmaintainable. Assuming anything other than a short script intended to carry out a well defined task, these are:
$c
bad.$count
better.$token_count
good.doWork
doesn't say anythinguse MyModule qw(list of imports)
.strict
and not usingwarnings
etc etc etc.
Basically, if you think Perl is
-f>@+?*<.-&'_:$#/%!
, and you aspire to write stuff like that in production code, then, yeah, you'll have problems.People tend to confuse stuff Perl programmers do for fun (e.g., JAPHs, golf etc) with what good Perl programs are supposed to look like.
I am still unclear on how they are able to separate in their minds code written for IOCCC from maintainable C.
我建议:
但总的来说,您足够关心可维护性并提出相关问题,这一事实告诉我您已经处于一个好的位置并且以正确的方式思考。
I suggest:
But overall, the fact that you care enough about maintainability to ask a question about it, tells me that you're already in a good place and thinking the right way.
我没有使用全部 Perl 最佳实践,但这就是 Damian写它是为了。无论我是否使用所有建议,它们至少都值得考虑。
I don't use all of Perl Best Practices, but that's the thing that Damian wrote it for. Whether or not I use all the suggestions, they are all worth at least considering.
至少:
请参阅 perldoc perlstyle 了解一些通用指南,这些指南将使您的程序更易于阅读和理解,并维持。
At the least:
See perldoc perlstyle for some general guidelines that will make your programs easier to read, understand, and maintain.
对于代码可读性非常重要的一个因素是空白的重要性,这一点我在其他答案中没有提到过,它既与 Perl 无关,又在某些方面与 Perl 相关。
Perl 允许您编写非常简洁的代码,但简洁的代码块并不意味着它们必须全部聚集在一起。
当我们谈论可读性时,空白有很多含义/用途,并非所有这些都被广泛使用,但最有用:
标记周围的空格可以更轻松地在视觉上分隔它们。
这个空间在 Perl 中尤为重要,因为即使在最佳风格的 Perl 代码中也普遍存在行噪声字符。
我发现
$myHashRef->{$keys1[$i]}{$keys3{$k}}
在生产紧急情况下的凌晨 2 点与间隔时间相比可读性较差:$myHashRef->{ $keys1[$i] }->{ $keys3{$k} }
。作为旁注,如果您发现您的代码执行大量以相同根开头的深层嵌套引用表达式,那么您绝对应该考虑将该根分配给临时指针(请参阅 Sinan 的评论/答案)。
一个部分但非常重要的特殊情况当然是正则表达式。 因此我不会进一步延长这篇文章,除非有人在评论中请求示例。
缩进正确且均匀。噢。明显地。然而,我看到太多的代码由于蹩脚的缩进而 100% 不可读,而且当一半代码由一个使用 4 个字符制表符的编辑器使用制表符缩进的代码和另一个使用 8 个字符制表符的编辑器的人用制表符缩进时,可读性更差。只需将你该死的编辑器设置为软(例如空间模拟)TAB,不要让其他人痛苦。
逻辑上独立的代码单元周围的空行(块和行集)。你可以用 1000 行好的 Perl 编写一个 10000 行的 Java 程序。现在,如果您在这 1000 行中添加 100-200 行空行以使内容更具可读性,那么您就不会像 Benedict Arnold 那样了。
将超长表达式拆分为多行,紧接着...
正确的垂直对齐方式。见证之间的区别:
和
和
就我个人而言,我更喜欢通过对齐 LHS 和 RHS 来进一步修复垂直对齐(这在长 SQL 查询的情况下尤其可读,而且在 Perl 代码本身中,无论是像这样的长条件语句还是多行语句)赋值和哈希/数组初始化):
顺便说一句,在某些情况下,通过首先不使用如此长的表达式,可以使代码更具可读性/可维护性。例如,如果
if(){}
块的内容是return
,则执行多个if/unless
语句,每个语句都有一个 return块可能会更好。One factor very important to code readability that I haven't seen mentioned in other answers is the importance of white space, which is both Perl-agnostic and in some ways Perl-specific.
Perl lets you write VERY concise code, but consise chunks don't mean they have to be all bunched together.
White space has lots of meaning/uses when we are talking about readability, not all of them widely used but most useful:
Spaces around tokens to easier separate them visually.
This space is doubly important in Perl due to prevalence of line noise characters even in best-style Perl code.
I find
$myHashRef->{$keys1[$i]}{$keys3{$k}}
to be less readable at 2am in the middle of producion emergency compared to spaced out:$myHashRef->{ $keys1[$i] }->{ $keys3{$k} }
.As a side note, if you find your code doing a lot of deep nested reference expressions all starting with the same root, you should absolutely consider assigning that root into a temporary pointer (see Sinan's comment/answer).
A partial but VERY important special case of this is of course regular expressions. The difference was illustrated to death in all the main materials I recall (PBP, RegEx O'Reilly book, etc..) so I won't lengthen this post even further unless someone requests examples in the comments.
Correct and uniform indentation. D'oh. Obviously. Yet I see way too much code 100% unreadable due to crappy indentation, and even less readable when half of the code was indented with TABs by a person whose editor used 4 character tabs and another by a person whose editor used 8 character TABs. Just set your bloody editor to do soft (e.g. space-emulated) TABs and don't make others miserable.
Empty lines around logically separate units of code (both blocks and just sets of lines). You can write a 10000 line Java program in 1000 lines of good Perl. Now don't feel like Benedict Arnold if you add 100-200 empty lines to those 1000 to make things more readable.
Splitting uber-long expressions into multiple lines, closely followed by...
Correct vertical alignment. Witness the difference between:
and
and
Personally, I prefer to fix the vertical alignment one more step by aligning LHS and RHS (this is especially readable in case of long SQL queries but also in Perl code itself, both the long conditionals like this one as well as many lines of assignments and hash/array initializations):
As a side note, in some cases the code could be made even more readable/maintainable by not having such long expressions in the first place. E.g. if the contents of the
if(){}
block is areturn
, then doing multipleif/unless
statements each of which has a return block may be better.我认为这是一个人们被告知 Perl 不可读的问题,他们开始对自己代码的可维护性做出假设。如果您足够认真地将可读性视为高质量代码的标志,那么这种批评很可能不适用于您。
大多数人在讨论可读性时都会引用正则表达式。正则表达式是嵌入在 perl 中的 dsl,您可以读取也可以不读取它们。如果有人不能花时间去理解对许多语言来说如此基本和重要的东西,我不关心试图弥合一些推断的认知差距......他们应该振作起来,阅读 perldocs,并在必要时提出问题。
其他人会引用 Perl 对短格式变量的使用,例如 @_、$!等等,这些都很容易消除歧义...我对让 perl 看起来像 java 不感兴趣。
所有这些怪癖和优点的好处是,用该语言编写的代码库通常简洁紧凑。我宁愿读十行 Perl,也不愿读一百行 Java。
对我来说,“可维护性”不仅仅是拥有易于阅读的代码。编写测试、做出断言...尽一切努力依靠 Perl 及其生态系统来保持代码正确。
简而言之:编写程序首先是正确的,然后是安全的,然后是性能良好的......一旦实现了这些目标,然后担心是否能舒服地蜷缩在火边。
i see this as an issue of people being told that perl is unreadable, and they start to make assumptions about the maintability of their own code. if you are conscientious enough to consider readability as a hallmark of quality code, chances are this critique doesn't apply to you.
most people will cite regexes when they discuss readability. regexes are a dsl embedded in perl and you can either read them or not. if someone can't take the time to understand something so basic and essential to many languages, i'm not concerned about trying to bridge some inferred cognitive gap...they should just man up, read the perldocs, and ask questions where necessary.
others will cite perl's use of short-form vars such as @_, $! etc. these are all easily disambiguated...i'm not interested in making perl look like java.
the upside of all of these quirks and perlisms is that codebases written in the language are often terse and compact. i'd rather read ten lines of perl than one hundred lines of java.
to me there is so much more to "maintainability" than simply having easy-to-read code. write tests, make assertions...do everything else you can do to lean on perl and its ecosystem to keep code correct.
in short: write programs to be first correct, then secure, then well-performing....once these goals have been met, then worry about making it nice to curl up with near a fire.
我想说的是包装/对象模型,它反映在 .pm 文件的目录结构中。为了攻读博士学位,我编写了很多 Perl 代码,之后我又重复使用这些代码。它用于自动 LaTeX 图表生成器。
I would say the packaging/object models, that gets reflected in the directory structure for .pm files. For my PhD I wrote quite a lot of Perl code that I reuse afterwards. It was for automatic LaTeX diagram generator.
我将谈论一些积极的事情来使 Perl 易于维护。
确实,您通常不应该太聪明地使用像
return !$@;#%
之类的非常密集的语句,但要聪明地使用列表处理运算符,例如map
和grep
以及 list-context 从split
之类的操作符返回,以便以函数式风格编写代码可以做出积极的贡献可维护性。在我的上一个雇主中,我们也有一些以类似方式工作的时髦哈希操作函数(hashmap
和hashgrep
,尽管从技术上讲,我们只向它们提供偶数大小的列表)。例如:另请参阅高阶 Perl、http://hop.perl.plover.com - 如果您可以防止元编程本身妨碍的话,充分利用元编程可以使定义任务更加连贯和可读。
I'll talk some positive things to make Perl maintainable.
It's true that you usually shouldn't get too clever with really dense statements a la
return !$@;#%
and the like, but a good amount of clever using list-processing operators, likemap
andgrep
and list-context returns from the likes ofsplit
and similar operators, in order to write code in a functional style can make a positive contribution to maintainability. At my last employer we also had some snazzy hash-manipulation functions that worked in a similar way (hashmap
andhashgrep
, though technically we only fed them even-sized lists). For instance:See also Higher Order Perl, http://hop.perl.plover.com - good use of metaprogramming can make defining tasks more coherent and readable, if you can keep the metaprogramming itself from getting in the way.