PHP

Начато 21 апреля 2012, 11:00 под Ride - Sunshine / Nowhere to Run
Опубликовано 7 августа 2012, 22:52 под Hadouken! - Mecha Love (Album Version)

Весенние тёрки за и против PHP в этом году не утихают уже больше месяца. Начавшись в нашем уютном твиттере, они, при активной поддержке людей, от программирования не только бесконечно далёких, но и, последнее время ежедневно, как от чумы, презрительно открещивающихся, путём коллективного бессознательного вылились в серию постов на хабрахабре. Меня с этим языком связывают очень давние, уходящие корнями чуть ли не в детство, отношения, разорвать которые вряд ли получится в ближайшем обозримом будущем, по сути, он был моим первым и довольно долгое время оставался единственным (эксперименты уровня Hello World считать не стоит). Я сел за PHP в девятом классе, не имея почти никакого понятия о том, что такое программный код и как он выполняется, и всерьёз задумался о смене, хотя бы, позы, где-то под конец первого курса — почти четыре года, которые, определённо, можно было провести с большей пользой. Впрочем, за ними следуют ещё три в этом плане лишь немногим лучшие. Я, по мере возможностей, как-то пытаюсь выкарабкаться из этого болота, не только PHP'шного, но и императивного в целом, и в этом посте хотел бы рассказать о том, с какими препятствиями встречаюсь на своём нелёгком пути.

Семь лет или две с половиной тысячи дней, каждый из которых начинается с <?php, несомненно оставят отпечаток на любом программисте, а молодого и неокрепшего и вовсе могут сделать инвалидом. Да даже на моторном уровне! Возьмём недавний пример: потребовалось решить головоломку с собеседования про монеты в тёмной комнате. В такой ситуации очевидно, что в отместку за требование, на наш ограниченный взгляд, невозможного, нужно проявить хитрость и найти изъян в требовании: никто же не сказал, что монеты нельзя переворачивать (я честно не знаю, читал ли про эту задачу раньше или опять помог фенотропил, обычно к решению подобного даже близко не подбираюсь), но как? Поскольку думать лень, руки послушно открывают редактор и по-быстрому уже почти неосознанно набирают:

<?php
{
    for ($p = 1; $p <= 11; $p++)
    {
        for ($n = 1; $n <= 12; $n++)
        {
            $ok = true;
            for ($e=0;$e<10000;$e++)
            {
                $a = array_merge(array(1,1,1,1),array(0,0,0,0,0,0,0,0));
                shuffle($a);
            
                for ($i = 0; $i < $n; $i++)
                {
                    $a[$i] = $a[$i] ? 0 : 1;
                }

                if (count(array_filter(array_slice($a, 0, $p))) == count(array_filter(array_slice($a, $p, 12))))
                {
                    
                }else $ok = false;
            }
            if ($ok)
            {
                var_dump($p);
                var_dump($n);
            }
        }
    }
}

Но чёрт возьми, почему на PHP? Я же ненавижу его больше жизни и стараюсь избегать везде, где это возможно, почему подсознание до сих пор выбирает его для подобных задач? Потому что пальцы привыкли, потому что мозг атрофировался, потому что написать то же самое на горячо любимом Python:

from random import shuffle
for p in range(1, 11 + 1):
    for n in range(1, 12 + 1):
        ok = True
        for e in range(1, 10000):
            a = [1] * 4 + [0] * 8
            shuffle(a)

            for i in range(0, n):
                a[i] = not a[i]

            if len(list(filter(None, a[0:p]))) == len(list(filter(None, a[p:]))):
                pass
            else:
                ok = False
        if ok:
            print(p)
            print(n)

