Фон
Я работаю над текущим проектом C #. Я не программист C #, в первую очередь программист C ++. Так что передо мной были поставлены простые задачи по рефакторингу.
Код это беспорядок. Это огромный проект. Поскольку наш клиент требовал частых выпусков с новыми функциями и исправлениями ошибок, все остальные разработчики были вынуждены использовать грубый подход при кодировании. Код крайне не поддерживаемый, и все другие разработчики согласны с ним.
Я здесь не для того, чтобы спорить, правильно ли они это сделали. Поскольку я занимаюсь рефакторингом, мне интересно, правильно ли я это делаю, поскольку мой рефакторинг кода кажется сложным! Вот моя задача как простой пример.
проблема
Есть шесть классов: A
, B
, C
, D
, E
и F
. У всех классов есть функция ExecJob()
. Все шесть реализаций очень похожи. В основном сначала A::ExecJob()
было написано. Затем потребовалась немного другая версия, которая была реализована B::ExecJob()
путем копирования-вставки-модификации A::ExecJob()
. Когда требовалась другая, немного другая версия, C::ExecJob()
была написана и так далее. Все шесть реализаций имеют некоторый общий код, затем несколько разных строк кода, затем снова некоторый общий код и так далее. Вот простой пример реализации:
A::ExecJob()
{
S1;
S2;
S3;
S4;
S5;
}
B::ExecJob()
{
S1;
S3;
S4;
S5;
}
C::ExecJob()
{
S1;
S3;
S4;
}
Где SN
группа точно таких же утверждений.
Чтобы сделать их общими, я создал другой класс и переместил общий код в функцию. Использование параметра для управления тем, какая группа операторов должна быть выполнена:
Base::CommonTask(param)
{
S1;
if (param.s2) S2;
S3;
S4;
if (param.s5) S5;
}
A::ExecJob() // A inherits Base
{
param.s2 = true;
param.s5 = true;
CommonTask(param);
}
B::ExecJob() // B inherits Base
{
param.s2 = false;
param.s5 = true;
CommonTask(param);
}
C::ExecJob() // C inherits Base
{
param.s2 = false;
param.s5 = false;
CommonTask(param);
}
Обратите внимание, что в этом примере используются только три класса и упрощенные операторы. На практике CommonTask()
функция выглядит очень сложной со всей этой проверкой параметров, и есть еще много операторов. Кроме того, в реальном коде есть несколько CommonTask()
функций просмотра.
Хотя все реализации совместно используют общий код, а ExecJob()
функции выглядят симпатичнее, существуют две проблемы, которые меня беспокоят:
- Для любого изменения
CommonTask()
необходимо протестировать все шесть (и может быть больше в будущем) функций. CommonTask()
это уже сложно. Со временем это станет более сложным.
Я делаю это правильно?