Про Pussy Riot

В последнее время стало модно высказываться по поводу отношения к Pussy Riot, даже Сергей Брин высказался. Похоже, настaл и мой черёд.

По началу я наблюдал это как забавный цирк, так как интересы обеих сторон этого «конфликта» мне далеки. Ну сплясали какие-то срамные девки на алтаре в ХХС, ну возненавидели их за это представители РПЦ. Учитывая, что девки являются представителями либерально-лгбтшно-феминистично-трэш-ад-содом-дебильного движения, знаменитого своими прошлыми идиотскими акциями, а РПЦ и ХХС к православной вере отношения практически не имеют, а занимаются сугобо обрядовой стороной вопроса, взыманием бобла и отжимом земель, всё это виделось как противостояние жабы и гадюки. Но вот потом стали открываться новые видения этого события, и постепенно вырисовывалась более другая картина.

Начнём с того, что оппозиционное движение стало несколько пугать Путина. Разные националисты, национал-демократы, консерваторы, представители малого и среднего бизнеса стали находить общий язык между собой, договариваться, искать пути решения существующего политического кризиса, предлагать конкретные действия, да ещё и по-немногу пробираться на митинги. Власти это не особо-то и надо, например. Одно дело, когда толпа Честных, Справедливых, Живущих Не По Лжи людей сидит у памятника Абая и поёт песни Окуджавы, и совсем другое дело, когда топла злых и конкретных людей приходит с арматурой, топорами и ружьями в Кремль с целью немного поубивать. Окуджава, конечно, силён. Если бы у моего дома круглые сутки его пели, я бы на третий день вышел с поднятыми руками. Но во-первых, Честные люди поют его не у дома Путина, а во-вторых, топор с арматурой всё же сильнее.

Что же делать оккупационной власти, дабы избежать незавидной участи? Дык это, надо как-то прогнать конкретных людей из оппозиции, да и желательно из страны вообще. Нужен новый лидер «оппозиционного» движения, более благоприятный для приманиваная Творческих Креативных личностей, целью которых является сам процесс, а не результат: громкие, шумные, эффектные (видимо, они путают слова «эффектность» и «эффективность») события, привлекающие внимание, но не решающих ровным счётом ничего. Чтобы глядя на «оппозицию», обыватель каждый раз повторял: «Уж лучше Путин, чем ЭТИ». Но каждому Честному Справедливому человеку известно, что настоящий лидер оппозиции должен обязательно пострадать и посидеть в тюрьме по политическим мотивам. Причём суд должен быть как можно более абсурдным и показательным, дабы ни один Честный человек не смог пропустить его мимо себя. И инициировать суд желательно должен кто-то, олицетворяющий собой стабильность, традиции, консерватизм, в общем, полная противоположность желаемому результату. Опять же, ориентировка на обывателя, который между словами «православие» и «РПЦ» ставит знак равенства.

И тут внезапно появляется толпа девок, пляшущих в церкви, которых раньше подозрительно быстро отпускали из ментовки при совершении хулиганств, и они избегали наказания. Дальше вы всё сами знаете.

В течение тюремного срока длительностью полгода-год новый лидер оппозиции пишет письма, Честные Справедливые Блогеры делают Репост, выводят в Топ и негодуют, мол, вот выйдет наш незабвенный лидер, уж тут-то мы покажем им всем! Вот выходит лидер-страдалец, тут же делает громкое заявление и начинает Бороться. Гастроли с концертами по городам, в каждом городе представители РПЦ выражают свой протест, толпы Честных Справедливых людей бегут в кассы покупать билеты, все при деле, все счастливы.

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

И так, в результате с одной стороны получаем беззубую «оппозицию», создающую видимость политической борьбы, всю такую Честную и Справедливую, свободную от здравомыслящих людей.

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

Всё так и будет.

Только вот забывает Путин, или не хочет знать того факта, что США всегда кидали своих карманных диктаторов. Кидали не на бобло, а на жизнь. Предатели этого заслуживают.

