Статьи

Рефакторинг практического кода, часть 4 — Эффективность

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

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

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

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

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

Неэффективность пропускной способности сети

1. Минимальные ли запросы ресурсов с сервера?

Веб-приложение — это некая бизнес-логика (написанная, например, на PHP), которая генерирует HTML, CSS и JavaScript для загрузки клиентом (обычно браузером). Имейте в виду, что у вас всегда есть кто-то, «ожидающий» загрузки вашей страницы, и он не хочет ждать очень долго. Вообще говоря, ваша страница должна загружаться примерно за 2,5 секунды при соединении 512 Кб. Для тяжелых страниц это не должно превышать 5-10 секунд, иначе пользователь начнет испытывать нетерпение. Чтобы достичь этого, вам нужно сократить количество ресурсов, запрашиваемых у сервера. Вместо того, чтобы загружать много CSS-файлов, объедините их в один файл. То же самое касается JavaScript. Затем оптимизируйте эти совокупные файлы дальше.

Вы можете легко уменьшить размер файлов CSS и JavaScript, по крайней мере, на 30%, если вы используете компрессоры / минимизаторы JavaScript, такие как YUI JS Compressor и CSSO. Некоторые могут утверждать, что это считается оптимизацией, а не рефакторингом кода, но на этом этапе есть некоторое совпадение, поскольку вы минимизируете свой код, чтобы минимизировать размер файла.

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

2. Мудро ли вы используете серверные обратные вызовы?

Большинство современных веб-приложений основаны на Ajax и, естественно, вызывают сервер в фоновом режиме. Это хорошо, если обратные вызовы вашего сервера не имеют большой задержки. Не злоупотребляйте Ajax для простых задач, которые не требуют сервера. Используйте его только тогда, когда вам действительно нужно извлечь что-то с сервера, а не для настоящих данных в реальном времени. Если вам требуются данные в реальном времени, рассмотрите возможность использования таких методов передачи данных, как Comet и WebSockets.

Недостатки памяти

1. Используете ли вы рекурсию?

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

2. Вы повторяете слишком много?

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

Кроме того, для большинства ваших циклов у вас всегда должны быть условия, близкие к разрыву, чтобы избежать задержки загрузки страницы. Например, вы можете захотеть перебирать последние 20 новостных лент, но почему бы не только последние 5, а затем предоставить хорошую ссылку «больше»? Думайте таким образом, и вы можете увеличить скорость вашей страницы.

3. Запланированы ли ваши запросы?

Задержка базы данных очень распространена как узкое место в приложениях PHP, поэтому вы всегда должны планировать свои запросы. Кто из нас написал что-то подобное?

select * from users;

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

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

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

Неэффективность обработки

1. Вам нужны динамические языковые функции?

PHP обладает множеством динамических функций, таких как перегрузка методов получения и установки, динамическая реализация и вызов метода / функции, даже самый опасный метод eval() Используйте все это с умом. Это могут быть волшебные элементы некоторых креативных решений нестандартных задач, но, вообще говоря, они вам не нужны в стандартном веб-приложении, в котором чрезмерное использование лишней дополнительной сложности.

2. Используете ли вы хорошие навыки кодирования?

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

Резюме

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

Рефакторинг — это важный метод разработки программного обеспечения, обеспечивающий работоспособность кода. В этой серии я представил практические списки, которые вы можете использовать при рефакторинге. Я говорил о хорошем коде и о том, как добиться хорошего кода с точки зрения читабельности, расширяемости и эффективности. Надеюсь, вам понравится читать сериал, так как мне понравилось писать его! 🙂

Изображение через Fotolia