О блоге

@nger-блог - блог, где я выкладываю свои мысли в основном на технические темы, перемежая их с разными философствованиями.

Rss -каналы

Браузеры для верстальщика

Сегодня я хотел бы затронуть такую тему, как использование HTML-верстальщиком различных браузеров. А точнее, поделиться своим подходом к оному.

Во-первых, для начала следует определиться с распределением "рынка сбыта" - долями различных браузеров у пользователей. А поможет нам в этом статистика от LiveInternet. Какая-никакая, а выборка. Несколько субъективное мнение, но я считаю, что верстать нужно по сути под первые 6 браузеров - IE 6, IE 7, Opera 9, Opera Mini, Firefox 2, Firefox 3. На самом деле, вся вёрстка разделится на 2-4 стиля - под настольные браузеры(возможно, отдельно под IE 6, IE 7) и Opera Mini. По сути, что под Opera Mini, что под другие PDA-браузеры, файл стилей может быть один. На стороне сервера мы просто смотрим User-Agent и отдаём мобильной опере нужный CSS-файл, а всем остальным - обычные, для IE можно использовать conditional comments. Теперь подробнее об инструментарии.

Разработка. Firefox 2 + Firebug + Web Developer Toolbar. Это стандарт де-факто. Крайне функционально и удобно. Я в дополнение к этим плагинам использую IE Tab, зачастую удобнее чем окно Internet Explorer'а. И какой-нибудь текстовый редактор. Я привык к UltraEdit. И, конечно, фотошоп или аналог для резки PSD-макета.

Тестирование. Virtual Machine. Virtual Box с Windows XP на борту - широкое поле для экспериментов. Там у меня стоят: Firefox 3, Opera 9.23, Opera 9.27, Opera 9.5, Safari 3.1.2, Internet Explorer 8 Beta 1(включен в режим симуляции IE 7). Таким образом, я охватываю очень широкий спектр браузеров на PC. Остальные платформы куда менее распространены. Впрочем, есть ещё Mac. Можно, конечно, купить MacBook или что-то подобное для тестов или для пользования, но заядлым PC-шникам это может оказаться невыгодным. Сам я пока не дошёл до виртуализации Mac OS X на PC, но это дело времени и трафика Для тестирования в Opera Mini я использую эмулятор от производителя, затем тестирую на своём телефоне. Требуется это далеко не всегда, но уж если делать на 100% грамотно - это необходимо.

Надеюсь, что кому-нибудь моя статья поможет. И если ещё кто-то думает, ставить виртуальную машину или нет - решит, что ставить. Ведь переустановить ось, откатиться, связать в "сеть" несколько машин куда проще используя технологии виртуализации. Как всегда, жду ваших комментариев.

Комментарии [5] | опубликовано: 2008-07-16 01:27

Схема работы с Subversion из-под Windows

В предыдущей заметке я уже писал, что решил перенести выполнение скриптов на виртуальную машину ака Linux сервер. Мотив тогда был немного прозаичнее, чем просто желание покрутить на линуксе код – у меня начались глюки с веб-сервером под виндой. Видимо, стояла не-thread-safe сборка php и скрипты при параллельной загрузке начали валиться, видеть память друг друга и т.д.

Однако, поюзав некоторое время систему “пишу на Windows, выполняю на Linux” я решил откатиться к менее радикальной – “пишу и тестирую на Windows, окончательно проверяю на Linux”.

Суть схемы “пишу и тестирую на Windows, окончательно проверяю на Linux”

Всю разработку я веду под Microsoft Visual Studio с расширениями VS.PHP и VisualSVN. Также, на Windows-хост-машине установлен Tortoise SVN. Для тестирования давно поднят Денвер(мне нравится его система работы с виртуальными серверами, а вернее простой скриптик, добавляющий в hosts инфу о них), в одном из виртуальных серверов которого сделана рабочая копия репозитория с Linux-сервера. Также, стандартный денверовский MySQL выключен, вместо него поставлен MySQL Server 5.0. Однако, он сейчас не используется – главным SQL-сервером стал тот же MySQL 5.0, только на Linux-виртуальной машине. Также, на Linux поднят svn-сервер, FTP-сервер и настроен httpd.

Организация работы.

Имея уже настроенные 2 сервера – тестировочный и почти продакшн, мы можем, во-первых, удобно тестировать проект под разными средами, а во-вторых(дело вкуса), писать под удобным(для кого как, но для меня удобным) Visual Studio, при этом быстро проверяя как себя ведёт код не только под Windows, но и под Linux.