даже просто эмоционально сложнее. Понятно, что между вышеприведёнными кодами разницы нет абсолютно никакой, они оба ужасны, и говорить о том, что PHP тянет на дно потому что я по-привычке пишу плохой код на нём, хотя мог бы писать хороший на чём-то другом было бы неправильно. Дело, повторяюсь, в другом: я привык к PHP душой и телом, и даже программируя на других языках, продолжаю отрисовывать этот «фрактал плохого дизайна». Нет, безусловно, по меткому выражению Sergey89 без PHP мы бы сейчас бухали пиво в подъезде или уже сидели в колонии, но, как я ни старался, ничего хорошего, что дал бы мне PHP как программисту вспомнить не смог. Зато, повторяюсь, дал много плохого.

Первое, и чуть ли не самое главное — это привычка программировать без отладчика. В PHP он как бы есть, называется xdebug, и я честно пытался пользоваться им несколько раз, но всё как-то не удавалось. По сей день основным инструментом отладки у меня является var_dump($x);exit; (иногда, прямо на продакшене), F5 в браузере, Ctrl+U в браузере (Chromium при этом начинает открывать страницу заново), и в результате в тех языках, где отладчик есть, я всё время про него забываю, украшая программу различными printf("%d does kotomshuk\n", rank). PHP не ориентирован на программиста, который, когда происходит ошибка, хочет её понять и устранить, для чего ему необходимо посмотреть как работала программа по шагам; скорее (и авторы этого не скрывают), его целевая аудитория скажет ой, а че-то оно неработает, в проге касяк, давай попробуем не i, а i + 1. Именно поэтому когда происходит какая-нибудь исключительная ситуация (например, выход за пределы массива), PHP вместо аварийного завершения работы и вывода stack trace, кидает в браузер даже не предупреждение, а уведомление, и спокойно работает дальше; надо ли говорить о том, что поведение программы, в которой произошло подобное, в половине случаев похоже на поведение слона в посудной лавке с соответствующими последствиями (для сайта-визитки, впрочем, не особенно страшными — всего-то нужно будет ещё раз взять с нашей почты текст в ворде и поставить на сайт). В современных PHP-фреймворках сделана попытка исправить эту ситуацию, но обратите внимание до чего жалко она выглядит:

PHP + Symfony 2
Python + werkzeug

Ошибка в PHP — это просто одна строка. Отделить суть ошибки от места, где она возникла, не представляется возможным, отсюда поэтому давайте просто выведем всё аршинным шрифтом, и плевать, что страница разъедется. Дальше идёт какой-то малоинформативный трейс на десять экранов, понять что-то по-которому вряд ли представляется возможным. Обратите внимание на Python справа: в любой из элементов стека можно войти и выполнять там произвольный код — с такими возможностями никакой отладчик не нужен! В PHP так не будет никогда. Кстати, вот что я наблюдаю при, например, опечатке в коде:

Fatal error: Cannot use object of type Loyal\LoyalBundle\Entity\OurCar as array in /home/themylogin/www/test7.openstart.ru/src/Loyal/LoyalBundle/Controller/LotController.php on line 249 Call Stack: 0.0015 338784 1. {main}() /home/themylogin/www/test7.openstart.ru/web/app_dev.php:0 0.0625 3680232 2. Symfony\Component\HttpKernel\Kernel->handle() /home/themylogin/www/test7.openstart.ru/web/app_dev.php:25 0.1247 4925548 3. Symfony\Bundle\FrameworkBundle\HttpKernel->handle() /home/themylogin/www/test7.openstart.ru/app/bootstrap.php.cache:547 0.1247 4926424 4. Symfony\Component\HttpKernel\HttpKernel->handle() /home/themylogin/www/test7.openstart.ru/app/cache/dev/classes.php:4852 0.1247 4926424 5. Symfony\Component\HttpKernel\HttpKernel->handleRaw() /home/themylogin/www/test7.openstart.ru/app/cache/dev/classes.php:3875 0.2977 7008428 6. call_user_func_array() /home/themylogin/www/test7.openstart.ru/app/cache/dev/classes.php:3905 0.2977 7008680 7. Loyal\LoyalBundle\Controller\LotController->trafficAction() /home/themylogin/www/test7.openstart.ru/app/cache/dev/classes.php:0

