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 (я использую TextOf из Cactoos):

Кажется, что это очень просто, но проблема очевидна: класс 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