Comments

Прогноз: каким не^Wбудет не^WWeb через 5 лет

Сейчас

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

Будет

Через 5 лет (примерно в 2017 году) не будет сайтиков в привычном понимании этого слова. Да и веба тоже не будет. Ни Web 3.0, ни 4.0, ничего не будет. Будут приложения, динамически загружающиеся на устройство пользователя и выполняющиеся в изолированном окружении, с возможностью взаимодействовать друг с другом по взаимному согласию. Окружением станет VM, выполняющая байткод или код, приравненный к нему. Приложение будет отвечать за всё взаимодействие с пользовательским устройством, за рендеринг, за обработку событий. С серверной частью оно обменивается любым образом: запросы-ответы HTTP (REST), постоянные соединения. Технология WebSockets отомрёт ещё до получения широкого распространения, так как это технология переходного периода. Нужды в ней в будущем не останется.

Не буду говорить, что всё рабочее окружение пользователя переместится в «облако», клауд компьютинг заборонено. Десктопные приложения останутся точно такими же, как сейчас, ну разве что в них появятся возможности быстро расшарить что-либо. Интернетные приложения будут интегрированы с десктопом, грубо говоря, тыкаешь иконку «AssMagazine» (фейсбук к тому времени помрёт и появятся новые социальные сети, так что не надо смеяться над стартапёрами, желающими создать новую социалочку, мотивируя это наличием фейсбука; пусть создают, потом тоже бобла на лохах поднимут), дык вот, тыкаешь на иконку, и окружение посылает запрос на сервер «AssMagazine», где проверяет наличие последней версии приложения, загружает его и запускает. Все рады, юзер доволен. Затем он нажимает мышкой на фоточку профиля одного из друзяшек, выбирает «Открыть в PhotoShop» (фотошоп не облачный, а натуральный, как сейчас), делает друзяшке dirty sanchez и тут же заливает к себе на стену, наблюдает за ростом числа одобряшек (лайки тоже вымрут вслед за фейсбуком, будут одобряшки). Как-то так.

Что надо

А надо уже сейчас делать следующие вещи:

  1. Большая контора (пусть будет Google, а не рукожопые «хиндженегры» из Microsoft) должна создать спецификацию и реализацию VM и дичайше сертифицировать других производителей на предмет соответствия спецификаций, дабы не было фрагментации. Не прошёл сертификацию — выполнять код заборонено, иначе в суд. Код VM должен одинаково выполняться на любой его реализации.
  2. Затем надо делать платформы для создания интернет-ресурсов. Грубо говоря, чтобы каждый Эдуард из Нижнеудинска мог в 3 щелчка мышкой создать свой интернет-ресурс, без писанины нативного кода. Ладно, пусть его ресурс располагается даже в «облаке», дабы Эдик не заморачивался с поднятием своего сервера. Таким образом хостеры типичных VDS/VPS для массового юзера заменятся на хостеров определённой платформы, где для юзера нет ни линуксов, ни фрипзд, ничего, только хранилище, отдающее его приложение и обеспечивающее его работу на стороне сервера.
  3. Собственно, будет неплохо, чтобы на это ориентировались уже сейчас, так как сам я это делать не хочу, но иметь такое хочу.

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

UPD:

  1. Erlang in the Browser
  2. Browserl
Comments (9)

Metalkia on Github

Metalkia is now on Github: metalkia_web

Pull requests are welcome!

Comments

Opscode: история успеха

В Opscode вычистили весь хипстерский хлам, типа рубей, единорогов и каучдб, и заменили это на Erlang+MySQL, после чего у них наступила благодать.

(Read more)

Comments (2)

Отладка в Erlang

