Совершенствование кода рефакторинг реферат

Обновлено: 30.06.2024

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

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

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

Без рефакторинга не обходится ни один действительно сложный и долгоживущий проект

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

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

Тем не менее, рефакторинга только в процессе разработки отдельных компонентов не достаточно. Если разрабатываемый компонент не изолирован, а взаимодействует с другими, то обычно есть необходимость в рефакторинге программных интерфейсов, через которые это самое взаимодействие реализуется.

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

Наиболее частые причины для рефакторинга:

  • дублирование кода
  • длинные методы
  • объёмные классы
  • длинные списки параметров
  • избыточные временные переменные
  • классы данных
  • несгруппированные данные
  • несоблюдение стандартов кодирования

Рефакторинг очень существенно влияет на сопровождаемость проекта

Рефакторинг и оптимизация производительности

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

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

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

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

Оптимизация в основном фокусируется на одиночном или повторном времени выполнения, использовании памяти, дискового пространства, пропускной способности или некотором другом ресурсе. Это обычно требует компромиссов — один параметр оптимизируется за счёт других.

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

Для оптимизации требуется найти узкое место (англ. hotspot): критическую часть кода, которая является основным потребителем необходимого ресурса. Улучшение примерно 20 % кода иногда влечёт за собой изменение 80 % результатов. Для поиска узких мест используются специальные программы — профайлеры.

Чем больше памяти использует программа, тем быстрее она обычно выполняется.

Простейшие приёмы оптимизации:

- Инициализация объектов данных (Правильная инициализация объектов позволяет сэкономить процессорное время.)

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

Приоритеты оптимизации:

• интерфейсный, т.е. желательно заранее ВСЁ согласовать с другими участниками проекта, включая кому сколько процессорного времени на конкретном ПК.

• Если ПК не является современным и многопроцессорным, заведомо сильно ограничить суммарный CPU расход, можно утилитами типа slowcpu.

• согласовать и обсудить - не спеша, и каждую мелочь вплоть до того где использовать ООП, а где нет - для ускорения.

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

Рефакторинг — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы[1]. В основе рефакторинга лежит последовательность небольших эквивалентных (то есть сохраняющих поведение) преобразований.

Цель рефакторинга — сделать код программы легче для понимания.

Рефакторинг следует отличать от оптимизации производительности. Как и рефакторинг, оптимизация обычно не изменяет поведение программы, а только ускоряет ее работу. Но оптимизация часто затрудняет понимание кода, что противоположно рефакторингу[2].

Основные стимулы его проведения являются следующие задачи:

- необходимо добавить новую функцию, которая недостаточно укладывается в принятое архитектурное решение;

Сборка, внедрение и поставка ПО

Программа – это не только .exe модуль. Скорее всего он зависит от своего окружения: системные библиотеки и компоненты Windows, исполняющая среда, Dll библиотеки.

Средство создания дистрибутивов мы будем называть инсталлятор. Под словом дистрибутив понимаем распространяемые файлы программы — обычно это Setup.exe плюс, возможно, еще несколько файлов.

Bootstrapper. Эта часть программы установки запускается первой и ее задача — подготовить все необходимое для работы installation engine. В частности, в случае использования Windows Installer, bootstrapper обеспечивает установку или обновление Windows Installer до требуемой версии.

Программа установки либо использует свой собственный installation engine, либо пользуется услугами сервиса Windows Installer. Installation engine выполняет всю основную работу: взаимодействует с пользователем через GUI, создает/удаляет папки и ключи реестра, копирует файлы, регистрирует компоненты


Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого.



Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни.


Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰).

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

Цель рефакторинга — сделать код программы легче для понимания; без этого рефакторинг нельзя считать успешным. Рефакторинг следует отличать от оптимизации производительности. Как и рефакторинг, оптимизация обычно не изменяет поведение программы, а только ускоряет её работу. Но оптимизация часто затрудняет понимание кода, что противоположно рефакторингу. С другой стороны, нужно отличать рефакторинг от реинжиниринга, который осуществляется для расширения функциональности программного обеспечения. Как правило, крупные рефакторинги предваряют реинжиниринг.

Причины применения рефакторинга

Рефакторинг нужно применять постоянно при разработке кода. Основными стимулами его проведения являются следующие задачи:

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

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

Признаки плохого кода

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

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

Среди признаков плохого кода можно выделить основные:

Дублирование кода - это использования одинаковых структур кода в нескольких местах. Объединение этих структур позволит улучшить программный код.

Примеры дублирования и методы их устранения:

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

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

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

Длинный список параметров

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

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

когда подключается новая база данных, а четыре — при добавлении финансового инструмента).

Если нет подходящего класса, то следует создать новый класс;

Метод обращается к данным другого объекта чаще, чем к собственным данным.

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

Группы данных, встречающихся совместно, нужно превращать в самостоятельный класс.

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

Одержимость элементарными типами

Проблема связана с использованием элементарных типов, вместо маленьких объектов для небольших задач, таких как валюта, диапазоны, специальные строки для телефонных номеров и т. п.

(Replace Type Code with State/Strategy).

Операторы типа switch

Одним из очевидных признаков объектно-ориентированного кода служит сравнительно редкое использование операторов типа switch (или case). Часто один и тот же блок switch оказывается разбросанным по разным местам программы. При добавлении в переключатель нового варианта приходится искать все эти блоки switch и модифицировать их. Как правило, заметив блок switch, следует подумать о полиморфизме.

Если switch переключается по коду типа, то следует использовать

Параллельные иерархии наследования

В коде с таким запашком всякий раз при порождении подкласса одного из классов приходится создавать подкласс другого класса.

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

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

Проектирование

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

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

1. SOLID (single responsibility, open-closed, Liskov substitution, interface segregation и dependency inversion)

Это основа основ в проектировании классов. Если вы еще не знакомы с SOLID, здесь можно ознакомиться.

2. DRY (do not repeat yourself)

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

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

— Вместо использования функции progress50(), лучше применить более абстрактную progress($percent).

— Отдавать предпочтение внешним зависимостям между модулями, внутренним (DI), что делает модуль более гибким и позволяет его использовать в нескольких местах.

3. KISS (keep it simple, stup. )

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

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

Стиль кода

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

Несколько замечаний, которые автор счел важными:

1. Ознакомьтесь с PHPDOC для написания комментариев к вашему коду.

2. Лучший комментарий — это правильно названный класс, метод, параметр или переменная.

3. Используйте утилиты PHPMD, PHPCS, их применение шире, чем только для определения несоответствий в стиле кода. Вот документация: PHPMD, PHPCS.

4. Используйте продвинутое IDE.

Рефакторинг в чистом виде

Я помню, как работал на одну компанию, и проверку кода у меня делал человек, который не всегда мог сдерживать свои эмоции, из-за чего о моем не чистом коде слышали все в open space. Поэтому мне приходилось учиться писать качественный код, очень быстро, чтобы избежать подобных случаев.

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

1. Длинные методы (лучше разделить функционал на несколько методов).

2. Громоздкие классы (ваш класс должен исполнять одну функциональную задачу в вашей системе).

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

4. Слишком много параметров в методе (некоторые расчеты можно сделать внутри метода, используя внутренние константы, значения полученные с атрибутов и геттеров).

5. Классы, содержащие одинаковые переменные и методы. Проблему можно решить через создание дополнительного класса).

6. Сложно читаемый IF (выражение можно вынести в отдельную переменную и разделить на логические части, которые также вынести в переменные, если много проверок на null, то лучше всего использовать NullObject — количество проверок значительно уменьшится).

7. Громоздкий SWITH (выносим в отдельный метод).

9. Слишком большое количество маленьких классов для выполнения одной задачи, которые в последствии сложнее поддерживать.

10. Слишком сложный функционал в одном классе, который можно разделить на несколько классов.

11. Класс делает слишком мало, чтобы его оставлять в системе.

13. Не использованные структуры классов, которые вы проектировали на будущее, но они так и не пригодились — такие лучше удалить.

14. Методы класса больше используются в другом классе, а в своем вообще не используются или же реже (стоит перенести метод в тот класс, где он больше используется).

15. Слишком длинная цепочка вызовов ($a->b()->c()->d()->e()), в этом случае стоит создать дополнительные методы.

17. Слишком много действий в конструкторе. (Конструктор должен только устанавливать свойства класса, если же в конструкторе создаются другие классы, происходят какие-то расчеты, то это делает его сложным для понимания, приходится вникать в суть реализации. Чтобы создать объект и выполнить какие-то действия, добавьте статический метод create($param1, . ), который создаст экземпляр класса с дополнительными действия над ним, этот метод можно назвать более подходящим к тому, что он будет все же делать).

Читайте также: