Определите инъекционные и тестовые единицы - PullRequest
1 голос
/ 22 апреля 2020

Допустим, у нас есть класс по крайней мере с одним видимым методом и несколькими закрытыми методами. Видимый вызывает частные, частные - другие частные и так далее. Существует модульный тест , который на 100% охватывает все пути класса, включая его частные методы.

В определенный момент разработчик решает извлечь некоторые из частных методов в другой класс, поскольку исходный класс слишком большой. Нет возможности для повторного использования извлеченного кода, поскольку он может использоваться только для исходного класса.

Теперь есть второй класс, который должен быть где-то создан для того, чтобы иметь возможность использовать его метод (ы). Теперь у нового класса есть, скажем, один видимый метод.

Вопросы:

  1. Должен ли новый класс быть зависимостью, которая является вопросом внедрения зависимостей ? Или это считается помощником, который может быть создан, где это имеет смысл (конструктор или метод)?
  2. Должны ли мы написать дополнительный модульный тест для нового класса?
  3. Должны ли параметры в видимом метод нового класса будет проверен снова, если они уже проверены в исходном классе?

Проблема общая, и конкретных примеров нет.

1 Ответ

2 голосов
/ 22 апреля 2020

Запах кода, с которым вы столкнулись, называется Превышение в конструкторе , и ваш результирующий рефакторинг очень похож на рефакторинг Facade Services , который (согласно DIPP & P ( §6.1.2, стр. 168)) определяется как:

Фасадная служба скрывает естественный кластер взаимодействующих Зависимостей вместе с их поведением за одним Абстракция .

Однако, если ваш рефакторинг будет рефакторингом Facade Services, он предписывает использование новой абстракции, а абстрактное поведение скрывает одну или несколько зависимостей. Если извлеченные логи c не имеют никаких зависимостей и не содержат изменчивого поведения (см. Ниже), рассмотрите возможность использования метода stati c.

1 Если новый класс быть зависимостью, которая является вопросом внедрения зависимости? Или это считается помощником, который может быть создан, когда это имеет смысл (конструктор или метод)?

Оба варианта являются жизнеспособными, и наилучшее решение зависит от множества факторов. Вы можете спросить себя:

  • Относится ли извлеченный лог c к тому же модулю, к которому принадлежит исходный класс? Если нет, DIP предписывает скрывать внешний код за абстракцией и вставлять его в конструктор.
  • Содержит ли извлеченный лог c изменчивое поведение ? Другими словами, должна ли его логика c быть заменена каким-либо образом или в какой-либо форме (например, при проверке во время тестирования, заменяться с использованием шаблона стратегии , или декорироваться или перехватываться для применения сквозных проблем )? В этом случае поведение должно быть абстрагировано и введено в конструктор, поскольку в противном случае оно будет препятствовать проверке и сопровождению.
  • Ожидается ли регулярное изменение зависимостей этого вспомогательного класса? В этом случае зависимость, по крайней мере, должна быть введена в конструктор, потому что в противном случае изменение зависимостей вспомогательного элемента будет зависеть от класса потребления.

В общем, я склонен сказать, что лучше всего определите новую абстракцию для этого вспомогательного класса и вставьте ее в конструктор. В случае сомнений я бы, конечно, go с последним, потому что определение новых абстракций иногда приводит к новому пониманию области приложения.

2 Должны ли мы написать дополнительный модульный тест для нового класса ?

Это зависит. С точки зрения тестирования, вы все равно можете решить протестировать класс и его помощника вместе. Это позволяет сохранить логику c в тестах одинаковой. Сложные классы часто имеют сложный набор тестов с ними. С этой точки зрения может иметь смысл тестировать оба класса изолированно, и, возможно, есть несколько тестов, которые тестируют два класса в интеграции. Если ваши тесты уже охватывали большинство случаев, вы сможете повторно использовать большую часть тестового кода.

3 Если параметры в видимом методе нового класса будут проверены снова, если они уже проверены в исходный класс?

Если вы обнаружите необходимость в повторной проверке набора параметров, рассмотрите возможность их извлечения в Объект параметров . Конструктор объекта параметров может выполнить проверку, и вы можете передать объект параметров от клиента к потребителю и от потребителя к помощнику.

...