Любое приложение на Erlang состоит из двух базовых структурных единиц: модулей и процессов. В модулях описывается код, а процессы выполняют код из разных модулей в разный момент времени. Было бы интересно в процессе работы приложения понаблюдать за тем, какой процесс вызывает какую функцию, и что она возвращает. Такая возможность, разумеется, в Erlang/OTP есть, и помимо этого, ею реально удобно пользоваться. Она работает очень просто и именно так, как ожидается. Трассировка встроена в виртуальную машину BEAM и использует язык Erlang для описания своего поведения, поэтому её можно с лёгкостью интегрировать в своё приложение в качестве подсистемы мониторинга и диагностики.

Трассировщик

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

Трассировщик запускаеся простой командой:

dbg:tracer().

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

А если недостаточно?

Этот параграф можно не читать.

Если стандартное поведение трассировщика нас не устраивает, то его можно с лёгкостью определить самому, используя функцию dbg:tracer/2. В этой функции первым аргументом описывается тип трассировщика: process или port.

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

В случае типа port, вторым аргументом должна идти функция, определённая с помощью dbg:trace_port/2. Использование порта позволяет снизить издержки на добавление трассировочных сообщений в очередь erlang-процесса, посылая их сразу напрямую в драйвер. Определены два трассировочных драйвера: ip и file, из названия которых сразу понятно, что они делают.

Драйвер ip открывает TCP/IP-порт, указанный вторым аргументом, и начинает его слушать. Как только на этот порт подцепляется трассировочный клиент с другой erlang-ноды, используя команду dbg:trace_client/2, он начинает получать сообщения и печатать их на консоль, как обычный dbg:tracer/0. Чтобы переопределить поведение клиента, используем dbg:trace_client/3.

Драйвер file работает похожим образом, но использует запись в файл, для последующего чтения с помощью dbg:trace_client/2.

События

Теперь определяемся, что хотим видеть, и задаём это с помощью команды:

dbg:p(Item, Flags).

Здесь Item задаёт необходимое нам множество процессов, действия которых надо отловить:

  • Переменная типа pid(): будем получать события от этого конкретного процесса
  • Атом all: получаем события от всех процессов в системе
  • Атом new: только от новых процессов, уже запущенные будут игнорироваться
  • Атом existing: только от уже запущенных процессов, новые будут игнорироваться (противоположность new)
  • Какой-то другой атом: будем получать события от процесса, зарегистрированного под этим атомом
  • Целое число: преобразуется в идентификатор процесса <0.Item.0>
  • Кортеж {X,Y,Z}: преобразуется в идентификатор процесса <X.Y.Z>
  • Строка "<X.Y.Z>": преобразуется в идентификатор процесса <X.Y.Z>

Значение Flags может быть атомом или списком следующих атомов:

  • s (send): отправляемые сообщения
  • r (receive): получаемые сообщения
  • m (messages): и то, и другое
  • c (call): вызываемые функции (это самый используемый флаг и подробнее о нём в параграфе про шаблоны функций)
  • p (procs): прочие события процесса
  • sos (set on spawn): флаги трассировки будут наследоваться всеми процессами, порождёнными множеством процессов, заданным Item
  • sol (set on link): флаги трассировки будут наследоваться всеми процессами, с которыми линкуется множество процессов, заданное Item
  • sofs (set on first spawn): то же самое, что и sos, но только для первого порождённого процесса
  • sofl (set on first link): то же самое, что и sol, но только для первого залинкованного процесса
  • all: устанавливает все вышеперечисленные флаги
  • clear: сбрасывает все вышеперечисленные флаги
  • timestamp: добавляет время события

Описание dbg:p/2

Шаблоны функций

Как уже было сказано, трассировка вызываемых функций используется наиболее часто из всех остальных (флаг c). Для операций с шаблонами трассируемых функций, используется следующий набор команд:

  • dbg:tp/2,3,4: добавляет трассировку только глобальных функций
  • dbg:tpl/2,3,4: добавляет трассировку локальных функций
  • dbg:ctp/0,1,2,3: удаляет трассировку, заданную dbg:tp/2,3,4 или dbg:tpl/2,3,4
  • dbg:ctpl/0,1,2,3: удаляет трассировку, заданную только dbg:tpl/2,3,4 (локальные функции)
  • dbg:ctpg/0,1,2,3: удаляет трассировку, заданную только dbg:tp/2,3,4 (глобальные функции)

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

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

