5. Рефакторинг кода

5. Рефакторинг кода

Рефакторинг — это улучшение внутренней структуры программного обеспечения с целью упростить его понимание и удешевить модификацию без изменения видимого поведения программного обеспечения.

Цель реконструкции (почему), объект (что), время (когда) и метод (как);

Зачем рефакторить (почему)?

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


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

Что именно рефакторится?

Под крупномасштабным рефакторингом понимается реконструкция конструкции кода верхнего уровня, включающая: реконструкцию систем, модулей, структур кода, отношений между классами и т. д. К методам реконструкции относятся: наслоение, модульность, развязка, абстрактные повторно используемые компоненты и т. д. Инструментами этого типа рефакторинга являются дизайнерские идеи, принципы и шаблоны. Этот тип рефакторинга потребует большего количества изменений кода и окажет большее влияние, поэтому он будет более сложным и трудоемким, а риск появления ошибок будет относительно высоким.


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

Когда проводить рефакторинг (когда)?

Непрерывный рефакторинг; при изменении или добавлении определенного функционального кода рефакторинг дизайна, который не соответствует стандартам кодирования или не является хорошим.

Как провести рефакторинг (как)?

При проведении масштабного рефакторинга мы должны заранее составить полный план рефакторинга и действовать поэтапно и упорядоченно. На каждом этапе небольшая часть кода подвергается рефакторингу, затем отправляется, тестируется и запускается. После того, как проблем не обнаружено, продолжается следующий этап рефакторинга, чтобы гарантировать, что код в хранилище кода всегда находится в работоспособном и логически работоспособном виде. правильное состояние. На каждом этапе мы должны контролировать объем кода, затрагиваемый рефакторингом, учитывать, как обеспечить совместимость со старой логикой кода, и при необходимости писать совместимый переходный код. Только так мы сможем не допустить, чтобы каждый этап рефакторинга занимал слишком много времени (желательно, чтобы его можно было завершить за один день), и предотвратить его конфликт с разработкой новых функций.


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

Зачем писать модульные тесты?

  1. Модульное тестирование может эффективно помочь вам найти ошибки в вашем коде.
  2. Написание модульных тестов может помочь вам найти проблемы в дизайне кода.
  3. Модульное тестирование — мощное дополнение к интеграционному тестированию.

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


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

  1. Сам процесс написания модульных тестов — это процесс рефакторинга кода.

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

  1. Чтение модульных тестов может помочь вам быстро ознакомиться с кодом.

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

  1. Модульное тестирование — это улучшенное решение для TDD, которое можно реализовать на практике.

Сначала напишите код, затем напишите модульные тесты и, наконец, определите проблемы на основе отзывов модульных тестов, а затем вернитесь и восстановите код. Этот процесс разработки легче принять и реализовать, а также он учитывает преимущества TDD.

Написание модульных тестов?

  • Охватывают ли тестовые примеры все возможные ситуации?

  • Он не полагается на конкретную логику реализации тестируемой функции, а заботится только о том, какие функции реализует тестируемая функция.

  • Внедрение зависимостей — наиболее эффективный способ написания тестируемого кода. Благодаря внедрению зависимостей при написании модульных тестов мы можем использовать фиктивные методы для устранения зависимости от внешних сервисов.

  • Распространенные антипаттерны

    1. ожидающее действие

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

    1. глобальные переменные
    2. статический метод

    Статические методы также сложно имитировать. Однако это зависит от ситуации. Только когда этот статический метод выполняется слишком долго, полагается на внешние ресурсы, имеет сложную логику и ожидающее поведение, нам нужно имитировать этот статический метод при модульном тестировании. Кроме того, если это простой статический метод типа Math.abs(), это не повлияет на тестируемость кода, поскольку нет необходимости в насмешках.

    1. Сложное наследование

    Если родительскому классу необходимо имитировать зависимый объект для модульного тестирования, то все подклассы, подклассы подклассов... должны имитировать этот зависимый объект при написании модульных тестов. Для отношений наследования с глубокими уровнями (показаны как вертикальная глубина на диаграмме классов отношений наследования) и сложными структурами (показаны как горизонтальная ширина на диаграмме классов отношений наследования) подклассы более низкого уровня могут иметь больше объектов для имитации. базовый подкласс для издевательства над многими зависимыми объектами один за другим при написании модульных тестов, а также необходимо проверить код родительского класса, чтобы понять, как издеваться над этими зависимыми объектами.

    1. Сильно связанный код

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

Большой рефакторинг (масштабный высокоуровневый)

1. Почему «разъединение» так важно?

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

  1. Нужно ли «отвязывать» код?

Есть много косвенных мер, например, влияет ли изменение кода на весь организм. Прямой критерий — нарисовать зависимости между модулями и классами и судить о необходимости развязки и реконструкции, исходя из сложности диаграммы зависимостей.

  1. Как «отсоединить» код?

Методы разделения кода включают в себя: инкапсуляцию и абстракцию, промежуточные уровни, модульность и некоторые другие идеи и принципы проектирования, такие как: принцип единой ответственности, программирование, основанное на интерфейсах, а не на реализации, внедрение зависимостей, использование большего количества композиции и меньшего наследования, Discipline Mitte Закон и т. д. Шаблоны проектирования, такие как шаблон Observer.

Небольшой рефакторинг (небольшой масштаб и низкий уровень)

おすすめ

転載: blog.csdn.net/weixin_46488959/article/details/126918989