программистское
Sep. 29th, 2009 06:51 pmОчень интересная беседа-интервью Джо Армстронга (Erlang) и Саймона Пейтона Джонса (Haskell). Формат транскрипта на этом сайте мерзостный, но нормальный транскрипт можно прочитать здесь.
Цитата:
Давно хочу изучить Эрланг, кстати. Кажется, эта беседа убедила меня заняться этим в ближайшие месяц-два.
Цитата:
JA: I didn't really know what thread safety was in Java, so I wrote a little Java Swing thing and of a Java friend I asked: I wrote this Java process and it worked fine. I could create one window, and then I created 2 windows in a graphical program and I drew a rectangle in one and I drew a rectancle in the other and it crashed. And I said "Why did it crash?" And he said "Well the Swing library's not threadsafe". Now, what does that mean? It means if you got one thing that works, you do 2 of them in parallel, they interact in strange ways. I thought "How can you program like that? It's impossible to program!"
Давно хочу изучить Эрланг, кстати. Кажется, эта беседа убедила меня заняться этим в ближайшие месяц-два.
no subject
Date: 2009-09-29 07:04 pm (UTC)no subject
Date: 2009-09-29 07:12 pm (UTC)workers
supervisors
так вот - основная идеология в worker - при помощи clause matching, единичного присваивания мы программируем только валидные пути выполнения. во всех оставшихся случаях позволяет данному процессу завершиться с badmatch или подобной ошибкой и прекратить выполнение.
задача супервизора - отловить падение worker-а (что-то пошло не так) и обработать по стандартному сценарию - т.е. либо restart (в частоности и всех зависящих процессов по иерархии), либо просто забить на данного отдельного worker-а. Рассматривайте аналогию с АТС - в принципе не важно, что один из 10000 звонков разорвался из-за того, что оба пациента орали Янку Дудль друг другу в телефон на полную мощность. Важно, чтоб все осташиеся звонки стабильно обслуживались :)
no subject
Date: 2009-09-29 07:15 pm (UTC)no subject
Date: 2009-09-29 07:23 pm (UTC)самое большое преимущество - в основном пишется только OК ветка.
с точки зрения безопасности - это тоже очень хорошая идея.
1. любой шаг вправо или влево - попытка к бегству - падает, логгим
2. прыжки на месте - провокация. когда в этом куске кода вы _планируете_ обработку ошибок - легче всего их вылавливать через try catch и не _задумываться_ что это за была ошибка - а выдавать стандартное сообщение об ошибке. в результате disclosure информации в ошибках - минимальный. потому что они тупо пишут - internal error и все ;)
2.1 да, программить чуть сложнее :))) но при наличии отличного механизма trace и правильной практике написания кода без side effects - локализация ошибки происходит очень быстро
no subject
Date: 2009-09-29 07:29 pm (UTC)еще один подход, который прививает эрланг - это следующее:
у вас есть программа, которая состоит из перемежающихся кусков -
1. трансформация данных
2. коммуникация с другими процессами
1. если программировать правильно - т.е. передавать все внутренее состояние через параметры функции и получать его обратно на выходе и писать функции без side effects (без взаимодействия с другими процессами и без хранения данных в process dictionary/etc table и т.д.) - тогда эта функция идеально отлаживается при помощи тестов.
потому что она ВСЕГДА при одном наборе входных данных должна давать один и тот же ответ. в результате - очень легко писать такие функции и их тесты :) хотя модули могут выглядеть монструозно :)))
2. тут самое интересное - потому что вы начинаете отлаживать _протокол_ взаимодействия с другими процессами. т.е. создаете enironment из заглушек-процессов, которые реагируют нужным вам образом и проверяете тестируемый код на то, что он _взаимодействует_ с другими согласно протоколу.
no subject
Date: 2009-09-29 07:33 pm (UTC)в одной из систем, ща посмотрел, wc -l показывает 33KLOC
;)
no subject
Date: 2009-09-30 06:46 am (UTC)no subject
Date: 2009-09-30 01:41 pm (UTC)dbg:p(new,c),
dbg:tpl(module_name, [{\'_\',[],[{return_trace}]}]),
ну и читайте мэнуал по этим функциям :))))
dbg:p - может вам будут интересны другие аргументы
dbg:tpl - можно указывать и конкретную функцию :)
[{\'_\',[],[{return_trace}]}] - это magic string, который без надобности менять не нада. ммм. это copypaste, и мне кажется, что \ там лишние - нужно проверить в реальной VM.
no subject
Date: 2009-09-30 01:42 pm (UTC)no subject
Date: 2009-09-30 02:01 pm (UTC)если че - пишите :)
no subject
Date: 2009-09-30 03:14 pm (UTC)RTMP сервер.
no subject
Date: 2009-09-30 01:45 pm (UTC)no subject
Date: 2009-09-29 07:38 pm (UTC)процессы НЕ могут взаимодействовать друг с другом только как при помощи отсылки друг другу сообщений :))))
соответственно это во власти _получателя_ обработать входящее сообщение когда ему удобно и когда у него _правильное_ состояние для этого.
таким образом вопрос - мы получили новую хрень в процессе обработки старой и она нам поломала все и вся - просто не стоит :)
ну и еще одна форма взаимодействия процессов - это убить другой процесс ;))))
для устойчивости есть еще офна фишка - процессы можно жестко связывать друг с другом. и если у вас конвейер - который должен четко передавать сообщение вправо по цепочке, а потом влево обратно - то если они слинкованы и один из них падает - то умирает сразу _ВСЯ_ цепочка - что очень полезно - т.е. либо мы ВСЕ работаем и у нас у ВСЕХ все хорошо, либо мы ВСЕ умираем :)
правда, есть возможность ловить падение прилнкованного(дочернего) процесса как СООБЩЕНИЕ, а не как убийство данного процесса - и это сообщение можно обработать. именно на этом и основаны супервизоры.
no subject
Date: 2009-09-29 07:19 pm (UTC)no subject
Date: 2009-09-29 07:19 pm (UTC)т.е.
A=3, что-то там, A=2 - все, упал. переменным нельзя присваивать новые значения. Это наже не переменные, а просто привязаные к значениям символические метки-имена.
{A,B} = {1,2,3} - падаем нафиг, arity не совпадает (количество элекентов) - это так же срабатывает при matching более сложных вложенных структур
case A of
1 -> ok;
2 -> ok
end
догадываетесь при значении A=3 что произойдет? праавильно, упадет нафиг. ибо этот случай разработчик не предполагал. нужно обрабатывать default ветку - пишите ее в явном виде.
ну и так далее. эта идеология во всем. дико удобно, после того как привыкаете.
{ok, Socket} = sockets:connect(blah-blah) - это я гипотетический код пишу, но блико к реальному
если в ответ пришло {err, Error} - то все, процесс упадет нафиг. Именно потому что я НЕ Хочу вообще обрабатывать error case. Если соединение не установилось - дальше делать вообще ничего не надо. Почему не соединилось - меня не интересует.
если бы интересовало - был бы код
case sockets:connect() of
{ok, Socket} -> ....;
{err, ErrMsg} -> ....
end