Заказал код у фрилансера с Avito за тысячу рублей в час. Результат оказался хуже, чем при оплате 500 рублей в час. Это заставило задуматься о связи цены и качества кода.
Разбор кода фрилансера
Код содержал странные и неэффективные техники. Вместо прямых ссылок на объекты сцены, использовались их имена, поиск осуществлялся через GameObject.Find. Это создавало множество списков с именами и ссылками, снижая производительность. Код отличался нелогичной структурой, смешением русского и английского языков и нечитабельным стилем. Реализация синглтона была нестандартной и запутанной.
Ошибки рефакторинга и их исправление
В предыдущем видео показан рефакторинг кода. Зрители указали на недостатки, многие из которых справедливы. Разберём их для улучшения качества кода.
Ошибки рефакторинга:
- Дублирование кода и некорректное сравнение дистанций: При копировании кода не были заменены объекты, дистанция сравнивалась сама с собой. Ошибка исправлена изменением сравнения в transform.positions. Теперь сравниваются текущая и предыдущая точки.
- Неэффективное использование GetComponent и Vector3.Distance: Изначально код содержал два вызова Vector3.Distance и GetComponent, снижая производительность.
- Неоптимальное размещение вызовов методов: Методы размещались внутри метода, вызываемого не каждый кадр. Оптимизация — вынесение вызова метода вне цикла обновления.
Оптимизация кода: измерение производительности
Перед оптимизацией были определены ключевые показатели эффективности (KPI). Использовался Unity Profiler для замера времени выполнения кода до и после оптимизации. Для более точных замеров количество объектов было увеличено.
Замер производительности показал, что основной спад производительности связан не с вызовами GetComponent или Vector3.Distance, а с неэффективной работой с пространством и отсутствием математического разбиения. Оптимизация GetComponent не дала значительного прироста производительности.
Этапы оптимизации:
- Удаление ненужных проверок и промежуточных шагов: Убраны лишние предусловия, вызовы GetComponent и работа с Linq. Это ускорило код примерно в 2 раза.
- Оптимизация вычисления дистанции: Вместо вычисления квадратного корня используется теорема Пифагора, снижая количество вычислений. Это дало дополнительное ускорение на 30%.
- Удаление вызова Physics.Raycast: Удаление вызова Physics.Raycast улучшило производительность на 3%.
В итоге, код был оптимизирован примерно в три раза. Дальнейшая оптимизация (планируется в следующем видео при достаточном количестве лайков) позволит ускорить код в 10 раз.
Дополнительные замечания
Отмечены и другие моменты, требующие улучшения:
- Избыточные проверки: Проверки в методе Fight можно оптимизировать.
- Использование Count: Вместо Count для проверки пустоты списка лучше использовать проверку на null или пустоту.
- Неэффективная сортировка: OrderBy для поиска ближайшего объекта неэффективен. Лучше использовать Min.
- Наименование событий: Стиль именования событий может быть улучшен.
- Методы расширения: Использование методов расширения — спорный момент.
- Именование параметров: Именование параметров может быть улучшено.
- Доступность методов расширения: Публичная доступность некоторых методов расширения нецелесообразна.
- Обработка исключений: Обработка исключений может быть улучшена.
- Контрактное программирование: Рекомендуется использовать фреймворки для контрактного программирования.
- Проверка на false: Предпочтительнее явное сравнение с false, а не !.
- Проверка типа float: Необязательно проверять тип float, достаточно проверять на отрицательное значение.
Опыт показал, что цена не всегда гарантирует качество кода. Даже за значительную сумму можно получить неэффективный и плохо написанный код. Важно тщательно проверять и оптимизировать код для повышения производительности. Хороший код — инвестиция в долгосрочный успех проекта.