Да, именно так, в одну строчку: Fatal Error у нас не отловить и она простым текстом будет выведена в браузер, очень удобно! Обнаружение и устранение ошибок — одна из ключевых задач, возникающих при разработке ПО, и отсутствие в языке программирования инструментов для её решения — признак того, что перед нами не язык программирования, а, например, не самый красивый шаблонизатор с возможностью выполнения переданных методом HTTP GET SQL-запросов.

Другая ключевая задача — управление сложностью. Для этого программы обычно разбивают на модули, и тут нашему шаблонизатору опять не повезло: модульность в нём не поощряется абсолютно. Понятия модуля у нас нет, есть понятие файла, который можно (но необязательно!) считать и выполнить в текущем контексте. Прямо как в C! В результате, код оформляется как Господь программисту на душу положит, в случае программиста PHP — с 90% вероятностью как попало. Решая эту проблему с помощью __autoload, впадаем в другую крайность: теперь можно не знать какие чужие модули использует наш. В последних версиях языка эта проблема была завуалирована с помощью пространств имён: теперь каждый файл начинается с нескольких конструкций use, что выглядит как модульность, но, тем не менее, ей не является. Откройте любой исходник на PHP: сотня-другая вызовов непонятно откуда взявшихся и непонятно как названных функций с абсолютно хаотичным порядком параметров, щедро перемешанных со знаком доллара — и вот уже склонный к насилию психопат, который знает, где вы живёте готовится спустить ветер из головы «того урода, что это писал». Помните: программирование на PHP опасно для жизни!

Отсутствие легко выводимой связности между частями программы приводят к трудностям не только у человека, но и у IDE. Вот так, например, работает «Find Usages» в JetBrains PhpStorm:

JetBrains PhpStorm: Find Usages

Я попытался найти все вызовы Loyal\LoyalBundle\Entity\Consignee::updateFromRequests, и он нашёл только те, что происходят в наследнике-прокси; те, что происходят в контроллере были благополучно проигнорированы. И это одна из лучших IDE и один из лучших фреймворков! А я-то перед этим уже удалил на радостях пару «неиспользуемых» методов. Рефакторинг, кстати, работает с тем же результатом: переименовывается только определение, вызовы — нет. Наспех написанное под на лету формулируемое ТЗ, похоже, таким и останется, и как я дальше буду это поддерживать, если честно, не знаю.

Для PHP вообще бесполезны всякие IDE, отладчики, профайлеры; большинство программ на этом языке пишется в Notepad++ под Шindows XP и тестируется через какой-нибудь Денвер, ведь встроенный веб-сервер появился только в 5.4. Отсутствие нормальных инструментов для развёртывания приложений, потому что можно просто скопировать все файлы через Total Commander и поправить конфиг? Пожалуйста. Отсутствие понятия о фикстурах и вообще всякого разделения между тестовыми и рабочими данными, потому что можно просто понавставлять строк вида «тицкукйбць» в базу через phpMyAdmin? Дайте два. Невидимые ошибки, разрывающие значения HTML-атрибутов, прямо в браузере? Очень удобно! Всё просто создано для того, чтобы любой любознательный школьник мог скачать это дерьмище себе на компьютер, откинуться на спинку кресла во время распаковки 7z-файла в /etc/hosts и очнуться спустя семь с половиной лет, по-прежнему нищим, а теперь, впридачу, ещё и озлобленным и тупым. Первая доза была бесплатно. Ничего не напоминает?

