me

slonik_v_domene


Убей в себе государство


Верификация email регекспами.
me
slonik_v_domene
https://data.iana.org/TLD/tlds-alpha-by-domain.txt
По ссылке - список актуальных TLD.

Мы видим, что:
- эпоха .com, .net, .org, .edu, .mil, малоизвестного .int и двухбуквенных геодоменов давно канула в Лету

- tld растут как грибы на навозной куче после дождя; регулярно появляются новые

- практически кто угодно может сделать свой tld с блекджеком и whois-серверами. Так, есть не только .YANDEX, .GOOGLE и .YAHOO, но и .GOODYEAR, .VIRGIN и даже .VODKA

- кроме того, есть куча непроизносимых tld типа .vermögensberatung или .சிங்கப்பூர்.

Обращаю на эти факты самое пристальное внимание всех любителей писать регекспы для верификации email: всё это плохо, очень плохо или вовсе никак не ложится в привычную схему "нагуглил и прикрутил раз и навсегда регексп". Поэтому правильный подход - не писать регекспы для верификации email.

На этом тему предлагаю закрыть.

Невыносимо лёгкая поступь прогресса
me
slonik_v_domene
Лет 15 назад вместо этого был бы один шаблон на HTML::Template/Smarty, один обработчик на mod_perl/PHP, и это более чем сносно работало на Pentium 2, в на Pentium III-800 просто рвало всё вклочья. На поддержке кода мог бы работать джуниор.
Теперь же создание блога - 6 статей. Вот уж воистину - торжество бессмысленности. Технология ради технологии и только ради технологии. И с ценником программиста далеко за 150 000.

Цикл уроков "Создание блога на Symfony 2.8 lts"
https://habrahabr.ru/post/301760
https://habrahabr.ru/post/302032
https://habrahabr.ru/post/302438
https://habrahabr.ru/post/302602
https://habrahabr.ru/post/303114
https://habrahabr.ru/post/303578

libev, complete primer
me
slonik_v_domene
Я просто оставлю это здесь.
Практически полный пример работы с libev. Из широко используемого разве что таймаутов не хватает, но это а) не интересно и б) элементарно дописывается.

Работать с сетью в N потоков, и, если надо - считать медленные вещи в M потоков. Вроде, даже С не совсем еще забыл.

cc ev-mt.c -pthread -lev -Wall -pedantic -o ev-mt

http://pastebin.com/NErPr3Cy

Асинхронное программирование, ко-рутины и все-все-все
me
slonik_v_domene
Всем известно, что написать асинхронное сетевое приложение, да ещё с поддержкой TLS/SSL - адский труд. По пути придётся преодолеть callback hell, сделать разбор состояний SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE сокета SSL и соотнести их с текущим состоянием асинхронного обработчика, не запутаться в перключениях socket -> TLS/SSL socket и т.п. Всё это очень сложно.

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