Разберём пример:

dbg:tracer().
dbg:p(all, [c, timestamp]).
dbg:tp(random, uniform, cx).

Здесь используется функция dbg:tp/3, гре первый аргумент — имя модуля random, второй — имя функции uniform, аргумента арности здесь нет, поэтому будет браться любая из существующих. Последний аргумент — MatchSpec имеет значение cx. Это то, что нам обычно и нужно. Параметр представляет собой суперпозицию двух параметров: c и x. Параметр c показывает, какая функция вызывает трассируемую функцию, а параметр x показывает возвращаемое значение трассируемой функции или исключение, если оно происходит. Вот так будет выглядеть вызов функции random:uniform/1 после включенной трассировки:

random:uniform(14).
(<0.32.0>) call random:uniform(14) ({erl_eval,do_apply,6}) (Timestamp: {1335,366136,885591})
(<0.32.0>) returned from random:uniform/1 -> 7 (Timestamp: {1335,366136,885625})
7

И в случае исключения (передаём неверный аргумент — атом вместо целого числа):

random:uniform(asd).
(<0.32.0>) call random:uniform(asd) ({erl_eval,do_apply,6}) (Timestamp: {1335,366468,181974})
(<0.32.0>) exception_from {random,uniform,1} {error,function_clause} (Timestamp: {1335,366468,181997})
** exception error: no function clause matching random:uniform(asd) (random.erl, line 111)

Это простой пример. При трассировке в больших проектах, наглядность сообщений очень повышается, по ним можно проследить любой произвольный отрезок жизни системы, включая внутренние состояния процессов (помним, что состояния процессов передаются из одной функции в другую, в качестве аргумента, например, handle_cast(Message, State) в процессе gen_server). Если же хочется просто посмотреть состояние нужного процесса gen_server в произвольный момент времени, то для этого существует функция sys:get_status(Pid).

Oстановка трассировки

Остановить трассировку можно функцией dbg:stop_clear(). После этого действия процесс трассировки завершится, а все шаблоны функций очистятся.

Распределённая отладка

Не забываем, что Erlang/OTP имеет хорошие средства для построения кластеров. Отладка тоже не отстаёт. Для этого всего лишь надо добавить удалённые ноды с помощью вызова dbg:n(remotenode1@somehostname). Теперь трассировщик будет принимать сообщения от удалённых нод тоже. Удалить удалённую ноду из списка трассируемых можно вызовом dbg:cn(remotenode1@somehostname).

Заключение

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

Comments

Почему я больше не буду троллить Node.js

В среду ездил в 2gis на мероприятие #DevDay. Там проводился квартирник, посвящённый Node.js и меня пригласили в качестве тролля-эксперта, противника Node.js. Я раньше был замечен в нелестных отзывах о ноде, всяческих сравнениях её с Erlang (не в пользу ноды, разумеется), поэтому должен был троллить и унижать её на квартирнике. Сразу скажу, что после мероприятия у меня абсолютно пропало желание троллить ноду и в ближайшее время я этого делать не буду, делал я это только по незнанию, так как не совсем чётко представлял себе, что такое нода.

Перед квартирником был отличный доклад Сергея Коржнева о типах и наследованиях в JS. Я на него, к сожалению, опоздал на полчаса из-за пробок. Сергей рассказал, какая бида-пичяль в JS с типами и как с этим бороться. На веб-клиенте альтернативы жаваскрипту пока нет и с этим надо как-то жить.

