Как провести рефакторинг: разделить класс на два, которые общаются через интерфейс

StackOverflow https://stackoverflow.com/questions/229438

Вопрос

Я только начинаю свой первый крупномасштабный рефакторинг, и мне нужно разделить (к сожалению, большой) класс на два, которые затем взаимодействуют только через интерфейс. (Мой Presenter оказался контроллером и должен отделить логику графического интерфейса от логики приложения). Используя C # в VisualStudio 2008 и Resharper, какой самый простой способ добиться этого?

Я собираюсь попробовать а) собрать членов для нового класса и "извлечь новый класс"; б) навести порядок c) "Извлечь интерфейс" d) выследить любые ссылки на класс и преобразовать их в ссылки интерфейса

но я никогда не делал этого раньше, и удивляюсь, знает ли кто-нибудь какие-нибудь хорошие советы или ошибки, прежде чем я начну все разрывать на части ... Спасибо!

Это было полезно?

Решение

Детские шаги.

Шаг 1. Внесите небольшое изменение, используя отличный рефакторинг Resharper.
Шаг 2: Тестирование (желательно модульное тестирование), чтобы убедиться, что код все еще работает
Шаг 3. Передайте управление исходным кодом

Повторите эти 3 шага много раз.

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

Другие советы

Называй меня старомодным, но лично я использую описанные тобой автоматические функции только для технических задач (таких как переименование и т. д.)

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

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

Сначала краткий ответ, я напишу об этом в блоге, спасибо за идею!

Итак, давайте предположим, что у нас есть это:

class PresenterAndController
  {
    public void Control()
    {
      Present();
    }

    public void Present()
    {
      // present something
    }
  }

Во-первых, нам нужно преобразовать все прямые использования членов в косвенные, то есть определить их с помощью поля. Для этого используйте рефакторинг экстракта суперкласса для извлечения части Presenter в суперкласс:

  internal class Presenter
  {
    public void Present()
    {
      // present something
    }
  }

  class PresenterAndController : Presenter
  {
    public void Control()
    {
      Present();
    }
  }

Создайте поле в PresenterAndController, которое будет делегировать одно, и используйте Generate (Alt-Ins) для создания делегирующих членов. Они будут скрывать базовые методы, так как они одинаковые:

  internal class Presenter
  {
    public void Present()
    {
      // present something
    }
  }

  class PresenterAndController : Presenter
  {
    private Presenter myPresenter;

    public void Present() // hides base method
    {
      myPresenter.Present();
    }

    public void Control()
    {
      Present(); // it now references method from this type
    }
  }

Удалите Presenter из списка наследования, и все готово для разделения классов. Теперь вы можете извлекать интерфейсы, использовать базовые типы, где это возможно, и иным образом приводить их в порядок.

Я никогда не использовал VisualStudio, но нахожу, что автоматический рефакторинг в Eclipse достаточно надежен - по крайней мере, настолько же надежен, как если бы я выполнял ту же работу.

Прежде чем сделать это, инвестируйте в контроль версий: изучите Git. Рефакторинг без SCM походит на вождение с завязанными глазами.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top