Perl需要更好的工具

Perl有变成一种过时语言的危险——新程序员在大学里学习Java和Python,像Google这样的公司几乎根本不用Perl。如果你担心Perl可能在中到大型项目中变得无关紧要,那么请继续阅读。

令人担忧的部分

我与目前使用Perl并对其未来感到担忧的公司经理进行了讨论,发现他们担心Perl的未来。我在这家旧金山的公司讨论了他们正在用Java重写其核心应用程序。另一家公司担心他们将来找不到新的Perl程序员。还有一家公司使用Perl进行大型项目,但苦于难以重构其庞大的代码库。

公司关心Perl未来的原因有很多。我提供了一部分解决方案:更好的Perl工具可以成为保持Perl作为中大型项目主要语言的关联性和有效性的重要部分。

在衡量开发环境(人员、语言、工具、流程等)的有效性时,一个关键的衡量指标是修改现有代码的成本和痛苦程度。一旦项目或系统发展到成千上万行代码,分布在几十(或几百)个模块中,修改成本可能会上升到团队害怕进行任何重大改变的点。优秀的工具是避免这种不幸情况或至少减少其影响的一种方式。其他因素是优秀的流程,当然还有优秀的人员。

21世纪的Perl集成开发环境

我认为,更多的、高质量的开发工具将有助于保持Perl在中型和大型项目环境中的关联性和活力。本文的重点在于IDE,即集成开发环境,主要是指具有图形界面的那些。

IDE是一个集成的编程工具套件,将源代码编辑器与各种其他工具结合成一个单一的包。现代IDE的常见功能包括重构支持、版本控制、实时语法检查以及键入时的代码自动完成。

我想要明确指出,一支技艺高超的Perl程序员团队,仅使用多年来一直存在的工具(如emacsvicvsmake)可以,并且确实能构建大型、复杂且成功的项目。我不担心那些程序员。我担心的是那些有一到五年经验的大型程序员群体,以及那些尚未开始编程的人:下一代的Perl程序员。

优秀的工具不能使一个糟糕的程序员变成一个好的程序员,但它们确实可以使一个优秀的程序员更出色。不幸的是,Perl的工具在其他语言(尤其是Java)中已经落后很多年。

一个强有力的例子是,Perl缺乏具有优秀重构支持的图形IDE。几个Java IDE具有广泛的重构支持。只有一个是Perl的,即Eclipse的EPIC插件,它甚至只支持一个重构操作。

以下是一个优秀的IDE如何激发至少一个Perl开发者的例子,请参阅Adam KennedyPerl.com关于他的新PPI模块的文章以及Scott Sotka的Devel::Refactor模块(在EPIC中使用)。

我承认图形化IDE并非所有好工具的全部。就像有些作家拒绝文字处理软件,而选择打字机或手写稿件一样,有些程序员也拒绝图形化IDE,甚至拒绝那些要求他们使用IDE的工作。并非每个人都应该有相同的工具集,有些事情铅笔能做而vi和emacs永远做不到。话虽如此,IDE在企业中用于大型项目时得到了广泛的应用,并且对于许多程序员和团队来说,它们提供了极大的生产力提升。

另一个重要的观点是,尽管本文讨论了十几种特定的工具或功能,但将所有工具集成在一个单一包中能产生最大的价值。一个提供所有这些功能,人们可以轻松安装、扩展和维护整个开发团队的IDE,比其各个部分的总和更有价值。

当一个IDE在安装时立即提供所有或几乎所有这里讨论的工具和功能,并且这些功能“了解”彼此时,这是一个巨大的优势。例如,如果你输入了一个不存在的子例程名称,实时语法检查器能够捕捉到这一点是很好的。如果代码辅助功能随后弹出一个上下文菜单,提供为子例程创建存根或更正名称为当前文件中可用的类似子例程或方法的功能,那就更好了。(这是某些Java IDE的标准行为。)

21世纪的Perl工具集应该包含什么?

Perl需要几个优秀的IDE——而不仅仅是几个,以便人们有更多的选择。Perl应得到并需要一些优秀的IDE,这些IDE能领先于其他语言的IDE,设定标准。

我非常清楚Perl的动态特性使得编写一个可以读取和理解Perl程序(尤其是大型且复杂的程序)的程序更加困难,但理解Perl程序的困难使得这类工具的价值更大,我相信Perl社区能够克服Perl的一些内置挑战。实际上,Perl最伟大的优势之一就是Perl用户可以将语言适应他们的需求。

一个优秀的Perl IDE至少应包含以下内容,以及其他我没有想到的功能。(当然,还有很多这样的功能!)

本文中的大部分屏幕截图示例都使用了EPIC Perl IDE。目前,它具有我最长列表中的大部分功能(尽管它当然不是所有功能都有)。

