Pull to refresh
359
2.9
Alex Efros @powerman

Software Architect, Team Lead, Lead Go Developer

Send message
Проблема не в том, чтобы сказать, а в том, чтобы услышать(понять). Ниже Вам привели ссылки, где это "сказано", причём довольно неплохо (а "Аэростат" можно не только почитать, но и послушать).

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

Можем продолжить эту беседу в аське, если захотите.
Недеяние - это вообще не цель. Это состояние. :)
Используя красивые слова не понимая их значения вы капитально запутываете и себя, и часть своих читателей. Недеяние - это не то, что Вы под ним понимаете. Недеяние не бывает "для меня" одно а "для тебя" другое. Задача свёртывания второстепенного никакого отношения к недеянию не имеет.
Соболезную. Это, кстати, довольно типовой случай. При работе в офисе народ через какое-то время понимает, что можно получать те же деньги работая значительно меньше... и, более того, никому вокруг, в общем, и не нужно, чтобы ты работал лучше и больше. И народ расслабляется. От этого "спасает" фриланс - там не поработаешь - не поешь.
Ни о чём - это тонко подмечено. Во-первых, до этого момента никто не говорил о дополнительной функциональности. Речь шла об overquality (хотя я ничего "over" в желании написать более качественно, чем минимально необходимо не вижу - кто сказал что нужно всё делать по минимуму?). А во-вторых, у Вашего шефа и заказчика действительно может не быть желания заниматься программированием из любви к искусству, но вот у Вас оно вполне уместно, если Вы программист.
Вы предприниматель? Или программист? Или и то, и другое одновременно? Вы бы определились...

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

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

P.S. Существует мания, когда всё подряд переписывается без веской причины - это имеет смысл только в рамках обучения. Но есть и другая ситуация, когда ты реально можешь написать библиотеку качественнее готовой, причём патчить готовую сложнее написания своей (из-за архитектурных проблем, например), причём в текущем проекте требуется уровен качества выше того, которые предоставляет готовая библиотека - тогда написание своей имеет смысл, хотя и часто не делается из-за экономических причин (повышение качества на X и увеличение времени разработки на Y не оправдывает увеличения расходов на Z). Но этот экономический расчёт зачастую верен только в краткосрочной перспективе, а в долгосрочной это переписывание всё-равно бы окупилось.
Да, очень хороший и взвешенный подход. Но на практике он выливается в то, что после написания первого крупного проекта (и написания для него своего фреймвока), средние, шаблонные проекты тоже оказывается проще писать на своём фреймвоке.
Давайте Вы не будете передёргивать - это просто не культурно.

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

Во-вторых, лично я не просто готов платить больше за качественный софт, вопрос стоит иначе: я не готов платить ни копейки за некачественный софт. Что касается цен M$, то, как известно, они зарабатывают ГОРАЗДО больше, чем тратят на разработку. Так что, я уверен, они имеют возможность писать гораздо более качественно, сохраняя прежний уровень цен. Просто им это не нужно.
Не ожидал увидеть в комментариях столько любителей overquality и изобретателей велосипедов. Нам явно уже можно объединяться и создавать специальную организацию для защиты наших интересов и пропагандирования наших идей. :)

P.S. А по поводу изобретательства велосипедов, я уже когда-то цитировал эту фразу на хабре, но я повторюсь, уж больно хорошо сказано автором JSON:
The good thing about reinventing the wheel is that you can get a round one.
А, вот лично Вы, ещё разве не устали от потоков низкокачественного софта, изливающихся на нас, и с которыми нам приходится иметь дело? Ведь мы, ITшники, работаем с софтом гораздо более интенсивно, чем наши не-ITшники заказчики. Да, overquality не нужно нашим заказчикам, но оно нужно именно нам самим! И с этой точки зрения оно вовсе не "over".
Когда заказчик, после сдачи проекта, просит добавить фичу X, то сложность поддержки зависит от того, насколько эта фича вписывается в архитектуру и насколько читабельно написан код. Совет:
5. Пишите код, который удобно читать вам. ... Когда же вы пишете код для того, чтобы его можно было легко восстановить в памяти, вы скорее предпочтете краткость.
полезен пока изначальный код пишется в "потоке". Когда программист, который написал этот код, полезет его модифицировать через 3 месяца, ему самому будет не просто вникнуть в эти краткие конструкции. Фактически, для того, чтобы нормально менять этот код, ему опять нужно будет войти в "поток", загрузить в голову весь проект целиком. Это, в принципе, правильно, но требует довольно много времени.