Обычно проблема решается в несколько шагов:
1. Код пишется без поддержки SSL/TLS, а перед сервером устанавливается прокси-сервер, на который терминируется SSL/TLS со стороны клиента (хороший пример - https://github.com/bumptech/stud для чего угодно, или всем известный nginx для HTTP/POP3/IMAP4).

2. Берётся готовый асинхронный фреймворк и с помощью него пишется собственный код.

На словах всё прекрасно, однако на самом деле решение - так себе.
Во-первых, появляется лишняя сущность в виде прокси-сервера, который требует ресурсов. Снаружи трафик шифрованный, но внутри кластера - нет, а значит, есть возможность перехвата данных. Особенно актуально это при размещении в облачных сервисах.

Во-вторых, это очень плохо отлаживается, так как основная причина - callback hell асинхронной машины всё равно остаётся.

Можно ли упростить программирование и отладку? Есть мнение, что не только можно, но и нужно.

Решение следующее: сделать по возможности одинаковое API для работы как в асинхронном режиме, так и в линейном. Под линейным подразумевается нечто вроде:
struct pollfd fds;
fds.events = POLLIN;
poll(&fds, 1, timeout);
recv(fds.fd, buf, len);

fds.events = POLLOUT;
poll(&fds, 1, timeout);
send(fds.fd, buf, len);

В примере показано использование устаревшего вызова poll, но так как семантика вызова у poll, epoll и kqueue одинаковые, то принципиальной разницы нет.

Асинхронное API при этом должно мимикрировать под линейное. Приведём фантазийный пример:
struct async_pollfd fds;
fds.events = POLLIN;
async_poll(async_context, &fds, 1, timeout);
recv(fds.fd, buf, len);

fds.events = POLLOUT;
async_poll(async_context, &fds, 1, timeout);
send(fds.fd, buf, len);

Заметим, что глубокой переработке подлежит только вызов ожидания сокета, но не процедуры чтения или записи в него. Это позволит одновременно ожидать готовности нескольких сокетов, а главное - упростит написание самого кода и позволит вызывать любые функции по готовности сокета. Так, не составит практически никакого труда заменить recv на SSL_read и send - на SSL_write.

И самое главное: отлаживать логику программы станет возможно в простейшей для понимания тестовой среде, где без сайд-эффектов работают такие средства как valgrind, gdb, gcov, gprof, strace и т.п.

Читатель работавший с асинхронными фреймворками сразу же задаст резонный вопрос:
- Как, используя асинхронное API, например, libev/libevent "вывернуть наизнанку" callback? Ведь из event loop мы попадаем в процедуру-callback, которая исполняется вне нашего кода, и выйти можно только обратно в event loop?

Вопрос действительно небанальный, однако для обсуждаемой проблемы есть решение: необходимо воспользоваться ко-рутинами.

Теперь соберём всё воедино и опишем алгоритм работы:
Изначально исполнение программы идёт в линейном блоке. После захода в функцию async_poll мы настраиваем требуемые события для одного или нескольких сокетов и производим переключение контекста внутрь event loop. Как только один или несколько сокетов будут готовы к чтению или записи, мы переключаем контекст обратно и выходим из async_poll.

Таким образом мы из асинхронного API делаем псевдосинхронное, незначительно отличающееся от линейного. Массовый параллелизм достигается тем, что async_poll может выполняться во многих ко-рутинах и их количество ограничено только размером оперативной памяти.

Все рассуждения описаны на уровне псевдокода. Как же это выглядит в реальности и насколько дороже относительно линейно исполняемого нам обойдётся код с переключением контекстов?

Ответ на первый вопрос доступен по ссылке:
http://pastebin.com/pBudcdg5

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

Результаты можно видеть в таблице:
 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
19765 stellar   20   0  426456   4760   2220 S  39.9  0.2   2:32.68 coro
19864 stellar   20   0  411224   4444   2004 R  37.9  0.2   2:31.21 linear


Мы видим, что разница составляет порядка 5%. Это - хороший результат и очень небольшая цена за радикальное упрощение разработки и отладки программы.

Обсуждение в ФБ: https://www.facebook.com/sloneus/posts/636050909879742

FreeBSD 10.3/amd64
me
slonik_v_domene
Нечастые новости из мира FreeBSD:

pkg install mysql57-server
echo 'mysql_enable="YES"' >> /etc/rc.conf
/usr/local/etc/rc.d/mysql-server start
/usr/local/etc/rc.d/mysql-server: WARNING: failed precmd routine for mysql

#FreeBSD как всегда SOSNOOLEY

Так скажите мйентейнеру, что первый тест под названием "поставь СУБД по дефолту" не проходит, потому что это тело не асилило написать шелл-скрипт без ошибок, ёпстыд. И вместо этого насрало себе в руки. А так-то суперсистема рулит, конечно.

Для тех, кто не врубается в причину сарказма: FreeBSD 10.3 доступна с 28.03.16. Сейчас - 20.05.2016 и при этом суперпопулярный сервер MySQL не работает "из коробки". Это значит, что система, как таковая сдохла. Увы и ах.

CAS 3.8.0 @ Github
me
slonik_v_domene
https://github.com/CommunicoPublic/cas

Если кто хочет и может поправить spec-file, велкам.
https://github.com/CommunicoPublic/cas/blob/master/cas.spec

CAS 3.8.0
me
slonik_v_domene
Давно я об этом не писал.
Вышел CAS 3.8.0; добавлен FastCGI сервер, Apache 2.X теперь, как и Apache 1.3 - deprecated. К сожалению, отличный в прошлом проект HTTP-сервер Apache сам себя похоронил под тяжестью лишней функциональности и массы глупых проверок, совершенно не нужных для сервера приложений.

http://cas.havoc.ru/download/cas-3.8.0.tar.gz

Because fuck off
me
slonik_v_domene
DIGIT_CHARS      = (48..57)+;
TAG_CHARS        = (33 | 35..36 | 38..39 | 44..91 | 93..122 | 124..126)+;
ATOM_CHARS       = (33 | 35..36 | 38..39 | 42 | 44..61 | 63..90 | 92 | 94..122 | 124..126)+;
SP               = ' ';
CR               = '\r';
LF               = '\n';
CRLF             = (CR ? LF);

BRACKET          = ('(' | ')' | '[' | ']' | '<' | '>') @BRACKETS;
WSP              = (SP | BRACKET) +;

TAG              = TAG_CHARS >TAG_START @PUSH_TAG_DATA %TAG_END;

ATOM             = (ATOM_CHARS+) >ATOM_START @PUSH_DATA %ATOM_END;

QUOTED_CHAR      = 1..9 | 11..12 | 14..33 | 35..91 | 93..127;
DQUOTE           = 92;
QUOTED_SPECIALS  = 34 | 92;
STRING_CHARS     = QUOTED_CHAR | (DQUOTE QUOTED_SPECIALS);
STRING           = '"' >STRING_START STRING_CHARS** @STRING_CHAR '"' %STRING_END;

LITERAL          = '{' DIGIT_CHARS >LITERAL_START @LITERAL_DATA '+'? @LITERAL_PLUS_END '}' CRLF @LITERAL_END;

TERM             = ATOM | STRING | LITERAL;
TERMS            = (TERM (WSP TERM)*);

CMD              = (65..90 | 97..122)+;
COMMAND          = (("UID"i %CMD_UID SP)? CMD);

COMMANDS         = TAG WSP+ COMMAND ( CRLF | (WSP+ TERMS WSP* CRLF) ) @CRLF_END;
main            := COMMANDS $!SYNTAX_ERROR;

ПО мотивам обсуждения в ФБ.
me
slonik_v_domene
Теперь я понимаю, откуда берутся пионеры.

Откуда берутся пионеры?

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

Еще раз и медленно.

Студентов.
Отличников.
Третьего курса.
Московского физико-технического института.

Что я там увидел:
- лабы по Assembler для MSDOS/6.22
- код на С и С++

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

Люди пишут код который лишь бы работал; там, где можно использовать зависящий O(1) по скорости от объёма данных алгоритм, можно обнаружить O(n^2). В частности, при программировании двоичных деревьев студенты не в курсе про вырожденные случаи несбалансированных деревьев и заранее полагают скорость поиска логарифмической (а она там линейная, лол). В случае с assembler люди ничего не слышали о конвейере, привет, 8086, и при этом они же метят на работу в Intel!

Далее.
Народ ничего не знает об STL. Это не нужно, так как закат Солнца вручную - модно и молодёжно.

Преподаватели проходят под никами, как вам такой: Alcoholic. Я так понимаю, это сокращение Коголик Александр, как, вы не знаете, что это ведущий специалист-алгоритмост круче Дейкстры?

Виноваты ли в этом студенты? Полагаю, что если и виноваты, то не сильно - нельзя учиться новому у старпёров, застрявших в MSDOS 2.0, нельзя всерьёз воспринимать в качестве преподавателей алкашей, нельзя писать качественный код, если проверяют только результаты, не оценивая алгоритм и его реализацию.

А вот то, что даже в #мфти полностью просрана школа - очевидно, и аукнется это не сейчас, и даже не через 3-5 лет, когда этот студенческий сброд пойдёт на работу, а через 15-20 лет, когда массово начнут выходить на пенсию те, кто еще успел отучиться в СССР. Вот тогда - да, наступит веселье.

Обсуждение в ФБ

О перезапусках
me
slonik_v_domene
Как «Яндекс» провалился с «Кинопоиском»

>Следовательно, на момент запуска нового «Кинопоиска» пиар-департамент «Яндекса» уже должен был иметь план действий на случай, если все пойдет не так.

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

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

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

>Во-вторых, не очень понятно, почему «Яндекс» не обнаружил все эти проблемы на этапе бета-теста?

Здесь нет ничего сложного. Недостаточно взять какую-то абстрактную аудиторию и провести тест. Если человек не пользовался сервисом, у него нет стереотипа восприятия, и ему всё равно, новая версия или старая. Можно смело утверждать, что есть и те, кому на этапе тестов меньше нравился старый Кинопоиск, просто потому, что его увидели после нового)) Аудитория для тестов должна быть репрезентативной. Жаль, что в Яндексе забыли про собственную же майку "Я - не ваша целевая аудитория".


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

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