语法着色文本编辑器

你们中的大多数人可能都见过这个。它可以在 vimemacs、BBEdit 和 TextPad 中使用。几乎每个像样的文本编辑器都会将源代码着色,使得关键词、操作符、变量等各自具有自己的颜色,从而更容易发现语法错误,例如忘记关闭引号对。

实时语法检查

实时语法检查示例 图1. 实时语法检查

图1中的IDE显示,第4行由于缺少 ) 而有错误,而第5行由于没有声明 $naame(并且 use strict 作用中)而有错误。

这里的关键点是IDE会在你保存和编译代码之前立即显示这些错误。(在这个例子中,EPIC IDE 允许你指定语法检查的运行频率,从0.01到10.00秒的空闲时间,或者仅在请求时运行。)

尽管这很棒,但如果IDE还能提供解决问题的方法会更好,例如,提供将 $naame 改为 $name 的选项。图2显示了这样做的一个IDE;不幸的是,对于Java而不是Perl。

IDE中的语法帮助 图2. IDE中的语法帮助

如果Perl IDE提供了这种帮助将非常好。

版本控制集成

所有非疯狂的大型项目都使用版本控制软件。最常用的版本控制软件系统可能是CVS、Perforce、Subversion和Visual SourceSafe。图3显示了IDE将本地文件与CVS存储库中的旧版本进行比较。

Figure 3
图3. 将本地文件与CVS中的旧版本进行比较--点击图片查看全尺寸截图

CVS集成在许多现代代码编辑器中可用,包括 emacsvim 和 BBEdit,以及像Eclipse和Komodo Pro这样的图形IDE。Subversion集成作为Eclipse的插件提供;Komodo Pro支持Perforce和Subversion。

代码辅助编辑器

假设你已经输入了一个对象引用,并想在该对象上调用一个方法,但你不确定方法名是什么。如果编辑器弹出一个列出该对象所有可用方法的菜单,那不是很好吗?它可能看起来像图4。

自动代码补全 图4. 自动代码补全

在这个例子中,IDE能够确定对象 $q 的实例所属的类,并列出可用方法的名称。如果你输入一个 p,那么列表只显示以 p 开头的方法名。如果你输入 pa,那么列表只显示 param()parse_params() 方法。

出色的重构支持

重构越容易,人们就会越经常进行重构。以下列表包含了最常见的重构。你个人的列表可能会有所不同。所有这些都是你可以手动完成的事情,但目的是将它们变成一两个点击操作,这样你就可以更频繁地进行它们。(有关重构操作的详尽列表,请参阅 Martin Fowler的按字母顺序排列的重构列表。)

提取子程序/方法

IDE应创建一个新的子程序,使用选定的代码,并用对新子程序的调用替换选定的代码,并带有适当的参数。以下是从Eclipse/EPIC(使用Devel::Refactor模块)中提取子程序重构的示例。

首先,您选择一段代码将其转换为新的子例程,然后从上下文菜单中选择“提取子例程”。随后,您将看到一个对话框,要求输入新子例程的名称(如图5所示)。

提取子例程重构前的代码 图5. 提取子例程重构前的代码

IDE将所选代码替换为新子例程的调用,并对参数和返回值做出合理猜测(如图6)。您可能需要手动清理结果。

提取子例程重构后的代码 图6. 提取子例程后的代码

图7显示了IDE创建的新子例程。在这种情况下,它不需要更改,但有时您可能需要调整参数和/或返回值。

提取子例程创建的新子例程 图7. 提取子例程创建的新子例程

理想情况下,编辑器应提示您用新子例程的调用替换类似的代码块。

重命名子例程/方法

IDE应找到项目中对子例程的所有调用,并为您提出更改建议。您应该能够预览所有可能发生更改的地方,并逐个接受或拒绝。此操作应该是可撤销的。

重命名变量

与重命名子例程一样,此功能应在整个项目中查找所有出现并为您提出更改建议。

更改子例程/方法签名

IDE应能够合理猜测每个子例程或方法调用是否提供了正确的参数。部分原因是启用上述提到的实时语法检查,部分原因是使您能够选择子例程声明,并告诉IDE您想要通过添加或删除参数来重构它。然后,IDE应提示您进行更改,尽力找到所有现有的子例程调用,并建议更正子例程调用以提供新参数。

显然,这在Perl中特别棘手,在Perl中,子例程从@_中获取参数。因此,IDE必须仔细查看代码如何使用shift@_$_[],以便对子例程期望的参数做出合理的猜测。然而,在许多常见情况下,Perl IDE可以对参数做出合理的猜测,如下面的两个示例所示,因此,如果您添加或删除一个参数,它可以立即提示您在整个项目中进行更正。