Всю писанину я провожу под Windows. Написав какой-то код, я отлаживаю его на локальном тестировочном сервере. Затем, если всё в порядке – делаю Commit изменений и они вносятся в репозиторий на Linux-SVN-сервере. Затем, SVN, юзая hook post-commit делает chekout(проверку и обновление) рабочей копии в папке /var/www/html на Linux-сервере. То есть при commit’е я сразу вижу обновлённый код в папке Apache под Linux’ом. Далее я уже перехожу к тестированию кода под Linux.

Профилирование и отладка

Заниматься профилированием под Windows, я считаю, не очень выгодно и очень неудобно. А вот отлаживать на Windows вполне себе можно. Начиная с обычных var_dump’ов и заканчивая продвинутой отладкой с breakpoint’ами(правда до этого я ещё не успел дойти).

Гораздо интереснее дела обстоят под Linux. Там также есть xDebug, но ещё есть удобный инструмент профилирования – kCacheGrind. И если его аналог под Windows, WinCacheGrind, глючен и убог, то kCacheGrind очень юзабельный продукт. Естественно, бесплатный. То есть, я занимаюсь основной отладкой под Windows, а профилированием – под основной средой выполнения, то есть Linux.

При внесении правок под Linux, можно не волноваться за Windows-сторону: после изменения кода нужно сделать commit со стороны рабочей копии под Linux-Apache-сервером и на Windows-стороне сделать Update. Тогда обе копии будут идентичны.

Думаю, я разъяснил преимущества, с моей точки зрения, Windows-конструирования и Linux-выполнения. Кто-то предпочитает полностью сидеть в Linux, я же пока к этому не готов. Новички в PHP вообще редко задумываются о Linux-использовании, ведь чтобы поставить Linux, PHP, SVN, MySQL и т.д. это нужно много(мы говорим о новичках) времени и сил. Я же пока остановился на вышеизложенном варианте. Спасибо за внимание.

Комментарии [1] | опубликовано: 2008-07-05 12:54

Отладочный php-сервер на локальной машине - Windows или Linux?

Да, вот такой вот немного странный вопрос - а на чём, собственно, отлаживать скрипты PHP? С одной стороны - Windows более привычна, особенно начинающим, под неё много софта, который можно применить в веб-разработке(например, Visual Studio), да и IE под Linux, мягко говоря, другой. С другой стороны - писать лучше на той платформе, на которой скрипты будут использоваться. Так что же выбрать?

Я решил совместить - писать скрипты под Windows, а сам сервер крутить на Linux. Как? Очень просто. Виртуальная машина. Всё-таки Windows у меня уже несколько лет, поэтому переходить на Linux в ближайшее время не собираюсь, следовательно, мой выбор очевиден - поставить VM на Windows и уже на VM - Linux.

Для начала я скачал виртуальную машину. Microsoft VirtualPC почему-то отказался запускать Linux на виртуалке, VMWare оказался неподъёмным для моего GPRS-канала, а вот VirtualBox подошёл прекрасно - и весит немного, и линукс запустил без ошибок, и бегает шустро. Уже на него я поставил Fedora Core 6(более свежей версии, к сожалению, не нашлось). Стоит отметить, что сначала я приобрёл Mandriva Linux Powerpack 2008 64 bit, однако не учёл одну деталь - Windows XP у меня 32-битная. Поэтому от мандривы пришлось отказаться.

Затем, настроил сеть, поставил PHP, MySQL, некоторые расширения, которые использую в своём проекте, а также SVN и графический клиент под него. Помогла мне в этом эта статья, хоть и написана она для 7 версии, на 6 порядок действий был аналогичен. Затем я восстановил рабочую копию своего проекта на VM и (внимание!) назначил права на файлы - в линуксе апач обязательно требует аттрибута x(eXecutable, исполняемый) для скриптов, пользователям Windows будет немного непривычно.

После этого настал черёд тестов. В среднем, время выполнения уменьшилось с 75(для форума)/100(для сайта) миллисекунд до 29(форум)/22(сайт) миллисекунд. И это с использованием памяти в 70 мегабайт вместо 20(Apache)+96(MySQL)+64(Memcached) = 180 мегабайт на винде. То есть памяти занимает меньше, а работает в 3 раза быстрее даже на виртуальной машине. Загрузка процессора 0%(если выйти из Gnome), загрузка памяти, как я уже сказал, 70 Мб.

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

Комментарии [2] | опубликовано: 2008-06-29 21:04

Дебаг в PHP

Debug(de_bug) означает избавление от багов, то есть ошибок. В данной заметке я постараюсь изложить свой опыт ловли ошибок. Основные виды ошибок, с которыми придётся столкнуться: – Синтаксические – незакрытая скобка, пропущенная запятая. Код с такими ошибками просто не запустится, поэтому их обнаружение не составляет особого труда, да и PHP сам подсказывает где именно закралась ошибка. – Логические ошибки – неправильно написанное имя переменной, неправильное условие, вызов неправильной функции… Самый обширный вид и самый трудноулавливаемый, так как зачастую возникают только при одном типе структуры входных данных. На их исправлении и остановимся подробнее.

Для начала следует уяснить работу исполнителя кода. Код всегда исполняется сверху вниз. Первая строка будет исполнена раньше второй. Сейчас мы говорим строго о PHP, который не поддерживает многопоточность. Именно поэтому следует начинать поиски ошибки с первой строчки первого вызванного скрипта. Исполнитель также может “уходить” с какой-то строчки на другую или даже в другой файл, если вызвать функцию подключения или просто какую-либо функцию – исполнитель пойдёт выполнять код той функции. Поэтому, следует разбирать – куда же пошёл исполнитель, возможно в каком-то подключённом файле данные изменяются не так как хотелось бы. Чтобы отслеживать входные данные на протяжении всего исполнения скрипта, можно использовать функции var_dump и print_r, которые выводят на экран содержимое данных. Первая выводит ещё и тип, я рекомендую использовать её, т.к. иногда неверный тип имеет самое большое значение в возникновении ошибки.

Если мы дошли до строчки после которой данные отличаются от ожидаемых, следует выяснить почему же так произошло. Очень часто встречается неправильный вызов функции, изменяющей данные. Иногда функции могут принимать, помимо данных, ключи, указывающие как эти данные нужно обработать. Например, функция htmlspecialchars принимает 2 ключа – как обрабатывать кавычки и кодировку. Иногда, в новых версиях значения этих ключей могут принимать другой смысл и скрипт, написаный под одну версию, может некорректно работать в более новой. Также, иногда меняется само поведение функции. Обычно это всё изложено в мануале по функции. Если мы видим, что поведение функции ожидаемо, значит, вероятно, данные для функции передаются в неправильном формате. Например, функция ожидает целое число, а мы передаём ей строку и она пытается разделить строку на число. Зачастую PHP сам преобразовывает типы, но преобразование не всегда предсказуемо, поэтому в функцию данные лучше передавать в требуемом типе.

Самая ранняя стадия получения неверных данных – ввод пользователем неверного текста. Поэтому следует проверить эти данные в первую очередь. Достаточно просто поставить код вроде var_dump($_POST); в какое-либо место скрипта(естественно, вставить нужно синтаксически верно, а не в абы какое место) и на экран будет выведено содержимое массива данных POST в данном месте скрипта.

Для дебаггинга на стороне клиента очень хорошо подходит Firefox с установленным расширением FireBug. К слову, для этого расширения есть подрасширение – FirePHP, позволяющее дампить переменные не засоряя дизайн сайта(данные передаются в заголовках страницы).

В процессе поиска ошибки следует тщательно следить за изменением всех данных – от локальных переменных до глобальных массивов. Иногда причиной ошибки оказывается другая ошибка – незапланированное изменение какой-нибудь глобальной переменной.

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

Таким образом, заканчивая, можно обобщить мысли: ошибки бывают разные, бороться с ними тоже нужно по-разному, имея в арсенале разные инструменты, но в любом поиске главный – один: голова. Ошибки стоит искать от начала и до места выхода – ошибка не возникает в коде, который не исполняется. Также не стоит избегать мониторинга глобальных данных. А если ошибка всё же произошла – лучше показать пользователю какую-нибудь заранее заготовленную страницу, чем поехавшую куда-то мазню.

Комментарии | опубликовано: 2008-03-25 16:17

Пара слов о рыбалке

Нет, не о той рыбалке, что на озере, рано утром, под пиво\водку и ухой вечером, а о сборе "рыбы", то есть текстов, нужных лишь для того, чтобы заполнить ими что-то. Дизайнеры, верстальщики используют рыбу для заполнения каких-то блоков информации, когда необходимый контент от заказчика ещё не пришёл. Программисты используют рыбу для проверки БД, скриптов и программ эмулируя действия пользователя, якобы он передаёт какие-то тексты программе. В общем, удел рыбных текстов - тестирование чего-либо, имеющего дело с текстовой информацией.
Создать рыбу можно разными способами:
  • Взять любое художественное произведение и выдрать оттуда главы, которые и будут текстами рыбы
  • Взять любой достаточно большой текст и сгенерировать множество текстов, используя цепи Маркова
  • Взять где-то базу уже нагенерированых текстов
