Moose面向对象编程还是标准Perl?

13

我将要编写一些网络爬虫来获取某个网站的数据,这个网站将会使用一些后端的Perl脚本从其他网站获取数据。我的设计(以非常抽象的方式)是编写一个包,比如说:

package MyApp::Crawler::SiteName

该网站名称将是一个用于爬取特定网站的模块/包,我显然会有其他被共享于不同模块之间的包,但这并不相关。

总之,我的问题是:为什么(或者为什么不...)应该选择Moose而不是标准的OO Perl?

6个回答

23

虽然我不同意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的东西。我认为你对Catalyst有误解。Catalyst并不使用Moose;它是一种替代的MVC框架。 - Jonathan Hall
1
Catalyst是建立在Moose之上的大型应用程序。实际上,在Catalyst :: Manual :: Intro中的示例控制器使用了Moose来构建控制器。Catalyst作为MVC的一种实现方式与其自身的构建方式以及期望人们构建和扩展它的方式是正交的。 - perigrin
我看到现在是真的。以前并不总是这样。 - Jonathan Hall
自从5.8000_01 2008-10-13 22:52:00以来,这就是真的;) - perigrin
是的,我现在明白了。我早在那之前就开始使用催化剂了。可惜啊。 - Jonathan Hall

10

在它的文档中,你可以找到为什么要使用Moose的答案。

Moose 的主要目标是使 Perl 5 的面向对象编程更加轻松、一致和少繁琐。通过 Moose,你可以更多地关注你想做什么,而不是面向对象编程的机械操作。

根据我的经验,并且可能其他人也会告诉你相同的事情。Moose 极大地减小了你的代码体积,它具有许多特性,例如验证、在创建对象时强制赋值、延迟验证、默认值等等。这些特性非常容易阅读和理解,以至于你永远都不想放弃 Moose。


3

使用Moose。这是我昨晚写的东西(在这种情况下使用Mouse)。它应该很明显它做什么,验证什么以及设置什么。现在想象一下编写等效的原始OO代码。它并不是特别难,但阅读起来越来越困难,不仅是代码本身,而且是意图,当你阅读之前没有见过或很长时间没有看到代码时,这可能是最重要的部分。

has "io" =>
    is => "ro",
    isa => "FileHandle",
    required => 1,
    handles => [qw( sysread )],
    trigger => sub { binmode +shift->{io}, ":bytes" },
    ;

去年我写了一个大的测试类,还使用了handles功能将大量方法重新分派到底层的Selenium/WWWMech对象。消除这种样板代码可以真正帮助提高可读性和维护性。


3
我不确定打破封装并使用后置修改器是否是你想要的。设置一个触发器来在存储的FH上设置“:bytes”层是否更适合你?或者它需要在每次从属性中获取时设置? - perigrin
@perigrin,你说得对。我会将它从“after”更新为“trigger”。 - Ashley

2

我从未使用过Moose,但我使用过Catalyst,并且在面向对象的Perl和非面向对象的Perl方面有丰富的经验。我的经验告诉我,最好使用您最熟悉的方法。

对我来说,那个方法已经变成了“除了Catalyst之外的任何东西” :) (这并不是说喜欢和信誓旦旦地支持Catalyst的人是错的-这只是我的口味)。

如果您已经拥有一个可以构建的爬虫应用程序的核心,请使用它编写的任何内容。 如果您从头开始,请使用您最有经验的内容-除非这是您尝试新事物的机会,那么请在完成任务的同时学习新东西。

我认为这只是“哪种语言最好”的又一个例子?”,这个问题永远无法回答,除非由个人回答。


你能详细说明一下“为什么”吗?我正在考虑转换到 Catalyst,希望从另一个角度看看。 - DVK

1
当我学习Perl中的对象时,我首先想到的是为什么它会这么复杂,因为Perl通常试图保持简单。
通过Moose,我看到在Perl中可以实现简单的面向对象编程。它将Perl的面向对象编程带回了可管理的水平。
(是的,我承认,我不喜欢Perl的对象设计。)

0
虽然这个问题是10年前提出的,但在Perl世界中发生了许多变化。我认为大多数人现在都看到,Moose并没有实现所有人所期望的。有几个衍生项目,大量的MooseX,等等。这种编码翻转表明该项目已经接近实用,但还不够完善。即使是原始作者Stevan Little也在开发他的替代品Moxie,但它从未真正得以发展。我认为没有任何人对Moose感到完全满意。
目前,无论您对框架的评估如何,未来可能不是Moose。我在Intermediate Perl中为Moose编写了一章,但在下一版中将其删除。这不是基于质量决策,而是基于该领域正在发生的实际情况。

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坚持下去可能不是一个好的短期计划。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接