- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我一直在阅读 Sandi Metz 的 Ruby 中的实用面向对象设计 以及许多在线讨论 Ruby 设计的网站。我很难完全理解实现依赖注入(inject)的正确方法。
互联网上充斥着解释依赖注入(inject)如何以我认为非常片面的方式工作的博客文章。
我知道这应该是不好的:
class ThisClass
def initialize
@another_class = AnotherClass.new
end
end
虽然这是一个解决方案:
class ThisClass
def initialize(another_class)
@another_class = another_class
end
end
我可以像这样发送 AnotherClass.new:
this_class = ThisClass.new(AnotherClass.new)
至少这是 Sandi Metz 推荐的方法。我不明白的是这样的线应该去哪里?它必须去某个地方,通常在这个例子中,显示的是一行完全放在任何类、方法或模块之外的行,就好像我只是为了测试目的在 IRB 中手动输入它一样。
This post (除其他外)建议采用这种不同的方法:
class ThisClass
def another_class
@another_class ||= AnotherClass.new
end
end
Jamis Buck会采取类似的方法:
class AnotherClass
end
class ThisClass
def another_class_factory(class_name = AnotherClass)
class_name.new
end
end
但是,这两个示例都在 ThisClass 中保留了 AnotherClass 的名称,Sandi Metz 说这是我们试图避免的主要事情之一。
那么这样做的最佳做法是什么?我是否应该制作一个“依赖”模块,其中填充了作为应用程序中每个类对象工厂的方法?
最佳答案
Something I've had a hard time fully understanding is the proper way to implement dependency injection.
我认为“正确”实现的最佳定义是遵守 SOLID principles面向对象的设计。在这种情况下,主要是依赖倒置原则。
在这方面,这是唯一不违反 DIP(1) 的解决方案:
class ThisClass
def initialize(another_class)
@another_class = another_class
end
end
在所有其他情况下,ThisClass
对AnotherClass
具有硬依赖性,没有它就无法运行。此外,如果我们想用第三个替换 AnotherClass
,我们需要修改 ThisClass
,这违反了Open Closed Principle。
当然,在上面的例子中,将参数和实例变量命名为another_class
并不理想,因为我们现在不知道(也不需要知道)传递给我们的是什么对象,如只要它响应预期的界面。这就是多态的美妙之处。
考虑以下示例,取自 ThoughtBot video on DIP :
class Copier
def initialize(reader, writer)
@reader = reader
@writer = writer
end
def copy
@writer.write(@reader.read_until_eof)
end
end
在这里你可以传递任何reader
和writer
对象来分别响应read_until_eof
和write
。这使您可以完全自由地使用不同的读写实现对来组合您的业务逻辑,即使在运行时也是如此:
Copier.new(KeyboardReader.new, Printer.new)
Copier.new(KeyboardReader.new, NetworkPrinter.new)
这让我们想到您的下一个问题。
It has to go somewhere and generally in examples of this what's shown is a line like that being placed totally outside of any class, method, or module [...]
你是对的。虽然对象思维涉及使用隔离良好、解耦和可组合的对象对域进行建模,但您仍然需要定义这些对象如何交互,以便实现任何业务逻辑。毕竟,除非我们组合它们,否则拥有可组合的对象是没有用的。
这里经常做的类比是将您的对象视为 Actor 。您是导演,您仍然需要创建一个脚本(2) 让 Actor 们知道如何相互交流。
也就是说,您的应用程序需要一个入口点。 脚本 开始的地方。这本身可能是一个对象——通常是一个抽象对象。在命令行应用程序中,它可以是您的经典 Main
类,而在 Rails 应用程序中,它可以是您的 Controller 。
乍一看这似乎很奇怪,因为对象思维的重点是建模具体的领域对象,并且关于该主题的大量著作都致力于此,但请记住 actor-script 隐喻,你会在路上。
我强烈建议你拿起这本书Object Thinking .它很好地解释了面向对象设计背后的思维方式,如果不了解特定于语言的实现细节就会变得毫无意义。
(1):值得注意的是,一些支持者认为将另一个类的实例存储在实例变量中是一种反模式,但在 Ruby 中,这是相当惯用的。
(2):我不确定这是否是一般编程中脚本 一词的起源,但也许一些历史学家可以对此有所启发。
关于ruby - Ruby 中依赖注入(inject)的最佳实践是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33326166/
本文分享自华为云社区《大模型LLM之分布式训练》,作者: 码上开花_Lancer。 随着语言模型参数量和所需训练数据量的急速增长,单个机器上有限的资源已无法满足大语言模型训练的要求。需要设计分布式训
本文分享自华为云社区《五大基础算法--动态规划法》,作者: 大金(内蒙的)。 一、基本概念 动态规划法,和分治法极其相似。区别就是,在求解子问题时,会保存该子问题的解,后面的子问题求解时,可以直接拿来
pip install scp pip install pexpect 测试代码: import os import stat import paramiko # 用于调用scp命令 def s
我目前正在实现“ token ”REST 服务。 token 只是一个字符串,由一些参数构建而成,然后经过哈希处理并在一定时间后过期。 我想在我的 REST 服务中有一个可以验证 token 的端点,
打开软删除后,我在客户端上添加一条记录,推送,删除添加的记录推送,然后尝试使用与初始记录相同的主键添加新记录(然后推送),我得到一个异常(exception)。 EntityDomainManager
打开软删除后,我在客户端上添加一条记录,推送,删除添加的记录推送,然后尝试使用与初始记录相同的主键添加新记录(然后推送),我得到一个异常(exception)。 EntityDomainManager
我有一个应用程序,每 x 秒接收一次天气信息。我想将此数据保存到 XML 文件中。 我应该为每个天气通知创建一个新的 XML 文件,还是将每个通知附加到同一个 XML 文件中?我不确定 XML 标准的
我猜我们大多数人都必须在某个时候处理这个问题,所以我想我会问这个问题。 当您的 BLL 中有很多集合并且您发现自己一遍又一遍地编写相同的旧内联(匿名)谓词时,显然有必要进行封装,但实现封装的最佳方
我有一些 c# 代码已经运行了一段时间了..我不得不说,虽然我了解 OO 原则的基础知识,但显然有不止一种方法可以给猫剥皮(尽管我讨厌那个短语!)。 因此,我有一个基本抽象类作为基本数据服务类,如下所
我设计了一个 SQL 数据库系统(使用 Postgre),我有一个问题,即创建一个关系/引用的常见做法是什么,这种关系/引用即使在引用的对象被删除时也能持续存在。 比如有一个UserORM,还有Act
我们的目标是搜索用户输入的字符串并计算在其中找到多少元音。不幸的是我被困在这里,有什么帮助吗? def numVowels(s): vowels= "AEIOUaeiou" if s
我有一个适用于我的“items”int 数组的旋转函数。下面的代码完成了它,除了我不必要地传输值。我正在努力实现“就地”轮换。我的意思是 ptrs 会递增或递减,而不是从数组中获取值。我需要通过这种方
我有一个 json 存储在我的应用程序文档文件夹中,我需要在我的所有 View 中使用它。我正在加载 json 并将其添加到每个 View 中的 NSMutableArray。但现在我了解到,我可以将
我用 C++ 开始了一个项目。这种语言的内存管理对我来说是新的。 我过去常常使用 new () 创建对象,然后传递指针,虽然它可以工作,但调试起来很痛苦,人们看到代码时会用有趣的眼神看着我。我为它没有
已结束。 这个问题是 off-topic .它目前不接受答案。 想要改进这个问题? Update the question所以它是on-topic堆栈溢出。 关闭 10 年前。 Improve thi
保持类松散耦合是编写易于理解、修改和调试的代码的一个重要方面——我明白这一点。然而,作为一个新手,几乎任何时候我都会超越我所苦苦挣扎的最简单的例子。 我或多或少地了解如何将字符串、整数和简单数据类型封
我发现我需要编写大量重复代码,因为我无法从其他 Controller 调用函数。例如,这里新闻提要内容在我的代码中重复,我对一个 Controller 做一些特定的事情,然后需要像这样加载我的新闻提要
假设需要一种数字数据类型,其允许值在指定范围内。更具体地说,假设要定义一个整数类型,其最小值为0,最大值为5000。这种情况在很多情况下都会出现,例如在对数据库数据类型,XSD数据类型进行建模时。 在
假设我想循环整个数组来访问每个元素。使用 for 循环、for...in 循环或 for...of 循环是 JavaScript 开发人员的标准做法吗? 例如: var myArray = ["app
我有一个旧的 SL4/ria 应用程序,我希望用 Breeze 取代它。我有一个关于内存使用和缓存的问题。我的应用程序加载工作列表(一个典型的用户可以访问大约 1,000 个这些工作)。此外,还有很多
我是一名优秀的程序员,十分优秀!