Эти способы пришли мне в голову, особо эту тему я нигде не встречал, поэтому руководствуюсь лишь своим опытом. Вначале для тестирования скриптов я использовал лишь простой генератор записей "добавить строку тест тест тест", однако это не отражает реальных ситуаций - такие записи без проблем кешируются и вообще не очень пригодны для тестирования в условиях, приближённых к боевым.
После этого, используя готовый класс для генерации текстов используя цепи Маркова, я нагенерировал около 1000 текстов, однако, толи класс содержал ошибку(которую мне не очень хотелось искать, а беглый осмотр кода не дал результата), толи звёзды не так встали, но из 900-кб текста Сильмариллиона он выдрал только 3 слова и все тексты содержали только 3 различных слова. Затем я этот же текст разобрал на главы, коих насчиталось около 20. Затраты явно не оправдались. Поэтому я начал искать другой способ генерации рыбы, и тут мне на глаза попался сервис Яндекс.Рефераты. Он создаёт совершенно несвязный текст по заданой тематике, но для тестирования - само то. Далее был написан простенький парсер, который берёт записи по случайным темам. Его код привожу ниже:
<?php

function process_urls($urls)
{
  $errno = 0;
  $errstr = '';
  $texts = array();
  $ids = array();
  $eofs = array();
  $counter = 0;
  while (in_array(false, $ids) || (count($urls) != 0 && count($ids) == 0))
  {
    foreach ($urls as $id => $href)
    {
      if (!isset($ids[$id]) || $ids[$id] === false)
      {
        if ($counter != 0 && ceil($counter / 100) == $counter / 100)
          sleep(1);
        $counter ++;
        $href = parse_url($href);
        $ids[$id] = fsockopen('213.180.204.20', 80, $errno, $errstr, 5);
        if ($ids[$id])
        {
          $out = "GET ".$href['path']."?".$href['query']." HTTP/1.1\r\n";
          $out .= "Host: ".$href['host']."\r\n";
          $out .= "Connection: Close\r\n\r\n";
          fwrite($ids[$id], $out);
          $eofs[$id] = false;
          $texts[$id] = '';
        }
      }
    }
  }
  while (in_array(false, $eofs))
  {
    foreach ($eofs as $id => $eof)
    {
      if ($eof == false)
      {
        $texts[$id] .= fread($ids[$id], 4096);
        $eofs[$id] = feof($ids[$id]);
      }
    }
  }
  foreach ($ids as $id => $id_val)
    fclose($ids[$id]);

  foreach ($texts as $id => $href)
  {
    $text = $texts[$id];
    $text = str_replace(array("\n", "\r", '', $text);
    preg_match(
      '#<h1 style="color\:black\; margin\-left\:0\;">Тема\: \«([^»]+)»</h1>((<p>[^<]+>/p<+)</div></td>#Sim',
      $text, $matches);
    preg_match_all('#<p>([^<]+)</p>#Sim', $matches[2], $matches2);
    mysql_query(
      'INSERT DELAYED INTO data (title, textdata) VALUES ("'.mysql_escape_string($matches[1]).
      '", "'.mysql_escape_string(implode("\r\n", $matches2[1])).
      '"');
  }
}

set_time_limit(3600);

mysql_connect('localhost', 'root', 'root');
mysql_select_db('data');
mysql_query('CREATE TABLE IF NOT EXISTS `data` (
`title` VARCHAR( 255 ) NOT NULL ,
`textdata` TEXT NOT NULL
);');
mysql_query('TRUNCATE TABLE `data`');

$themes = array('astronomy', 'geology', 'gyroscope', 'literature', 'marketing', 'mathematics', 'music', 'polit',
'agrobiologia', 'law', 'psychology', 'geography', 'physics', 'philosophy', 'chemistry', 'estetica');
$urls = array();

for ($i = 0; $i <= 50000; $i++)
{
  $themes_copy = $themes;
  $use_themes = array();
  do
  {
    $rand_index = array_rand($themes_copy);
    $use_themes[] = $themes_copy[$rand_index];
    unset($themes_copy[$rand_index]);
  } while (count($themes_copy) && rand(0, 5));
  $urls[] = 'http://referats.yandex.ru/all.xml?mix='.implode('%2c', $use_themes).'&'.implode('=on&', $use_themes).'=on';
}

while (count($urls))
{
  process_urls(array_splice($urls, -10));
}
Собственно ради него и затевалось написание данной заметки. Достаточно шустро обрабатывает страницы и помещает тексты, пригодные для занесения, например, в раздел новостей на сайте, в БД. Использовать его нужно осторожно, естественно только для тестирования.
Мне интересно увидеть комментарии по поводу скрипта и вообще идеи создания рыбы, ведь действительно, идею почти никто не освещает.

Комментарии [4] | опубликовано: 2008-03-01 18:34