sub doSomething {
    my $gender = shift;
    my $age    = shift;
    # Not too terribly hard to guess that $gender and $age are params
}

sub anotherThing {
    my ($speed,$direction) = @_;
    # No magic needed to guess $speed and $direction are params.
}
移动子例程/方法

此重构操作应提供列表或对话框,以便您在项目中选择目标文件。IDE应允许您预览它为实现移动而进行的所有更改,包括更新对子例程/方法的调用以使用正确的类。至少,IDE应向您显示或列出所有对子例程的调用,以便您可以自行进行适当的更改。理想情况下,IDE应猜测可能的目标;例如,如果$self是移动的方法的参数,那么IDE可能会假设该方法是一个对象(实例)方法,并最初仅列出继承自源类或从源类继承的目标类。

更改包名

与重命名子例程和重命名变量一样,在更改包名时,IDE应提供更新项目中对所有现有引用的建议。

源文件和资源树的查看与导航

优秀IDE的一个有用特性是能够以树形格式查看一个项目或多个项目的所有代码,您可以对文件夹内容进行“折叠”和“展开”。所有现代图形IDE都支持这一点,甚至可以处理不同语言的多个项目。

以这种方式查看您的项目,您将获得高级概述并能够深入到特定的文件,通过一些文件夹显示内容而另一些不显示,以混合详细程度。

例如,图8显示了ActiveState的Komodo IDE的部分屏幕截图。

Komodo中的代码树视图 图8. Komodo中的代码树视图

创建和运行单元测试的支持

任何从CPAN安装过Perl模块的人都已经看到过单元测试——这些是在安装过程中执行make test部分时运行的各个测试。绝大多数CPAN模块都包含一组测试,通常使用Test::Harness和/或Test::More模块。一个优秀的IDE会使得在开发项目时创建和运行单元测试变得非常容易。

IDE对单元测试最基本的支持形式就是简单地让它能够从IDE中执行任意脚本。为您的项目创建一个test.pl文件,并在开发过程中不断向其中添加测试,或者添加到t/子目录中,并在做出更改时运行脚本。所有现代IDE都至少提供这种最小功能。

对单元测试的更高级支持可能类似于Java IDE中JUnit测试的特性,您可以选择一个现有的类文件(Perl中的.pm文件)并让IDE为文件中的每个子程序创建一组存根测试。(有关单元测试的更多信息,请参阅JUnit和Perl模块Test::Unit。)此外,IDE应支持运行一组测试,并提供简单的视觉反馈以显示哪些通过了/失败了。JUnit世界中的标准做法是显示一个“绿色条”(所有通过)或“红色条”(有失败)并允许您查看失败的详细信息。其他一些令人愉悦的功能包括计算代码覆盖率,提供测试的统计摘要等。

图9显示了使用Eclipse成功运行的Java测试套件。

JUnit测试运行,成功 图9. 成功的JUnit测试运行

图10显示了相同的测试运行,这次是失败的。

JUnit测试运行,有失败 图10. 有失败的JUnit测试运行

失败消息的堆栈跟踪出现在窗口的另一部分(此处裁剪以节省空间)。如果您双击失败的测试(testInflate),IDE将打开文件(在本例中是BalloonTest)并导航到测试函数。

核心思想是,IDE应使添加、修改和运行测试尽可能不痛苦,这样您在开发过程中就会做更多。

语言特定的帮助

这是一个相当直接的想法——IDE应该能够找到并显示代码中任何关键字的适当文档,所以如果您突出显示push并请求帮助,您应该看到Perl文档中的push条目。如果您突出显示导入模块中的方法、子程序或其他符号名称,IDE应显示所选项目的模块文档。当然,这要求文档以一致、机器可读的形式提供,这并不总是事实。

具有实时结果显示的调试器

所有现代集成开发环境(IDE)都提供在调试器下运行代码的支持,通常包括可视化显示正在发生的事情,包括变量的状态。《Komodo IDE支持调试在本地或远程运行的Perl。

IDE中调试的典型支持包括设置断点、监视变量状态等。基本上,IDE应提供对调试器所有功能的支持。图形IDE应提供正在发生的事情的可视显示。

自动代码格式化

这意味着自动或按需重缩进和其他代码格式化。例如,当您剪切和粘贴一大块代码时,IDE应支持将该代码块重格式化为与新位置匹配的缩进。如果您更改每个缩进级别的空格或制表符数量,或者更改大括号放置的约定,那么IDE应支持调整整个文件或项目中的所有文件。

无缝处理多种语言

许多大型软件项目涉及多种语言。这在网络应用中几乎是普遍现象,其中用户界面通常使用HTML、CSS和JavaScript,后端使用Perl、PHP、Java、Python、Ruby等语言之一或多个。拥有无缝集成所有语言工作的开发工具非常有帮助。这变得越来越普遍。例如,Komodo和Eclipse都支持多种语言。

