Конечно, и что в этом плохого? Есть такой принцип: Принцип единственной ответственности буква S, из абрревиатуры SOLID, вот мы как раз ему и последовали. В чем косяк то?
Принцип единственной ответственности не запрещает DI и не запрещает общаться с другими компонентами.
Так я выше написал, что этот класс будет тестироваться с помощью интеграционных тестов.
Ну т.е. все сводится к тому какой тест можно назвать юнит-тестом, а какой уже интеграционный. Вопрос не в сути, а в терминологии. При этом ради сохранения чистоты терминологии автор готов пойти на усложнение кода и, соответственно, добавление ошибок.
Если у тебя будет как ты выше написал CalculatorWithLogger, CalculatorWithDatabase, CalculatorWithLoggarAndDatabase, то тут в любом случае придется вводить интерфейс. Ты уже докапываешься до незначительных деталей ИМХО.
И не просто так придется вводить интерфейс. Т.к. у тебя будет
Calculator : ICalculator
CalculatorWithLogger : ICalculator
CalculatorWithDatabase : ICalculator
CalculatorWithLoggarAndDatabase : ICalculator
что, как ты понимаешь, легко может привести к ошибке.
Для исключения ошибки тебе придется вводить еще один интерфейс:
Calculator : ICalculatorUnit
CalculatorWithLogger : ICalculator
CalculatorWithDatabase : ICalculator
CalculatorWithLoggarAndDatabase : ICalculator