Комментарии (12)
s_mordvinov
7 августа 2012, 23:46
S Q #1
Ну почему же нищим? Всё от желания зависит, как мне кажется, и от потребности косить от армии.
Ну почему же нищим? Всё от желания зависит, как мне кажется, и от потребности косить от армии.
anonymous
8 августа 2012, 09:04
S Q #2
Читал по диагонали.
на горячо любимом Python:
Ты любой почти любой определённый язык будешь горячо любить, пока не разберёшься в нём досконально. Вот это:
if len(list(filter(None, a[0:p]))) == len(list(filter(None, a[p:]))):
не требует приведения к list, filter сам по себе возвращает новый list. А ещё в питоне обрати внимание на GIL, на UnicodeDecodeError (ну в случае юникода надо просто понять, как им правильно пользоваться).
Для PHP вообще бесполезны всякие IDE
Использую emacs для всего. Зависимость есть, брат жив.
Читал по диагонали. <quote>на горячо любимом Python:</quote> Ты <s>любой</s> <s>почти любой</s> определённый язык будешь горячо любить, пока не разберёшься в нём досконально. Вот это: <source lang="python">if len(list(filter(None, a[0:p]))) == len(list(filter(None, a[p:]))):</source> не требует приведения к list, filter сам по себе возвращает новый list. А ещё в питоне обрати внимание на GIL, на UnicodeDecodeError (ну в случае юникода надо просто понять, как им правильно пользоваться). <quote>Для PHP вообще бесполезны всякие IDE</quote> Использую emacs для всего. Зависимость есть, брат жив.
themylogin
8 августа 2012, 11:51
S Q #3
filter сам по себе возвращает новый list
Да вообще-то нет
Python 3.2.3 (default, Apr 23 2012, 23:35:30) 
>>> filter(None, [0,1,0,2,3])
Про GIL знаю, юникодом пользоваться умею, ты меня вообще за кого принимаешь?
<quote>filter сам по себе возвращает новый list</quote> Да вообще-то нет <source>Python 3.2.3 (default, Apr 23 2012, 23:35:30) >>> filter(None, [0,1,0,2,3]) &lt;filter object at 0xb708584c&gt;</source>Про GIL знаю, юникодом пользоваться умею, ты меня вообще за кого принимаешь? <smile>:-\</smile>
anonymous
24 августа 2012, 06:05
S Q #4
Да, именно так, в одну строчку: Fatal Error у нас не отловить и она простым текстом будет выведена в браузер, очень удобно!
Почему же? Можно вполне. С записью в лог-файл и форматированием того самого трейса "в одну строку" в человечески вид.
register_shutdown_function('shutdownFunction');
function shutdownFunction()
{
    $error = error_get_last();
    $errorException = new ErrorException($error['type'], $error['message'], 0, $error['file'], $error['line']);

    $data = $errorException->getMessage() . '<br /><br />';
    $data .= '<b>Stack Trace:</b>' . str_replace('#', '<br />#', $errorException->getTraceAsString());

    $data = '['.date('d.m.Y H:i:s').'] ' . $data;
    file_put_contents(LOG . 'error.log.txt', $data . "\n", FILE_APPEND);

    if (SERVER_TYPE == SERVER_DEBUG) echo $data;
}
Откройте любой исходник на PHP: сотня-другая вызовов непонятно откуда взявшихся и непонятно как названных функций с абсолютно хаотичным порядком параметров, щедро перемешанных со знаком доллара
А это уже говнокод, который в нормальных девелоперских конторах просто недопустим. При чем тут похапэ то? При том, что он позволяет это делать? Да ради бога. В прямых руках, "опасность для жизни" сводится к нулю.

