我将要编写一些网络爬虫来获取某个网站的数据,这个网站将会使用一些后端的Perl脚本从其他网站获取数据。我的设计(以非常抽象的方式)是编写一个包,比如说:
package MyApp::Crawler::SiteName
该网站名称将是一个用于爬取特定网站的模块/包,我显然会有其他被共享于不同模块之间的包,但这并不相关。
总之,我的问题是:为什么(或者为什么不...)应该选择Moose而不是标准的OO Perl?
虽然我不同意Flimzy的介绍(“我没有使用Moose,但我使用了使用Moose的东西”),但我同意他的前提。
使用你认为能够产生最好结果的工具。如果目标是学习如何有效地使用Moose,那就使用Moose。如果目标是编写高质量代码,学习Moose会分散注意力,那就不要使用Moose。
然而,你的问题是开放式的(正如其他人所指出的)。没有一个答案会被普遍接受为正确,否则Moose的采用率就会更高,我也不会回答这个问题。我只能解释为什么每次我开始一个新项目时都选择使用Moose。
正如Sid在Moose文档中引用的那样,Moose的核心目标是成为一种更清洁、更标准化的方式来完成自Perl 5.0发布以来面向对象的Perl程序员一直在做的事情。它提供了快捷方式,使得做正确的事情比做错误的事情更简单。在我看来,在标准Perl中缺少这种功能。它提供了新的工具,使将问题抽象为更小、更易于解决的问题变得更简单,并提供了一种强大的内省和元编程API,试图将从Perl空间(即我曾经称之为符号表巫术)中黑客Perl内部的兽群标准化。
自从我开始使用Moose以来,我发现我的自然代码量感觉已经减少了66%[^1]。我发现自己更容易遵循良好的设计原则,如封装和信息隐藏,因为Moose提供了使其比不使用更容易的工具。因为Moose自动生成了我通常需要编写的许多样板代码(例如访问器方法、委托方法和其他类似的内容),所以我发现我更容易快速地掌握我六个月前所做的事情。我也发现自己写的诡计性代码比几年前少得多,只是为了节省自己的几下按键而已。
有可能编写干净、健壮、优雅的面向对象Perl代码而不使用Moose[^2]。根据我的经验,这需要更多的努力和自我控制。在那些要求不能使用Moose的项目中,我发现我的常规面向对象代码收益于我从Moose获取的习惯。我会像使用Moose一样思考它,然后比写下我期望Moose为我生成的代码多打三倍的字[^3]。
因此,我使用Moose是因为我发现它使我成为更好的程序员,并且由于它,我编写了更好的程序。如果你也不认为这对你有用,那么Moose就不是正确的答案。
[^1]: 我曾经在一个模块中达到约300行代码时才开始考虑我的设计。现在我在约100行代码时就开始感到不安了。
[^2]: Miyagawa在Twiggy中的代码是我今天刚看到的一个很好的例子。
[^3]: 这并非普遍适用。有几个故事在流传,讲述人们过度使用Moose提供的工具而编写了不易维护的可怕代码。糟糕的程序员可以在任何地方编写糟糕的代码。
在它的文档中,你可以找到为什么要使用Moose的答案。
Moose 的主要目标是使 Perl 5 的面向对象编程更加轻松、一致和少繁琐。通过 Moose,你可以更多地关注你想做什么,而不是面向对象编程的机械操作。
根据我的经验,并且可能其他人也会告诉你相同的事情。Moose 极大地减小了你的代码体积,它具有许多特性,例如验证、在创建对象时强制赋值、延迟验证、默认值等等。这些特性非常容易阅读和理解,以至于你永远都不想放弃 Moose。
使用Moose。这是我昨晚写的东西(在这种情况下使用Mouse)。它应该很明显它做什么,验证什么以及设置什么。现在想象一下编写等效的原始OO代码。它并不是特别难,但阅读起来越来越困难,不仅是代码本身,而且是意图,当你阅读之前没有见过或很长时间没有看到代码时,这可能是最重要的部分。
has "io" =>
is => "ro",
isa => "FileHandle",
required => 1,
handles => [qw( sysread )],
trigger => sub { binmode +shift->{io}, ":bytes" },
;
去年我写了一个大的测试类,还使用了handles
功能将大量方法重新分派到底层的Selenium/WWWMech对象。消除这种样板代码可以真正帮助提高可读性和维护性。
我从未使用过Moose,但我使用过Catalyst,并且在面向对象的Perl和非面向对象的Perl方面有丰富的经验。我的经验告诉我,最好使用您最熟悉的方法。
对我来说,那个方法已经变成了“除了Catalyst之外的任何东西” :) (这并不是说喜欢和信誓旦旦地支持Catalyst的人是错的-这只是我的口味)。
如果您已经拥有一个可以构建的爬虫应用程序的核心,请使用它编写的任何内容。 如果您从头开始,请使用您最有经验的内容-除非这是您尝试新事物的机会,那么请在完成任务的同时学习新东西。
我认为这只是“哪种语言最好”的又一个例子?”,这个问题永远无法回答,除非由个人回答。
Ovid正在开发Corrina,这是一个类似但也不同的框架,旨在解决一些相同的问题。Ovid概述了他想要改进的各种事情,因此您可以将其作为自己决策的基础。无论您对Moose或Corrina有何看法,我认为社区现在正在从Moose阶段过渡。
您可能想听一下How Moose made me a bad OO programmer,这是Tadeusz Sośnierz在PerlCon 2019上的短篇演讲。
即使您持怀疑态度,在承诺重新配置大型代码库之前,请在小型项目中尝试使用Moose。然后,在中型项目中尝试它。我倾向于认为像Moose这样的框架在适合一页的示例中看起来很吸引人,但在问题变得更加复杂时就会暴露出它们的弱点。在您了解更多信息之前,请不要全力以赴。
您至少应该了解Moose的基础知识,因为您可能会遇到其他使用它的代码。
Perl 5 Porters可能会将其包含在核心perl中,但完整的交付可能需要五到十年的时间,即使那时你也必须坚持使用受支持的Perl版本。我遇到的大多数人都落后于Perl版本三到五年。如果您控制自己的perl版本,那就没有问题。然而,并不是每个人都这样做。为Corrina坚持下去可能不是一个好的短期计划。