Теперь выводы:
1) Если вы перезапускаете проект, особенно - с длинной историей, будьте готовы к недовольству пользователей в любом случае.
2) Минимизация недовольства - отдельный, технологически сложный, проект. Только подготовкой службы PR здесь не отделаться, необходима разработка механизмов миграции аудитории по частям, причем - в обе стороны, и налаживание анализа пользовательской активности.
3) "Я - не ваша целевая аудитория". A/B тестирование работает только тогда, когда аудитории A и B имеют одни и те же статистические параметры. Если вы в "A" поместили хипстеров-либертарианцев, а в "B" - любителей традиционных ценностей, то у вас не A/B, а две разных аудитории.

Ну и последнее.
Идея купить сервис и полностью, с нуля, его переделать - довольно странная, если не сказать более грубо. Что в таком случае покупается? Пользователи и доменное имя? Неужели это может стоить таких денег? Окей, допустим, это так. Но вот вы перезапускаете сервис, аудитория встречает перезапсук с негодованием и голосует с проекта ногами. Поздравляю, ваши деньги ушли вместе с пользователями, а еще вам прилетело черной сажи в карму. Если есть желание сделать проект с нуля - делайте, тем более, что вариантов продвижения при наличии своей рекламной сети - масса. Взлетит проект - вы сами отожмете посетителей у конкурента, и ничего не придется покупать.

https://www.facebook.com/sloneus/posts/543121732505994

?

Log in

No account? Create an account