Насчет IDE. PhpStorm в моих проектах прекрасно находит и все использования функции, и прекрасно рефакторит все вхождения кода. Может у тебя какой-то очень странный phpStorm?
и очнуться спустя семь с половиной лет, по-прежнему нищим
Вот это совсем уже спорно. Выросшие из школьников PHP-разработчики, работающие с крупными проектами, получают не меньше питон-мастеров.
<quote>Да, именно так, в одну строчку: Fatal Error у нас не отловить и она простым текстом будет выведена в браузер, очень удобно!</quote>Почему же? Можно вполне. С записью в лог-файл и форматированием того самого трейса "в одну строку" в человечески вид. <source lang="php"> register_shutdown_function('shutdownFunction'); function shutdownFunction() { $error = error_get_last(); $errorException = new ErrorException($error['type'], $error['message'], 0, $error['file'], $error['line']); $data = $errorException->getMessage() . '<br /><br />'; $data .= '<b>Stack Trace:</b>' . str_replace('#', '<br />#', $errorException->getTraceAsString()); $data = '['.date('d.m.Y H:i:s').'] ' . $data; file_put_contents(LOG . 'error.log.txt', $data . "\n", FILE_APPEND); if (SERVER_TYPE == SERVER_DEBUG) echo $data; }</source> <quote>Откройте любой исходник на PHP: сотня-другая вызовов непонятно откуда взявшихся и непонятно как названных функций с абсолютно хаотичным порядком параметров, щедро перемешанных со знаком доллара</quote>А это уже говнокод, который в нормальных девелоперских конторах просто недопустим. При чем тут похапэ то? При том, что он позволяет это делать? Да ради бога. В прямых руках, "опасность для жизни" сводится к нулю. Насчет IDE. PhpStorm в моих проектах прекрасно находит и все использования функции, и прекрасно рефакторит все вхождения кода. Может у тебя какой-то очень странный phpStorm? :) <quote>и очнуться спустя семь с половиной лет, по-прежнему нищим</quote>Вот это совсем уже спорно. Выросшие из школьников PHP-разработчики, работающие с крупными проектами, получают не меньше питон-мастеров.
themylogin
24 августа 2012, 23:06
S Q #5
Почему же? Можно вполне.
Хорошая идея! Я почему-то даже не подумал.
А это уже говнокод, который в нормальных девелоперских конторах просто недопустим. При чем тут похапэ то?
При том, что именно там str_replace, но strrev. shuffle, но array_reverse. array_map(callback, input), но array_filter(input, callback). Да-да, array, самая охуительная структура данных, которая только может быть. Список и хэш, два в одном!
PhpStorm в моих проектах прекрасно находит и все использования функции, и прекрасно рефакторит все вхождения кода.
Давай я скину тестовый проект, а ты попробуешь?
(а то я очень сомневаюсь, что в языке, где, блядь, this - это отдельный токен, возможен рефакторинг)
Выросшие из школьников PHP-разработчики, работающие с крупными проектами, получают не меньше питон-мастеров.
Голословные утверждения. Где факты?
<quote>Почему же? Можно вполне.</quote> Хорошая идея! Я почему-то даже не подумал. <quote>А это уже говнокод, который в нормальных девелоперских конторах просто недопустим. При чем тут похапэ то?</quote> При том, что именно там <var>str_replace</var>, но <var>strrev</var>. <var>shuffle</var>, но <var>array_reverse</var>. <var>array_map(callback, input)</var>, но <var>array_filter(input, callback)</var>. Да-да, array, самая охуительная структура данных, которая только может быть. Список и хэш, два в одном! <quote>PhpStorm в моих проектах прекрасно находит и все использования функции, и прекрасно рефакторит все вхождения кода.</quote> Давай я скину тестовый проект, а ты попробуешь? (а то я очень сомневаюсь, что в языке, где, блядь, <var>this</var> - это отдельный токен, возможен рефакторинг) <quote> Выросшие из школьников PHP-разработчики, работающие с крупными проектами, получают не меньше питон-мастеров.</quote> Голословные утверждения. Где факты?
anonymous
25 августа 2012, 23:40
S Q #6
Голословные утверждения. Где факты?
В Киеве вакансии Senior PHP Engineer начинаются от трёх килобаксов. Разумеется, что в говняных конторах эта сумма будет в два-три раза меньше, но и с питоном точно та же ситуация.
Давай я скину тестовый проект, а ты попробуешь?
Кидай на hast4656 at gmail dot com.
Единственное "но": у меня все проекты почти полностью задокументированны phpdoc'ом. Возможно, как раз это и спасает.
Хорошая идея! Я почему-то даже не подумал.
Я немного ступил там, кстати. Нужно внутри колбэк-функции сначала проверять, если ошибка вообще. Иначе эта хрень будет исполняться каждый раз при завершении скрипта.
Да-да, array, самая охуительная структура данных, которая только может быть. Список и хэш, два в одном!
Зато какая удобная! Не нужно запоминать, какие функции работают с множествами, словарми, списками, массивами. Всё есть в array!
<quote>Голословные утверждения. Где факты?</quote> В Киеве вакансии Senior PHP Engineer начинаются от трёх килобаксов. Разумеется, что в говняных конторах эта сумма будет в два-три раза меньше, но и с питоном точно та же ситуация. <quote>Давай я скину тестовый проект, а ты попробуешь?</quote> Кидай на hast4656 at gmail dot com. Единственное "но": у меня все проекты почти полностью задокументированны phpdoc'ом. Возможно, как раз это и спасает. <quote>Хорошая идея! Я почему-то даже не подумал.</quote> Я немного ступил там, кстати. Нужно внутри колбэк-функции сначала проверять, если ошибка вообще. Иначе эта хрень будет исполняться каждый раз при завершении скрипта. <quote>Да-да, array, самая охуительная структура данных, которая только может быть. Список и хэш, два в одном!</quote> Зато какая удобная! Не нужно запоминать, какие функции работают с множествами, словарми, списками, массивами. Всё есть в array! :D
themylogin
26 августа 2012, 01:20
S Q #7
В Киеве вакансии Senior PHP Engineer начинаются от трёх килобаксов.
Сколько времени Senior PHP Engineer будет половиной этой зарплаты выплачивать ипотеку за двухкомнатную квартиру в пятнадцати минутах езды от центра Киева?
Кидай на hast4656 at gmail dot com.
Отправил. Для всеобщего обозрения проект здесь.
<quote>В Киеве вакансии Senior PHP Engineer начинаются от трёх килобаксов.</quote> Сколько времени Senior PHP Engineer будет половиной этой зарплаты выплачивать ипотеку за двухкомнатную квартиру в пятнадцати минутах езды от центра Киева? <quote>Кидай на hast4656 at gmail dot com.</quote> Отправил. Для всеобщего обозрения проект <a href="http://thelogin.ru/data/blog/uploads/php/test.tar.gz">здесь</a>.
anonymous
26 августа 2012, 01:46
S Q #8
Сколько времени Senior PHP Engineer будет половиной этой зарплаты выплачивать ипотеку за двухкомнатную квартиру в пятнадцати минутах езды от центра Киева?
В 15-ти минутах - примерно три года. Отдавая половину.

