Пример твоего босса выглядит для меня разумным.
Некоторые ключевые соображения, которые я стараюсь учитывать при разработке любого сценария:
Принцип единой ответственности
Класс должен меняться только по одной причине.
Оправдывает ли каждый новый класс свое существование
Созданы ли классы только ради этого или они содержат значимую часть логики?
Можете ли вы протестировать каждый фрагмент кода изолированно?
В вашем сценарии, просто взглянув на имена, может показаться, что вы уходите от Единой ответственности - у вас есть IInvoiceCalculator, но этот класс также отвечает за обновление InvoiceLines. Вы не только сильно усложнили тестирование поведения обновления, но теперь вам нужно изменить свой класс InvoiceCalculator как при изменении бизнес-правил расчета , так и при изменении правил обновления.
Тогда возникает вопрос об обновлении логики - оправдывает ли логика отдельный класс? Это действительно зависит, и это трудно сказать, не видя код, но, конечно, тот факт, что ваш начальник хочет, чтобы тестируемая логика подсказывала, что это больше, чем простой вызов по линии в режиме реального времени.
Вы говорите, что этот рефакторинг создает большое количество дополнительных классов (я предполагаю, что вы имеете в виду все ваши бизнес-сущности, так как я вижу только пару новых классов и их интерфейсы в вашем примере), но вы должны посмотрим, что вы получите от этого. Похоже, вы получаете полную тестируемость своего кода, возможность вводить новые вычисления и новую логику обновления в отдельности, а также более четкую инкапсуляцию того, что является отдельными частями бизнес-логики.
Прибыль , приведенная выше, конечно, подлежит анализу затрат и выгод, но, так как ваши опросы просят их, кажется, что он счастлив, что они окупятся, за дополнительную работу по реализации код таким образом.
Последний, третий пункт о тестировании в изоляции также является ключевым преимуществом того, как ваш начальник разработал это - чем ближе ваши публичные методы к коду, который действительно работает, тем легче вводить заглушки или макеты для частей вашей системы, которые не тестируются. Например, если вы тестируете метод обновления, который вызывает слой данных, вы не хотите тестировать слой данных, поэтому вы обычно вводите макет. Если вам нужно сначала пропустить этот фиктивный слой данных через всю логику калькулятора, настройка вашего теста будет намного сложнее, поскольку теперь имитация должна отвечать многим другим потенциальным требованиям, не связанным с реальным тестом, о котором идет речь.
Хотя этот подход поначалу является дополнительной работой, я бы сказал, что большая часть работы - это время, чтобы продумать дизайн, после этого, и после того, как вы освоитесь с более основанным на внедрении стилем кода, Необработанное время реализации программного обеспечения, структурированного таким образом, фактически сопоставимо.