android di框架_您的DI框架正在杀死您的代码

android di框架

最近,我读了一篇非常有趣的文章,探讨了典型的OO代码与功能更强的样式之间的区别。 即使在Java和C#之类的OO语言中,对于功能的编码风格也有很多话要说。 我发现最大的缺点始终是代码组织之一:OO为您提供了一种组织大量代码的可发现方式。 虽然采用功能性样式,您可能需要较少的代码,但很难对其进行清晰组织。

我要挑战的并不是迈克的结论,而是他的出发点:他从他所描述的“典型的面向对象的C#代码”开始。 不幸的是,我认为他很厉害:即使在这个玩具示例中,也几乎就像我在野外看到的几乎所有所谓的“面向对象”代码一样。 我的类似代码的问题是:它不是面向对象的。 它是无规组织为类的过程代码。 只是因为你有上课,不要让它面向对象。

程序代码是什么意思? 我看到的典型模式是由两种类型的类组成的代码库:

  1. 值对象,无需业务逻辑即可保存所有数据
    如果这是来自您的持久层,nhibernate或类似对象的对象,则在此额外加分。
  2. 具有一两个公共功能的类–它们作用于没有自己状态的价值对象
    这些几乎都是“名词”

名词性动词是OO代码差的必杀技:OrderProcessor,AccountManager,PriceCalculator。 不,将其称为OrderService并不能使其更好。 它仍然是名词名词,您被毫无意义的“服务”一词所掩盖。 名词-动词表示其所有功能且没有状态,它作用于其他人的状态。 这几乎可以肯定是功能羡慕的标志。

这些名词动词的另一个设计气味是它们几乎总是单例。 哦,您可能没有意识到它们是单例的,因为您已经巧妙地将其隐藏在依赖注入框架的背后:但是它仍然是单例的。 如果没有状态,则可能是单例。 除了名称以外,这都是静态方法。 噢,请确保它比实际使用“静态”一词更具测试性。 但这仍然是静态方法。 如果您不使用自己的DI框架对自己撒谎,而是将其编写为静态方法,则您会大吃一惊。 但是,因为您已将其打包,并称其为“依赖关系”,所以您认为可以。 好吧,不是。 它仍然是废话。 您所拥有的是过程,可以将它们随意分组为可笑的“依赖项”类。 可以肯定,这不是OO。

好的OO设计的特性之一是,对数据进行操作的代码位于靠近数据的位置。 数据的实际表示方式可以隐藏在行为之后。 您关注的是对象的行为,而不是数据的表示。 这使您可以根据具有行为名词对域进行建模。 一个好的OO设计应包括与该领域中的名词相对应的类,其行为是作用于这些名词的动词:Order.SubmitForPicking()。 UserAccount.UpdatePostalAddress(),Basket.CalculatePriceIn includedTaxes()。

这些是熟悉领域但不熟悉软件的人仍然可以理解的词。 您的客户知道OrderPriceStrategyFactory的用途吗? 不,那不是真的。 它是你胡闹的胡说。

具有讽刺意味的是,不受人喜爱的价值目标是真正解决设计问题的地方。 这些几乎都是领域中的实际名词。 他们只是缺乏任何使他们有用的行为。 回到Mike的例子:他有一个Customer类–它的公共接口只是一个电子邮件地址属性,一个经典的值对象:所有状态,没有任何行为[如果您想在家玩,我已经将Mike的代码复制到了git中回购 ; 以及我的重构版本 ]。

在这个领域,客户听起来像是一个好名词。 我敢打赌客户会知道客户是什么。 如果仅存在某些行为,则该域对象可能具有。 客户在Mike的世界中做什么? 好吧,此示例全部关于创建和发送报告。 报告是针对单个客户制作的,因此我认为我们可以要求客户创建自己的报告。 通过将方法从ReportBuilder移到“客户”,它就在其操作的数据旁边。 突然,公共电子邮件属性可以被隐藏–这似乎是一个有用的更改,如果我们更改了与客户联系的方式,那么只有客户需要更改,而不是ReportBuilder。 这几乎就像是将设计中的单个更改包含在单个类中。 也许有人应该就这种单一责任的恶意代码写一个原则。

通过遵循这样的模式,将方法从名词-动词转移到它们所操作的名词上,我们最终得到了更清晰的设计。 客户可以创建报表(),报表可以RenderAsEmail(),电子邮件可以发送()。 在这样的领域中,这些似乎是明显的名词和明显的行为。 在软件的人造世界之外,它们都是有意义的。 该设计对领域进行建模,并且应该清楚域模型必须如何响应每个新要求而进行更改-因为每个都代表我们对领域的理解的变化。

那么,为什么这种模式如此罕见? 我指责IoC框架。 不严重,它们完全是邪恶的。 重构Mike的示例时,即使使用穷人的DI ,我遇到的第一件事就是我的域对象需要依赖项。 因为我现在已经移动了将报告从ReportingService通过电子邮件发送到Report域对象的功能,所以我的域对象现在需要了解Emailer。 在原始设计中,可以将其插入,但是对于新添加的对象,如何插入依赖项? 我需要在构造时或以电子邮件发送时将Emailer传递到我的报告中。 当重构它时,我选择传递使用时的依赖关系,但这只是因为在没有支持的情况下在构造时传递麻烦。

几乎所有的DI框架都使这成为皇家的痛苦。 如果我要将依赖项注入到也具有状态的类中(例如客户报告的详细信息),则基本上是不可能的,因此没有人这样做。 只需将报表创建拖到ReportBuilder上,而让客户独自一人,则更好,更简单,更快捷。 但这是错误的。 客户值得拥有一些功能。 他有用。 他厌倦了只是作为价值的存储库。 如果只有一种方法可以将依赖项注入名词中,而这并不是胡说八道。

例如,使用NInject(非常典型的DI框架),您可以创建一个域对象,该域对象需要通过字符串键入来注入依赖项和状态。 认真吗 在21世纪,您希望我放弃类型安全性,并将参数名称放入字符串中。 不,只是说不。

难怪当人们面对这些妥协时,人们便选择了名词-动词。 这些选择绝对是可怕的。 我见过的唯一可以使您正确执行此操作的DI框架是Guice的辅助注入。 据我所知,其他所有人都是错误的。

您的DI框架会杀死您的代码吗? 几乎可以肯定:如果您有有价值的对象和名词/名词,那么您的设计就是垃圾。 这是您的DI框架过分难以进行更好的设计的错。

翻译自: https://www.javacodegeeks.com/2015/09/your-di-framework-is-killing-your-code.html

android di框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值