12 posts tagged

программирование

Later Ctrl + ↑

Синглтон не только для конфигов

Singleton — первый шаблон проектирования о котором я узнал. Очень хорошо помню этот момент, по тому, что было это на собеседовании. Мое первое и, если честно, единственное техническое собеседование. Как уже догадался читатель, на вопрос «что такое синглтон и с чем его едят» я только удивленно моргал глазами. Правда, на работу меня все равно взяли. Может быть по тому, что после об]яснения мне в двух словах сути, общий механизм построения я описать смог.

Если что-то хочет познакомится с этим и гругими порождающими шаблонами, то можно обратиться к «банде четырех» или , ближе ко мне, Мэтт Зандстра – PHP. Объекты, шаблоны и методики программирования. Когда мы говорим про веб-разработку, то обычно мы слышим такие применения для Синглтона:

Первый пример

Первый, самый популярный, на мой взгляд, пример — подключение к базе данных. Это всегда казалось мне какой-то шляпой. Используя Синглтон мы гарантируем, что подключимся к база данных только один раз, а в дальнейшем будем использовать это подключение. Но что, если у нас несколько баз данных? «Ок,» — скажут знатоки — «если все реализовать правильно, то мы будем гарантировать, что к конкретной базе не будем подключаться более одного раза». Ну а если база одна, но коннектиться нужно от разных пользователей? «Ок,» — скажут знатоки, обозвав меня занудой и любителем придумывать проблемы — «ты можешь все написать так, что гарантируешь, что подключение к одной базе от имени одного пользователя будет единственно и его-то ты и будешь использовать дальше. И вообще суть в том, что ты сможешь использовать подключение в других классах не передавая его явно». А почему я не могу использовать global? Или просто статический метод? «Просто ты дурак и любишь поспорить. Это все гораздо хуже.» Это я слышал в разных интерпретациях много раз.

Второй пример

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

$class1 = myClass::getInstance();
$class2 = myClass::getInstance();
$class2->setA(3);
$class1->setA(5);
echo $class2->getA(); //5

То есть мы всегда гарантируем, что в любой момент времени в любом классе переменная A будет единой для всей системы. Чем это отличается от глобальных переменных, про которые любой новичок скажет, что «Так писать нельзя» ? Мне всегда было непонятно.

Другие примеры мне долгое время не встречались и я не понимал, нафига тогда этот синглтон нужен на самом деле и почему он делает код лучше. И вот сегодня ко мне пришло откровение

Мой вариант

В одном из наших проектов сложная система расчета цен для разных пользователей. Все началось с того, что все пользователи делятся на несколько ценовых групп, в каждой из которых есть своя наценка на каждую группу товаров. Позже оказалось, что есть поставщики с другой политикой. Они предоставляют прайс «для всех», а диллерам и постоянным покупателям дают от него скидки. Соответственно модель наценок на каждую товарную группу превратилась в модель наценка-или-скидка. Но и это еще не все. Есть клиенты (и их много), которые давно работают с нашими заказчиками и у них есть особые условия – специальная скидка или наценка на конкретный товар или группу товаров.

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

Итак, та-да-а-ам. Меня спас Синглтон. Паттерн гарантировал мне, что я лишь однажды запрашиваю из базы информацию о наценках/скидках, товарах и клиентах. А обрабатываю её по мере надобности. Так как запрос из базы самая «толстая» операция и мне удалось сократить количество запросов с примерно 80 до 3-4, мы получили прирост в производительности расчета примерно в 10 раз.

На практике это означает, что все стало «летать». И все благодаря тому, что мы не делаем лишних запросов к базе, за счет Синглтона.

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

 No comments   2015   web   программирование

Мой первый раз с WordPress

За три года, что я работаю в web-разработке мне как-то удавалось избегать самого популярного в мире движка, не считая совсем мелких правок. Но мне приходилось слышать от коллег различные мнения от «Какое извращение превращать блог в магазин, форум и все, что угодно!» до «Вполне адекватная CMS для небольших проектов.» И вот предоставилась возможность поработать с WordPress воочию.

Первый блин

Надо сказать, что странности начались с самого начала. Оказалось, что в текущей версии прямо в ядро включена возможность функционирования в режиме «multisite», т.е. такой режим в котором на одной и той же копии движка работают несколько сайтов. Сам этот факт для меня весьма удивительный. Я могу представить себя ситуацию, при которой мне необходима будет такая система, но включать этот функционал в ядро? И тем более использовать его для размещения никак не связанных друг с другом сайтов, кроме того факта, что они принадлежат одной компании. Это мне не понятно.

Как и любая работа над сайтом, эта началась для нас с копирования сайта (точнее сайтов) на наш сервер и бекапа. Почему мы даже для мелких работ используем демо-версию сайта я напишу отдельно.

В переносе мультисайта мне помогли заметки SiteHint.ru и WP MAGAZINE. Как я понял, сложности связанные с этим давно известны сообществу WP и обсуждать их смысла нет. Наверное, этой заметки бы не было, если бы сайт «завелся» сразу после этого без проблем.

Настоящее веселье

Самое интересное началось, когда я думал, что перенос уже завершен успешно. Один из разделов (всего один и самый важный!) загружался не до конца. То есть просто в какой-то момент html код обрывался, как говорится «на самом интересном месте».

«Плавали, знаем», подумал я и стал искать, как включить ошибки. Перепробовал все, что можно от включения в конфиге, путем определения констант:

define(‘WP_DEBUG’, false);
define(‘WP_DEBUG_LOG’, true);
define(‘WP_DEBUG_DISPLAY’, false);

до прямых директив

ini_set(‘log_errors’,’On’);
ini_set(‘display_errors’,’Off’);
ini_set(‘error_reporting’, E_ALL );

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

update_meta_cache(‘post’, $post_ids);

А в ней проблема возникает во время запроса кэша из БД:

$meta_list = $wpdb->get_results( “SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC”, ARRAY_A );

И, наконец, изучив объект $wpdb я нашел место падения

while ( $row = @mysqli_fetch_object( $this->result ) ) {
$this->last_result[$num_rows] = $row;
$num_rows++;
}

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

Решение

Убрав собачку я увидел уже истинную причину проблем:

Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 81 bytes) in /var/www/path_to_script/wp-db.php on line 1684

Временно забыть о проблеме с памятью удалось заменив в wp-config.php

define(‘WP_MEMORY_LIMIT’, ‘64M’);

На

define(‘WP_MEMORY_LIMIT’, ‘128M’);

Конечно, нужно искать причину, почему скрипт «жрет» столько оперативки, но это уже не срочно.

Как так

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

Пока эти вопросы остались для меня без ответа. Если что-то изменится, напишу продолжение поста.

P.S. Все вышесказанное о движке WordPress 4.1.8

 4   2015   web   программирование