Я думаю, что этот совет можно применять так, чтобы это не усложняло поддержку кода. Во-первых, можно привыкнуть писать/читать более простой, хоть и не такой краткий код. Тогда удобно будет читать именно его. :) Во-вторых, краткость здесь нужна ради удержания всего проекта в голове, а не ради того, чтобы сложную функцию "запинать" в 3 строки. Поэтому если при нормальной записи кода проект в голове перестаёт умещаться, нужно не код более кратко записывать, а проект дробить на изолированные кусочки, которые не нужно одновременно удерживать в голове.
Да, судя по комментариям, disclaimer ему сделать явно бы не помешало. Но он, вообще-то, его сделал, просто он "размазан" по тексту. К примеру:
Но в данном случае это личный проект, и он хочет сделать его идеально.

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

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

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

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

Теперь Датское королевство переписано надлежащим образом, без перехватов die и вызовов exit. Всё стало очень культурно и аккуратно. И проблема с goto отпала сама собой - сейчас фреймвок сам генерит исключение вместо exit. И никаких вложенных eval-ов в тех местах, где может быть редирект у меня ни в одном проекте нет... и если когда-нить появятся, значит после этого eval необработанные исключения будут передаваться наверх, как и положено.

В общем, ощущения у нас были правильные - изменил архитектуру и проблема исчезла.
Да, идея с END красивая... но не менее стрёмная, чем с goto. Дело в том, что, насколько я знаю, блоки END начинают выполняться когда perl уже входит в состояние завершения работы, освобождает ресурсы, etc. И тут ему говорят, погоди, поработай ещё, а мы тебе ещё один блок END подсунем. :)

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

Что касается утечек - они 100% должны быть, ведь после обработки каждого запроса в память добавляется ещё один блок END, при этом старые блоки из памяти не освобождаются. Другое дело, что много он памяти врядли занимает, и рестарт процесса раз в несколько тысяч запросов эту утечку памяти решит.
Это немного не в тему, но вопрос немного в другом - не в том, как прервать accept, а в том, как перехватить exit (вызываемый в коде обрабатывающем запрос) и вернуться в этот цикл.
YES!!! Чувство жо.. в общем, интуиция меня не подвела и на сей раз. :) Вот он, этот баг с goto:

perl -e '
BEGIN {
  *CORE::GLOBAL::exit = sub {
    goto FASTCGI_NEXT_REQUEST;
  };
}
while (1) {
  eval { that_cgi_script() };
 FASTCGI_NEXT_REQUEST:
  last;
}

sub that_cgi_script {
  local $SIG{__DIE__} = sub { print "<p>error: $_[0]"; exit; print "XXX\n" };
  print "before buggy code\n";
  eval { buggy_code() };
  print "after buggy code\n";
}
sub buggy_code {
  die "error!";
  print "after die\n";
}
'

Этот пример выводит:

before buggy code
<p>error: error! at -e line 20.
after buggy code

т.е. goto не срабатывает как надо, и выполнение продолжается после eval. Фактически exit в обработчике $SIG{__DIE__} срабатывает как return - ведь "print XXX" не срабатывает.

Я нашел как этот баг обойти. Нужно в блоке BEGIN добавить no-op обработчик CORE::GLOBAL::die (который просто симулирует работу системного):

  *CORE::GLOBAL::die = sub {
    if ($SIG{__DIE__}) {
      my $s = $_[0];
      $s .= sprintf " at %s line %d.\n", (caller)[1,2] if $s !~ /\n\z/;
      $SIG{__DIE__}->($s);
    }
  };

и теперь этот тест работает корректно, и выводит:

before buggy code
<p>error: error! at -e line 27.

