Запах кода, с которым вы столкнулись, называется Превышение в конструкторе , и ваш результирующий рефакторинг очень похож на рефакторинг Facade Services , который (согласно DIPP & P ( §6.1.2, стр. 168)) определяется как:
Фасадная служба скрывает естественный кластер взаимодействующих Зависимостей вместе с их поведением за одним Абстракция .
Однако, если ваш рефакторинг будет рефакторингом Facade Services, он предписывает использование новой абстракции, а абстрактное поведение скрывает одну или несколько зависимостей. Если извлеченные логи c не имеют никаких зависимостей и не содержат изменчивого поведения (см. Ниже), рассмотрите возможность использования метода stati c.
1 Если новый класс быть зависимостью, которая является вопросом внедрения зависимости? Или это считается помощником, который может быть создан, когда это имеет смысл (конструктор или метод)?
Оба варианта являются жизнеспособными, и наилучшее решение зависит от множества факторов. Вы можете спросить себя:
- Относится ли извлеченный лог c к тому же модулю, к которому принадлежит исходный класс? Если нет, DIP предписывает скрывать внешний код за абстракцией и вставлять его в конструктор.
- Содержит ли извлеченный лог c изменчивое поведение ? Другими словами, должна ли его логика c быть заменена каким-либо образом или в какой-либо форме (например, при проверке во время тестирования, заменяться с использованием шаблона стратегии , или декорироваться или перехватываться для применения сквозных проблем )? В этом случае поведение должно быть абстрагировано и введено в конструктор, поскольку в противном случае оно будет препятствовать проверке и сопровождению.
- Ожидается ли регулярное изменение зависимостей этого вспомогательного класса? В этом случае зависимость, по крайней мере, должна быть введена в конструктор, потому что в противном случае изменение зависимостей вспомогательного элемента будет зависеть от класса потребления.
В общем, я склонен сказать, что лучше всего определите новую абстракцию для этого вспомогательного класса и вставьте ее в конструктор. В случае сомнений я бы, конечно, go с последним, потому что определение новых абстракций иногда приводит к новому пониманию области приложения.
2 Должны ли мы написать дополнительный модульный тест для нового класса ?
Это зависит. С точки зрения тестирования, вы все равно можете решить протестировать класс и его помощника вместе. Это позволяет сохранить логику c в тестах одинаковой. Сложные классы часто имеют сложный набор тестов с ними. С этой точки зрения может иметь смысл тестировать оба класса изолированно, и, возможно, есть несколько тестов, которые тестируют два класса в интеграции. Если ваши тесты уже охватывали большинство случаев, вы сможете повторно использовать большую часть тестового кода.
3 Если параметры в видимом методе нового класса будут проверены снова, если они уже проверены в исходный класс?
Если вы обнаружите необходимость в повторной проверке набора параметров, рассмотрите возможность их извлечения в Объект параметров . Конструктор объекта параметров может выполнить проверку, и вы можете передать объект параметров от клиента к потребителю и от потребителя к помощнику.