Operator new() is Toxic

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

实例化对象,在大多数面向对象的语言中,包括Java、Ruby和C++,我们使用操作符new()。嗯,除非我们使用静态工厂方法,但我们不使用它们,因为它们是邪恶的。尽管在我们需要时创建一个新对象看起来很容易,但我建议对这个有毒的操作符更加小心。

我相信你明白这个操作符的问题在于它耦合了对象,使得测试和重用变得非常困难甚至不可能。假设有一个文件中的故事,我们需要将其作为UTF-8文本读取(我正在使用CactoosTextOf):

这个问题似乎非常简单,但问题显而易见:类Story无法被重复使用。它只能读取一个特定的文件。此外,测试它将会非常困难,因为它只能从一个固定的位置读取内容,无法改变。更正式地说,这个问题被称为不可打破的依赖—我们无法打破Story/tmp/story.txt之间的连接—它们永远在一起。

为了解决这个问题,我们需要引入一个构造函数,让Story接受内容的位置作为参数。

现在,每个Story的用户都必须知道文件的名称:

这并不是很方便,特别是对于之前使用“Story”的用户来说,他们对文件路径一无所知。为了帮助他们,我们引入了一个辅助构造函数:

现在我们只需要通过一个无参数的构造函数创建一个实例,就像我们之前做的那样。

我相信你对这个技术已经非常了解了,它也被称为依赖注入。我实际上并没有说什么新的东西。我想让你注意的是这三个代码片段中的new操作符的位置和数量。

在第一个代码片段中,new操作符都在text()方法中。在第二个代码片段中,我们失去了其中一个。在第三个代码片段中,一个操作符在方法中,而第二个操作符则移到了构造函数中。

记住这个事实,让我们继续。

如果文件不是以UTF-8编码而是KOI8-R编码,类TextOf和方法Story.text()将会抛出异常。然而,TextOf类能够读取任何编码,只需要在构造函数中有一个附加参数:

为了使Story能够使用不同的编码方式,我们需要引入一些额外的次要构造函数并修改其主要构造函数:

这只是依赖注入,但请注意new操作符的位置。它们现在都在构造函数中,而没有留在text()方法中。

在我看来,这里的趋势是明显的:new操作符在方法中停留得越久,类的可重用性和可测试性就越差。

换句话说,new操作符是一件相当有害的事情,所以请尽量在方法中最小化使用它。确保在您的次要构造函数中实例化所有或几乎所有内容。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-16 at 15:19

sixnines availability badge   GitHub stars