Впрочем, объяснить почему добавление такого обработчика заставляет goto работать правильно я пока не готов. :( Возможно, дело в том, что мой обрабочик всё-таки не до конца симулирует стандартный обработчик перла. Правда, на множестве разнообразных тестов, которые я прогнал - я разницы между ними не заметил, если не считать вышеописанную.
Ну что тут сказать... Доводы в пользу архитектуры - это как раз те самые пункты, которые я перечислил, плюс достаточно простой и элегантный протокол - а с Вашей стороны доводов по архитектуре я пока не видел. Ваши ответы из серии "а оно вам надо", "это забота сисадмина" - это странные ответы. Во-первых я и есть сисадмин, и это, действительно, моя забота. Во-вторых, Вы попросили рассказать преимущества FastCGI - я рассказал. Надо ли оно Вам - это другой вопрос, но факт наличия этих преимуществ отрицать бессмысленно. И что касается отсутствия FCGI на CPAN - это шутка?

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

Что касается Apache::Request и тяжёлого CGI.pm. Да, в принципе я согласен. Но, а Вам не всё равно, насколько тяжёл CGI.pm, в условиях FastCGI? Параметры он возвращает? Аплоады контролирует? Что ещё от него нужно? Не html же через него выводить... :)

Лично для меня, основной довод в пользу именно FastCGI, это безопасность: CGIшки запускаются от пользовательского аккаунта, внутри веб-сервера они не выполняются, никаких сложных механизмов обеспечения безопасности типа SuExec и CgiWrap не используется. Второй довод - поддержка разных веб-серверов. Мы давно хотели отказаться от апача, и использование FastCGI облегчает попытку попробовать другой веб-сервер.

Кстати, на CPAN появился модуль FCGI::Spawn, который использует FCGI как раз для обеспечения безопасности: он не держит в памяти конкретную CGI, а, вместо этого, при каждом запросе подгружает и запускает CGI, указанную параметром $ENV{SCRIPT_FILENAME}. Как там написано: "hot ready for hosting providing".
  • FastCGI чисто архитектурно значительно лучше альтернатив.
  • В отличие от mod_perl, FastCGI сервер может работать с разными веб-серверами (apache, nginx, lighttpd, etc.).
  • FastCGI лучше масштабируется, т.к. позволяет разнести веб-сервер и CGIшки по разным машинам.
  • По сравнению с mod_perl, FastCGI приложения гораздо удобнее контролировать (запускать, рестартовать, отлаживать, управлять кол-вом одновременно работающих процессов, etc.), и все эти операции не требуют перенастройки и перезапуска веб-сервера.
  • Можно перезапустить веб-сервер не перезапуская CGIшки (удобно при активном использовании кеширования).
  • При использовании апача, запуск FastCGI-приложения от обычного пользовательского аккаунта (не nobody) гораздо проще и безопаснее, чем использование SuExec или CgiWrap.
    Я не совсем понял, что Вы имели в виду под "только применительно к Perl". Все эти особенности FastCGI к Perl применимы так же, как и к другим языкам. Ничего Perl-специфичного в технологии/протоколе FastCGI нет.

    Если это не под NDA, расскажите, пожалуйста, чего именно Вы натерпелись при использовании Perl под FastCGI, и какие библиотеки при этом использовали.
Простите, но с этим я согласиться не могу. Причём - по всем пунктам сразу. :)

  1. Цепочки return-ов - это ужасно. Это означает, что каждая функция должна возвращать смесь результата и ошибки - примерно как это делает весь POSIX с его кошмарным кодом возврата -1 и errno. Чтобы этого избежать, как раз и придумали исключения.
  2. goto (он же setjmp/longjmp) - это вполне адекватная вещь, когда используется по назначению. А когда goto используется вместо управления циклами (next/last/redo), выхода из процудур (return), симуляции исключений (die) - вот тогда он неуместен. Например, в perl есть goto на процедуру, который может использоваться для оптимизации tail recursion.
  3. mod_perl. Во-первых он не предназначен для ускорения CGI, он разрабатывался для ковыряния внутренностей апача на perl, в чём ему равных нет. Во-вторых на хостинге mod_perl это одна большая дыра в безопасности. Ну и кроме того у FastCGI есть много других плюсов, по сравнению с mod_perl - если интересно, могу рассказать.

Information

Rating
1,970-th
Location
Харьков, Харьковская обл., Украина
Date of birth
Registered
Activity

Specialization

Backend Developer, Software Architect
Lead
From 10,000 $
Designing application architecture
Golang
Linux
Docker
Network security
Modular testing
Mentoring
Development of tech specifications
Software development
High-loaded systems