我看到很多 .Net 和 Java 的 IoC 框架。有谁知道为什么 Smalltalk 没有等效的框架。这更像是一个哲学问题。我想知道 Smalltalk 的做事方式是否有某些东西排除了拥有 IoC 框架的必要性。
5 回答
MVC是在 Smalltalk 上发明的,可以说是最初的控制反转框架。虽然比其 java 同类产品更轻量,但它具有保存数据的模型的基本概念,一个视图呈现数据以响应从控制器传播的事件。
不那么轻率的是,Java 实际上需要大量框架支持才能在没有过多样板代码的情况下创建 Web 应用程序。Smalltalk 支持诸如continuation之类的编程习惯用法,这允许作者假装他们不是真的在编写事件驱动的代码。 Seaside就是这样工作的,通过更灵活的开发范式赋予 IoC 的好处。
编辑:MVC 是 Smalltalk 中 UI 的框架(可以说它并不是真正的框架,但类库已经内置了对它的支持)。它具有控制属性的反转,因为视图和模型响应控制器调度的事件 - 不要调用我们,我们会调用你的属性。控制反转是框架内的一种设计模式,用于减少 Java 应用程序中对大量样板的需求。在应用程序框架的某些定义中,控制反转是被视为区分框架与库的主要属性。
函数是 smalltalk 中的一等公民,因此很容易在没有框架的情况下拥有 IoC。
我认为 IOC 或依赖注入模式解决了 Smalltalk 环境中不存在的问题。Smalltalk 是一种无类型的动态语言,使用消息传递进行通信。这使得对象在语言级别上本质上是松散耦合的。任何对象都可以向另一个对象发送消息,而无需考虑类型,只要它可以处理消息即可。因此,正如您可能猜到的那样,在任何给定时间更改依赖项都是相对容易和自然的。只需决定在何处、何时以及如何更改依赖项。
这有几个可能的原因。一个是我们没有费心使用“IoC”限定符,这本质上是多余的——因为将某些东西称为框架意味着控制流的反转。
另一个是 Smalltalk 语言以闭包的形式提供对“IoC”流的直接支持。使用闭包进行编程的一个结果是,在框架中发现的控制流似乎并没有那么明显的不同,以至于让人产生一种从“正常”流感“倒转”的感觉。相反,通过闭包,控制流一直在这两种观点之间来回切换,并且无处不在。即使在单个语句中。
第三个原因也许是,即使没有闭包,所描述的“控制反转”也不是与框架唯一相关的——在大多数涉及 I/O 的代码形式中都可以找到相同的流程。
第四,Smalltalkers 可能比其他人更多地使用这类流,因为我们更多地依赖于对象的概念和它们之间发送的消息,而不是结构的概念和成员函数的调用。在没有闭包的情况下,这两种观点是等价的,可以互换的,但是闭包的加入改变了结果——使用中的控制流感是效果之一。
最后,人们甚至可以考虑将 REPL 风格的控制流描述为“更简单”,但“正常”流的“倒置”意义,在几乎在其他任何地方都使用它的意义上是正常的。
总之,Smalltalk 存在相同类型的框架。我们对它们的描述略有不同。差异至少部分是由于 Smalltalk 中闭包的存在和利用,许多其他环境尚未提供 - 特别是 C++、C# 和 Java。
在Java中,当您编写类似的东西时会创建一个依赖项
MyClass32 temp = this.theThing();
现在你的代码依赖于 MyClass32 类。没有它,您的代码将无法工作。该类中的任何更改都可能使您的代码无法编译,这需要对您的代码进行大量额外更改,这可能需要在依赖于您的类中进行进一步的代码更改。很多额外的工作。
在 Smalltalk 中你会写 temp := self theThing;
无论#getTheThing 返回什么,您的代码都将起作用。您的代码不依赖于 MyClass32 类。您唯一的依赖是“临时”必须理解您发送给它的任何消息。
所以从某种意义上说,依赖注入框架的目的是让像 Java 这样的静态类型语言更像是动态类型语言。
也就是说,我在 Smalltalk 中经常遵循一种设计模式:创建一个类方法,如返回 SOME 类的 MyClass。它不需要有 NAME 'MyCLass'。它可能是几个班级之一,晚上返回不同的班级。这种模式出现在 Smalltalk MVC 中,其中视图类具有方法 #defaultControllerClass,该方法通常由子类重新定义。