<quote>Сколько времени Senior PHP Engineer будет половиной этой зарплаты выплачивать ипотеку за двухкомнатную квартиру в пятнадцати минутах езды от центра Киева?</quote>В 15-ти минутах - примерно три года. Отдавая половину.
themylogin
26 августа 2012, 01:57
S Q #9
5400$ двухкомнатная квартира почти в центре?
(в Новосибирске за такие деньги - голые стены в отдалённом районе без инфраструктуры, и это ещё дешево отделался)
5400$ двухкомнатная квартира почти в центре? (в Новосибирске за такие деньги - голые стены в отдалённом районе без инфраструктуры, и это ещё дешево отделался)
anonymous
26 августа 2012, 17:24
S Q #10
Да, с симфони и правда ничерта не работает. Но это особенности реализации симфонии. В роадмапе 5-й версии, кстати, что-то подобное обещают для simphony и YII.
5400$ двухкомнатная квартира почти в центре?
Что-то я просчитался, лол. Ну смотри, однокомнатная квартира в 10-15 минутах от центра стоит 60 косарей. Двухкомнатная будет стоить примерно 100. Пять с половиной лет выходит.
Да, с симфони и правда ничерта не работает. Но это особенности реализации симфонии. В роадмапе 5-й версии, кстати, что-то подобное обещают для simphony и YII. <quote>5400$ двухкомнатная квартира почти в центре?</quote> Что-то я просчитался, лол. Ну смотри, однокомнатная квартира в 10-15 минутах от центра стоит 60 косарей. Двухкомнатная будет стоить примерно 100. Пять с половиной лет выходит.
themylogin
26 августа 2012, 17:29
S Q #11
особенности реализации симфонии
Вот-вот, я об этом и писал. Единого порядка нет, и каждый делает автолоадер кто во что горазд, а потом разработчики IDE вынуждены всё это поддерживать.
<quote>особенности реализации симфонии</quote> Вот-вот, я об этом и писал. Единого порядка нет, и каждый делает автолоадер кто во что горазд, а потом разработчики IDE вынуждены всё это поддерживать.
themylogin
4 сентября 2012, 19:27
S Q #12
"На сайте должно быть прайс-лист, о компании, схема проезда дубльгис и контакты, сколько будет стоить цена?"

