Заказанный на сомнительной бирже код, стоивший 500 рублей, демонстрирует крайне низкое качество. Этот пример наглядно показывает необходимость рефакторинга даже в работающем коде. Представлены исходный и рефакторированный код классов Cube и CubeManager.
Анализ исходного кода: Класс Cube
Исходный код содержит два класса: Cube и CubeManager. Класс Cube отвечает за управление отдельным кубом, атакующим противника. Кубы разбросаны на сцене и сражаются парами. Класс управляет перемещением и нанесением урона.
Предполагается наличие полей health (здоровье) и cooldown (время перезарядки). Поле cube2 хранит ссылку на противника. Использование публичных полей (health, cooldown, cube2) является грубым нарушением принципов ООП. Несогласованность в стиле именования полей (одно с большой, другое с маленькой буквы) ухудшает читаемость. Имя поля cube2 неинформативно. Метод Start содержит стандартные, бесполезные комментарии.
Метод Update, выполняемый каждый кадр, включает отсчёт кулдауна, проверку дистанции до противника (transform.Translate) с использованием магического числа 0.1 (расстояние в метрах). Нарушена стилистика кода: в одних блоках if используются фигурные скобки, в других — нет. Отступы отсутствуют. Перемещение происходит только при дистанции до противника больше единицы. Проверка кулдауна, его сброс и изменение здоровья противника (health) осуществляется через прямой доступ к публичному полю, что нарушает инкапсуляцию. Отсутствие контроля объекта над собственным здоровьем приводит к проверке здоровья в каждом кадре для уничтожения объекта при нулевом значении. Качество кода не соответствует даже уровню junior-разработчика.
Анализ исходного кода: Класс CubeManager
Класс CubeManager хранит всё состояние в методе Update. Поиск ближайшего свободного противника и назначение пар для битвы реализованы с помощью двух вложенных циклов и неудачного именования переменных. Поиск всех объектов осуществляется каждый кадр, что значительно снижает производительность. Связь между строками кода трудно проследить.
Рефакторинг кода: Класс Cube
Рефакторинг класса Cube включает:
- Перевод полей health и cooldown в приватные с префиксом _ (_health, _cooldown).
- Переименование поля cube2 в _target.
- Создание метода TakeDamage для нанесения урона с проверкой на отрицательный урон.
- Перемещение проверки здоровья в метод TakeDamage.
- Добавление фигурных скобок к блокам if.
- Вынесение магического числа в поле.
- Изменение порядка строк в Update для повышения читаемости.
- Передачу ссылки на компонент и вызов метода TakeDamage вместо использования GetComponent.
- Разделение метода Update на части: таймер, проверка состояния, движение и атака.
Рефакторинг кода: Класс CubeManager
Рефакторинг класса CubeManager:
- Замена GameObject.FindGameObjectsWithTag на список кубов.
- Использование FindObjectsOfType для поиска объектов по типу.
- Создание свойства FreeCubes для хранения списка свободных кубов.
- Перебор свободных кубов в методе Update.
- Создание метода FindClosestCube для поиска ближайшего противника с проверкой на то, что куб не является самим собой.
- Добавление обработчика события смерти куба (OnCubeDeath) для удаления куба из списка FreeCubes.
- Добавление обработчика события OnDestroy для удаления подписки на событие OnCubeDeath.
Завершение рефакторинга
После рефакторинга код стал более чистым и понятным. Некоторые улучшения, например, избавление от лишних проверок, требуют дополнительной работы.