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

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

Я собираюсь попробовать а) Соберите члены для нового класса и «извлеките новый класс». б) убрать образовавшийся беспорядок в) «Извлечь интерфейс» г) отслеживать любые ссылки на класс и преобразовывать их в ссылки на интерфейсы

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 462
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Шаги малыша.

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

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

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

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

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

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

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

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

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

Сначала нам нужно преобразовать использование всех прямых членов в косвенные, то есть квалифицировать их с помощью поля. Для этого используйте рефакторинг суперкласса extract для извлечения части 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 похож на вождение с завязанными глазами.

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