В новых версиях Symfony 2 сообщение об ошибке выглядит поприличнее. Правда, всё равно ни хуя не понятно в чём проблема:

Вызываем PHP-отладчик (Ctrl+U), ну точно!
<abbr title="Doctrine\ORM\Query\QueryException">QueryException</abbr>: Invalid parameter format, ? given, but :<name> or ?<num> expected.
"На сайте должно быть прайс-лист, о компании, схема проезда дубльгис и контакты, сколько будет стоить цена?" В новых версиях Symfony 2 сообщение об ошибке выглядит поприличнее. Правда, всё равно ни хуя не понятно в чём проблема: <a href="http://i.thelogin.ru/_/134676159930.png"><img src="http://i.thelogin.ru/1280/134676159930.png" /></a> Вызываем PHP-отладчик (Ctrl+U), ну точно! <source lang="html"><abbr title="Doctrine\ORM\Query\QueryException">QueryException</abbr>: Invalid parameter format, ? given, but :<name> or ?<num> expected.</source>
Добавить комментарий
Войдите через  Доступные тэги: <b>, <i>, <s>, <u>, <a href="">, <img src="" /> (загрузить), <pre>, <quote>
Теги
1nsk C++ E-Business GNU/GPL-софт HTML/CSS ICQ IDE KDE last.fm Linux Linuxnsk Microsoft Motivator MySQL P2P Party PCI PHP Python Qt SATA SEO Sibnet thelogin.ru Timelapse USB VHDL Web 2.0 Webstream Windows Wireless А я говорил! Авто Админ Алкоголь Аниме Атмосфера Аудио Безобразие Бизнес Блоги Боты Бред Быт Велосипед Весна Вечер Взлом Видеозахват Винил Винтаж Вконтакте Вода Воспоминания Гетто Гламур Гопота Горский Графити Грузовики Дача Девушки Деньги Дизайн Домофон Драки Европа Еда Железо Затулинка Зима Игрушки Игры Идея Интересно Интернет Исследование История Казань Карикатуры Квартира Класс Концерты Коромшук Коты КПК Красиво Криминал Крыши Курение Лето Литература Лицей НГТУ Лохи Магнитофоны Маркса Мат Математика Машинный перевод Мегафон Менты Метро Мечты Мифы Мне стыдно Мобайл Можга Москва МТС Музыка Мультикассы Мультфильмы Мы помним Надписи Наука Недвижимость Непоняятно Новосибирск Ночь Обидно Обман Образование Омск Опечатки Орфография Осень Парк Пиратство Плохо Погода Поезда Политика Помойка Праздники Презрение Природа Провайдеры Программирование Протест Психология Путешествия Радиотехника Растения Реклама Религия Ремонт Рисунки Руины Рэп Салют Серверы Сервис Сериалы Скриншоты Смешно СМИ Снег Собаки Совет Софт Спам Спасём Россию Стоп-ляп Страх Стройка Студяга Танцы ТВ Трамваи Транс Транспорт Уважаю Ужас Умный дом Утро Филдрепорты Философия Форум ФПМИ Франция Хикки Хостинг Цитатник Школа 208 ЭГ Эксперимент Юго-Западный