自动构建和测试

此功能可能非常基本,通过在IDE中轻松运行任意脚本并查看其输出来实现。这可以简单到配置IDE以一键运行传统的Perl模块构建和测试命令。

$ perl Makefile.PL
$ make
$ make test

此功能的更高级版本可能涉及IDE创建存根代码以测试现有文件中的所有子例程,或在指定目录下使用Test::Harness运行所有脚本,或使用Test::Unit::TestRunnerTest::Unit::TkTestRunner运行一系列测试。(后者提供GUI测试框架。)

结论和建议

虽然有许多工具可以帮助Perl开发,但Perl工具箱的当前状态仍落后于其他语言几年——与Java工具相比,可能落后三到五年。虽然有几个Java工具具有上述所有功能,但几乎没有Perl工具具有所有这些功能。另一方面,事情正在好转;现在比一年前要好。有可能在一年或两年内缩小这个差距。

可以相对容易地改进的两个明显领域是向EPIC和Komodo添加更多功能。EPIC是开源的,因此可能有一更大的才能池可以贡献。另一方面,Komodo有一个有资金支持的公司,人们实际上会得到报酬来改进它。希望这两个工具都会随着时间的推移而变得更好。

另一个有趣的可能是开发新的IDE或在现有IDE中使用Adam Kennedy的PPI模块对其进行扩展,该模块能够将Perl文档解析成合理的抽象语法树,并操作元素和重新组合文档。有一个新的Perl编辑器项目,VIP正在设计阶段,旨在“可插拔”并具有支持结对编程的特殊功能。

最后,我收集了一些与相关材料相关的链接列表。下面的第一个列表包括Perl的IDE和图形编辑器,第二个列表包括各种相关文章和网站。希望这些都很有启发性并有所帮助。

当前Perl IDE

列出的IDE支持Perl。该列表无疑是不完整的,但应成为任何希望进一步了解此内容的良好起点。

  • Affrus

    仅限Perl,仅限Mac OS X。闭源(因此用户无法扩展)。主要用于CGI和独立脚本。提供免费演示。购买价格为$99。(参见Perl.com对Affrus的评测以了解更多信息。)

  • Eclipse/EPIC

    EPIC是Eclipse平台的一个插件。Eclipse是开源和跨平台的(Windows/Mac/Linux/Solaris等)。一旦安装了Eclipse,请使用EPIC更新URL,在Eclipse应用程序内部安装EPIC插件。Eclipse支持Java,并通过插件支持C/C++、COBOL、Perl、PHP、UML2、Python、Ruby、XML等。Eclipse周围有一个庞大且活跃的社区。

  • Emacs是所有文本编辑器/开发环境/冒险游戏/一体化工具的母亲。专家程序员广泛使用它,并且有针对特定语言的众多增强功能,包括当然的Perl。使用CPerlMode的Emacs是一个功能丰富的Perl IDE,尽管它是一个非GUI IDE(这对一些人来说可能更好)。有一套针对CPerlMode的扩展可供使用,但您需要加入Yahoo Extreme Perl小组才能获取它们。

  • Komodo

    该软件可在Linux、Solaris和Windows上运行。提供免费演示;个人和学生使用价格为$29.95,商业用途为$295。它支持Perl、PHP、Python、Tcl和XSLT。

  • PAGE

    PAGE仅在Windows(9x/ME/NT/2000/XP)上运行。它是一个针对Perl的快速应用程序开发工具,并提供三种版本:免费版、标准版($10)和企业版($50)。PAGE提供几个“向导”用于创建脚本、模块(包)、网页表单,甚至数据库应用程序。

  • Perl Editor

    这是一个仅在Windows(9x/NT/2000/XP)上运行的闭源程序。它具有GUI代码分析器,专业版包含正则表达式测试器和内置的Web服务器(用于CGI测试等)。Perl Editor声称拥有市场上最好的调试器。它还提供用于管理MySQL数据库的GUI工具。购买价格为$69.95。

  • vim

    vi的著名后裔是一个功能强大且灵活的文本编辑器,具有许多插件和扩展。请查看vim脚本;例如,Perl-SupportExecPerl

  • visiPerl

    这是一个在Win9x/NT/2000上运行的闭源应用程序。它处理Perl和HTML,具有代码模板,旨在用于网站建设。visiPerl包括内置的Web服务器用于测试和一个FTP客户端用于代码部署。提供免费演示,或您可以选择以$59的价格购买。

标签

反馈

这篇文章有什么问题吗?请通过在GitHub上打开一个问题或拉取请求来帮助我们。