Затем после перерыва начался сам квартирник, вели который Влад Семёнов (@Semenov) и Степан Столяров (@stevebest). Ребята сразу же рассказали столько страшных вещей про Node.js, что абсолютно перехотелось троллить. Оказалось, что приложение на ноде надо перезапускать каждые два дня, ибо оно течёт, и утечки очень сложно поймать. Говорили, что в Яндекс сделали шаблоны, способные работать на стороне клиента и сервера сначала на JS (сервер на Node.js), так как хотелось использовать один и тот же код, но потом серверную часть переписали на C, получив выигрыш в производительности всего 20%. Видать, стало тяжело поддерживать, и хотя бы на сервере решили упростить задачу. (Яндексоиды, если кто в теме, можете прояснить?)

Говорили про библиотеку socket.io, которая реализует WebSockets и позволяет прозрачно делать даунгрейд в браузерах вплоть до IE5.5, и в качестве примера сервиса, использующую эту библиотеку с Node.js, привели trello.com, где из socket.io удалили всю возможность даунгрейда и поддерживают только новые браузеры. Это расово верно, так как чем меньше сайтов будет поддерживать старое барахло, тем лучше для мировой революции.

Тут я понял, что люди, выбирающие Node.js в здравом уме и твёрдой памяти, не нуждаются в Erlang. Нет смысла сравнивать ноду и ерланг, у них разные непересекающиеся ниши. Сторонников ноды не страшат пилообразные графики CPU и памяти в munin. Ну, упал один инстанс ноды, ну увидели несколько пользователей ошибку на nginx, это ж не катастрофа. Нажмёт он F5 и запрос обработает другой инстанс ноды, а первый пока поднимется. Это не смертельно, это не критично. Зато прикольно, круто и модно. Starbucks одобряє. Когда я раньше троллил ноду, считал, что она наступает ерлангу на пятки. Увы, это не так. Пропасть между нодой и ерлангом просто огроменная.

Общеизвестно, что 95% софта может быть написано абсолютно на любом языке. Не всем нужны кластеры, не всем нужна отказоустойчивость, не всем нужна возможность держать миллион соединений, не у всех есть высокие нагрузки. Это нормально. Оставшиеся 5% в принципе могут быть написаны только на чём-то узкоспециализированном и не имеющем альтернатив: C, ASM, Verilog, Erlang, JS (client-side!). Выбирать технологию для 95% можно руководствуясь лишь личными предпочтениями или модой. Node.js для этого хорошо подходит.

UPD: @illbullet меня поправил. Про шаблонизатор на C и JS — это было в Mail.ru, подробнее тут. Не знаю, почему у меня про Яндекс отложилось.

Comments (9)

Отложенная инициализация процесса

Инициализация процесса gen_server происходит в коллбеке init/1. Этот коллбэк вызывается уже запущенным новым процессом с поведением gen_server после того, как внешний процесс захотел его запустить с помощью функции start_link/1. Пусть модуль с описанием этого нового процесса имеет имя zz_worker. Тогда функция, запускающая этот процесс будет выглядеть так:

start_link(Args) ->
    gen_server:start_link(zz_worker, Args, []).

Разберём функцию gen_server:start_link/3. Первый её аргумент — имя модуля, где находятся коллбэки gen_server, описывающие действия процесса в ответ на определённые сообщения. Второй аргумент Args — то, что передаётся в функцию init/1. Третий аргумент — системные параметры, мы их тут не рассматриваем, поэтому просто передаём пустой список.

Процесс, вызывающий zz_worker:start_link/1 получит ответ {ok, Pid :: pid()} только тогда, когда функция init/1 закончит свою работу, а до тех пор вызывающий процесс будет находиться в блокировке. Если инициализация процесса проходит быстро, то и вызывающий процесс быстро получит ответ и продолжит работу. Если для инициализации требуется совершить какое-то длительное действие, то вызывающий процесс получит ответ и продолжит своё выполнение не скоро. Очень часто нас такое поведение устраивает и ничего больше не надо делать. Часто, но не всегда. Иногда возникает необходимость быстро запускать много процессов, не дожидаясь завершения инициализации каждого. Для этого надо уменьшить время выполнения функции init/1, а всю тяжёлую инициализацию оставить на потом.

Рассмотрим функцию init/1:

init(Args) ->
    State = do_long_initialization(Args),
    {ok, State}.

Здесь некая функция do_long_initialization/1 выполняется очень долго, своим выполнением оттягивая момент получения идентификатора этого процесса внешним процессом. Подумаем, как её выполнение оставить на потом. Вспоминаем, что в Erlang у нас все процессы обмениваются сообщениями, и сообщение можно послать любому процессу, в том числе и самому себе. Если мы пошлём сообщение самому себе в функции init/1, то оно гарантированно появится в мейлбоксе самым первым, так как больше никто про этот процесс ещё не узнал и не может ничего ему послать.

init(Args) ->
    self() ! {init, Args},
    {ok, #state{}}.

init/1 возвращает кортеж {ok, State :: term()} если инициализация прошла успешно, причём значение State будет использоваться в дальнейшем в качестве состояния процесса. Сейчас мы просто вернём сконструированный рекорд #state{} со значениями полей по умолчанию. Всё, в init/1 процесс посылает сообщение самому себе, функция на этом завершается и внешний процесс получает идентификатор нового процесса, после чего выходит из состояния блокировки и может работать дальше.

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

handle_info({init, Args}, OldState) ->
    NewState = do_long_initialization(Args),
    {noreply, NewState}.

Здесь в OldState будет то самое старое состояние со значениями по умолчанию. Оно нам сейчас не нужно, просто игнорируем его. И уже в этом обработчике вызываем ту самую долгую функцию do_long_initialization/1, которая возвращает нам новое актуальное значение состояния процесса. Не забываем, что этот обработчик выполнится самым первым после завершения функции init/1, поэтому не паримся насчёт гонок, их не будет.

Вместо посылки сообщения с помощью ! можно так же использовать gen_server:cast(self(), {init, Args}), тогда обрабатывать сообщение надо в обработчике handle_cast/2.

Comments (1)

Несбывшиеся мечты

На заре программирования, в 80-х и 90-х годах люди верили, что если сделать код, имеющий многие уровни абстракций, то наступит счастье. Для добавления новой функциональности надо будет всего лишь унаследовать пару классов, переопределить три метода и всё само заработает. Кроме того, написанный один раз код можно будет использовать повторно. Именно тогда появились такие вещи, как C++, Java, SOAP, CORBA, ASN.1, где, казалось бы, заложено всё, что угодно, расширяй — не хочу.

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

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

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

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

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

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

Слабая связность vs. сильная. Сообщения vs. методы. Объектно ориентированное программирование vs. процессы.

P.S. И да, говорить, что вызов метода в C++/Java/ObjC, это тоже посылка сообщения — глупость. Посылка сообщений подразумевает их потенциальную асинхронность и наличие очереди сообщений. Если сообщения только синхронные и не складываются в очередь, то это не сообщения, а миф.

Comments

Python после Erlang

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

retfun() ->
  io:format("~p~n", [abc]),
  5+5.

вернёт 10. Ну и то, что абсолютно все функции либо возвращают что-то, либо кидают исключение, тоже кажется нормальным поведением.

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

И когда я пишу на питоне что-то вроде:

def retfun(self, arg):
    self.some_other_fun(arg)

а оно мне возвращает None вместо результата функции self.some_other_fun(arg), я очень негодую. Зачем делать функции, которые ничего не возвращают? Ведь если сделать так, что каждая функция должна что-то возвращать, тогда можно будет выкинуть ключевое слово return.

Comments (9)

Релиз CEAN 2.0

После долгих лет забвения вышел релиз CEAN 2.0. Теперь это не только репозиторий с пакетами, но ещё и фреймворк для разработки на Erlang/OTP на основе git и zsh.

  • Добавляет новые команды в Unix shell и Erlang.
  • Фреймворк теперь Open Source (GPL).
  • Возможность генерировать пакеты и инсталляторы.
  • Работает в кластерном окружении. Возможна синхронизация Erlang/CEAN на нескольких хостах, используя всего одну команду.
  • Возможность иметь столько версий инсталляций Erlang/OTP, сколько хочется.
  • Надёжный генератор зависимостей пакетов.

Ссылки:

Comments

Курица карри с рисом
  1. Куринное филе, 700 гр.
  2. Рис пропаренный, 700 гр.
  3. Перец болгарский, красный, 3 шт.
  4. Лук, 4 средние головки
  5. Вино белое, немного
  6. Специи: карри, кайенский перец, чёрный перец, орегано, майоран, розмарин, зира, имбирь, корица, мускатный орех
  7. Сахар, 2 ст. ложки
  8. Масло растительное или топлёное сливочное, достаточное количество
  9. Лук зелёный

Для начала надо замариновать куринное мясо. Сначала режем его кусочками 1.5x1.5 см, и делаем маринад. В глубокую посудину наливаем вино, столько, сколько нужно чтобы скрыть всё мясо. В вине разводим соль, добавляем туда корицу, имбирь, кайенский перец, розмарин, мускатный орех. Всего по-немногу, в зависимости от пристрастий. Закидываем туда мясо и ждём часа полтора.

Чистим лук, перец, промываем рис (замачивать его не надо). Из посуды потребуется сковорода с непригорающим покрытием и чугунный вок. Нагреваем обе посудины, кидаем или льём туда масло (оливковое не желательно, лучше подсолнечное или топлёное сливочное). В сковороде будет готовиться рис, а в воке мясо.

В сковороду бросаем зёрен 15-20 зиры, как она начнёт пениться, насыпаем в неё карри (примерно столовую ложку, без горки), чуть меньше столовой ложки сахара, быстро перемешиваем, чтобы сахар не начал гореть, и сразу же закидываем заранее порезанный кубиками лук (2 головки). Обжариваем минуты две, чтобы лук стал прозрачным, после этого насыпаем промытый рис, перемешивая с луком и карри жарим минут 5. К этому времени должен вскипеть чайник, рис в сковороде заливаем кипятком, солим (примерно столовую ложку соли), перемешиваем и закрываем крышкой. Сильно много кипятка сразу лить не надо, всего лишь, чтобы рис стал чуть-чуть жидковатым. По мере испарения воды её надо ещё подливать до тех пор, пока рис не приготовится. Перемешивать его больше не надо, на пару дойдёт. Готовность определяется пробой риса с поверхности.

Параллельно с рисом готовим курицу. В воке так же раскаляется масло, туда бросается столовая ложка карри и остаток сахара. Тут же бросается лук, порезанный кольцами или полукольцами (2 головки). Когда лук подрумянится, закладываем мясо и обжариваем, постоянно перемешивая. Посыпаем чёрным перцем, орегано и майораном. Орегано и майоран не обязательно, на любителя, но мне нравится. Перемешивая, жарим ещё минуты 2, затем закидываем болгарский перец, порезанный кусками примерно 2.5x2.5 см. Хорошо перемешиваем, накрываем крышкой, жарим минуты 3, потом ещё раз перемешиваем и оставляем доходить минут 10.

Вот и всё. По желанию посыпается зелёным резанным луком и поедается. Приятного аппетита.

Comments

*Улучшены ссылки в уведомлениях

Теперь ссылки в уведомлениях о комментариях ведут на тот блог, в который писался комментарий, а не в основной блог автора комментария. Энжой!

Comments

Подсветка кода в Markdown

Теперь можно делать так:

main() ->
  PathInfo = wf_context:path_info(),
  case dict:find(content, PathInfo) of
    {ok, feed} ->
      feed();
    _ ->
      #template { file="./site/templates/metalkia/bare.html" }
  end.

Работает в режиме ввода Markdown.

Блок кода пишется с минимальным отступом в 4 пробела. Язык кода задаётся в первой строчке, так же с отступом в 4 пробела и тремя двоеточиями. Например, в приведённом примере было указано :::erlang.

Comments (3)

HTTP Streaming

«HTTP Streaming» by Макс Лапшин:

Comments

Metalkia feed

Хотите быть в курсе изменений в Metalkia? Подпишитесь на фид блога, посвящённого разработке: http://mtreskin.metalkia.com/blog/metalkia/feed

Comments

Изменения в редактировании

Теперь пользователь, редактируя свой пост, видит ровно то, что писал сам, без дополнительной постобработки. Это правильно, ящитаю.

Comments

+Markdown

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

Энжой!

Comments (2)

+Заголовки

Приделал заголовки к постам. Сначала думал, что можно обойтись и без них, но оказалось, что неудобно.

Comments

+Заголовки

Приделал заголовки к постам. Сначала думал, что можно обойтись и без них, но оказалось, что неудобно.

Comments (7)

Atom feed

Сделал поддержку Atom. Фиды доступны, например, по таким адресам:

Comments

Казахстан. Озеро Язевое

Днём спуск с горы по тому же серпантину прошёл не сильно замеченным, дорога нормальная. Навстречу даже одна «Волга» проехала. Где-то рядом с предполагаемым поворотом на озеро Язевое увидели встречный «УАЗ-таблетку», остановились, спросили дорогу, куда свернуть. Водила объяснил, куда поворачивать, и отсыпал ещё кедровых орехов полные карманы.

(Read more)
Comments

Казахстан. Рахмановские ключи

Скоро доехали до Катон-Карагая. Там сходили в управу Катон-Карагайского природного парка и оформили пропуск в заповедную зону, где находятся Рахмановские ключи и озеро Язевое. В полицейском участке оформили регистрацию, как раз 5-й день шёл, и часов в 18 поехали дальше. На выезде встали на заправке, залили полный бак. Местный водила на Honda CRV стал пугать, что бензина не хватит, надо брать канистры. Канистры мы не взяли, я прикинул, что туда-обратно примерно 400 км должно получиться, подумал, что хватит. Собственно, и хватило, но по этому поводу голова немного болела, позже думал, что не хватит.

(Read more)
Comments

Казахстан. Бухтарма

Рано утром встали, попили чаю и поехали из Саввушек на границу с Казахстаном. В Змеиногорске остановил гаец, спросил, не везём ли чего запрещённого. Ответили, что не везём, и поехали дальше. Последние километры перед границей — пыльная грунтовка. Попали как раз на пересмену, очередь растянулась машин на 30:

Часа через два заехали на территорию таможни, прошли её минут за 10 и уже нейтральная территория. Километра через 4 уже казахстанская таможня, там тоже минут 10-15 и на свободе. Всё быстро, чётко, удобно. Теперь через Шемонаиху едем в Усть-Каменогорск (Өскемен). В Өскемене надо получить пропуск в погранзону (Катон-Карагайский район граничит с Китаем).

(Read more)
Comments

«Зачем рельсовику Ерланг» by Макс Лапшин:

Comments

Саввушка, Колыванское озеро

После Колывани поехали в Саввушку, на Колыванское озеро. Это рядом. Приехали, встали на территории турбазы рядом с обсерваторией:

(Read more)
Comments

Алтайский край. Колывань

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

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

Здание камнерезного завода:

Альбом: Колывань-2011
(Read more)
Comments

В блоге Travel буду писать про всяческие туристические покатушки и выкладывать фотки с мест.

Comments

+Уведомления о комментариях

В Metalkia добавлены уведомления о комментариях на email. Письмо получают все участники треда, в котором появился новый комментарий.

Comments (2)

Вставка кода

Код можно записывать так:

handle_info({Port, {data, Data}}, #state{port = Port} = State) ->
  ?DBG("Data from port: ~p", [Data]),
  port_close(Port),
  {noreply, State#state{port = undefined}};
handle_info(_Info, State) ->
  ?DBG("Unhandled info: ~p", [_Info]),
  {noreply, State}.

или так:

Comments (21)

Erlang Russian теперь работает на платформе Metalkia
Comments