猴子修补。 SOLID原则?

在一些个人项目中,我正在慢慢地从PHP5转向Python,我现在很喜欢这种体验。 在选择沿着Python路线前,我看了Ruby。 我从ruby社区注意到的是,猴子修补既常见又备受推崇。 我也遇到了很多关于调试ruby s / w的试验的恐怖故事,因为有人包括一个相对无害的库来完成一些工作但是修补了一些使用频繁的核心对象而没有告诉任何人。

我选择Python(除了其他原因)之外它的语法更清晰,而且它可以完成Ruby所能做的一切。 Python正在使OO点击比PHP有更好的点击,我正在越来越多地阅读OO原则以增强这种更好的理解。

今晚我一直在阅读Robert Martin的SOLID原则:

  • 单一责任原则,
  • O pen / closed原则,
  • L iskov替代原则,
  • 接口隔离原则,和
  • 依赖倒置原理

我目前接受O软件实体(课程,模块,function等)应该开放扩展,但是要求修改

我的头脑是在确保OO设计的一致性和整个猴子修补之间的冲突。 我知道可以在Python中进行猴子修补。 我也明白,“pythonic”是遵循常见的,经过良好测试的oop最佳实践和原则。

我想知道的是社区对两个对立主题的看法; 他们如何互操作,当它最好地使用它时,是否应该完成猴子修补……希望你能为我提供解决方案。

猴子修补(覆盖或修改预先存在的方法)与简单添加新方法之间存在差异。 我认为后者完全没问题,前者应该被怀疑地看待,但我仍然赞成保留它。

我遇到了很多问题,其中第三方扩展monkeypatches核心库并打破了事情,他们真的很糟糕。 不幸的是,它们总是看起来源于第三方扩展开发人员走的阻力最小,而不是考虑如何正确地构建他们的解决方案。
这很糟糕,但它不再是猴子修补的错误,而不是刀具制造者的错,人们有时会割伤自己。

我曾经见过的唯一合法的猴子补丁需求是解决第三方或核心库中的错误。 仅此一点,它是无价的,如果他们取消了这样做的能力,我真的很失望。

我们在C#程序中出现错误的时间表:

  1. 阅读奇怪的错误报告并将问题跟踪到CLR库中的小错误。
  2. 投资日期提出了一个解决方法,涉及在陌生的地方捕获exception和大量黑客攻击,这些都会严重影响代码
  3. 当微软发布服务包时,花几天时间解决hacky变通办法

我们有一个rails程序中的错误时间表:

  1. 阅读奇怪的错误报告并将问题跟踪到ruby标准库中的小错误
  2. 花15分钟执行小型猴子补丁来删除ruby库中的bug,如果它运行在错误版本的ruby上,则在它周围放置警卫。
  3. 继续正常编码。
  4. 稍后在下一版本的ruby发布时删除monkeypatch。

错误修正过程看起来很相似,除了monkeypatching,它是一个15分钟的解决方案,一个5秒的’提取’,而没有它,疼痛和痛苦随之而来。

PS:下面的例子是“技术上”monkeypatching,但它是“道德”monkeypatching? 我没有改变任何行为 – 这或多或少只是在ruby中做AOP ……

class SomeClass alias original_dostuff dostuff def dostuff # extra stuff, eg logging, opening a transaction, etc original_dostuff end end 

在我看来,monkeypatching对于拥有可以被滥用的东西很有用。 人们倾向于发现它并且觉得应该在每种情况下使用它,其中可能混合或其他构造可能更合适。

我不认为这是你应该禁止的事情,这只是Ruby家伙喜欢使用的东西。 你可以用Python做类似的事情,但社区已采取的立场应该更简单,更明显。

猴子修补不是ruby-explicit,它在javascript中也完成,具有负(IMO)效果。

我的个人意见是猴子补丁应该只进行

a)为您需要的新版本语言中提供的旧版本语言添加function。

b)当没有其他“合乎逻辑”的地方时。

有许多简单的方法可以使猴子修补变得非常糟糕,例如能够改变ADDITION等基本function的工作方式。

我的立场是,如果你能避免它,那就这样做。

如果你能以一种不错的方式避免它,那就对你有所帮助。

如果你无法避免它,请得到200人的意见,因为你可能只是没有考虑到它。

我的宠物讨厌是扩展function对象的mootools。 是的,你可以这样做。 而不只是人们只是学习javascript如何工作:

 setTimeout(function(){ foo(args); }, 5000 ); 

为每个函数对象添加了一个新方法(是的,我不是在开玩笑),所以函数现在有自己的函数。

 foo.delay( 5000 , args ); 

这种废话的附加效果是有效的:

 foo.delay.delay( 500, [ 500, args ] ); 

就像无限的广告一样。

结果? 你不再拥有一个图书馆和一种语言,你的语言鞠躬到图书馆,如果图书馆恰好在范围内,你就不再拥有一种语言,而且你不能按照学习时的方式做事。语言,而不是必须学习一个的命令子集,只是为了不让它掉在脸上(以过度减速为代价!)

我可以注意到foo.delay还使用自己的方法返回了一个对象,所以你可以做到

 x = foo.delay( 500, args ); x.clear(); 

乃至

  x.clear.delay(10); 

这可能听起来过于有用,但是你必须考虑到使这个可行的大量开销。

  clearTimeout(x); 

太难了!

(免责声明:自从我使用moo以来已经有一段时间了,并试图忘记它,并且函数名称/结构可能不正确。这不是API参考。请查看他们的网站了解详细信息(对不起,他们的API参考很糟糕!) )

Mokeypatching通常是错误的。 创建一个合适的子类并添加方法。

我在生产代码中使用过monkeypatching。

问题是REST使用GET,POST,PUT和DELETE。 但是Django测试客户端只提供GET和POST。 我为PUT(如POST)和DELETE(如GET)进行了monkeypatched方法。

由于Django客户端和Django测试驱动程序之间的紧密绑定,因此将其简化为支持完整REST测试似乎是最简单的。

您可能会发现有关Ruby的开放类和开放封闭原则的讨论。

即使我喜欢Ruby,我觉得猴子修补是最后的工具,可以完成任务。 在所有条件相同的情况下,我更喜欢使用传统的OO技术,并且具有多种function编程优点。

在我看来,猴子修补是AOP的一种forms。 文章面向方面的设计原则:面向对象设计的教训 (PDF)给出了一些关于如何将SOLID和其他OOP原则应用于AOP的想法。

我的第一个想法是猴子修补违反了OCP,因为一个类的客户应该能够期望该类一致地工作。

猴子修补是完全错误的 ,恕我直言。 我没有遇到你之前提到过的开放/封闭原则,但这是我长期坚持的原则,我同意它100%。 我认为猴子修补是一种更大规模的代码气味,一种编码 – 哲学 – 气味,就像它一样。