Разработка веб-сайта на паскале (backend)

    В этой статье я расскажу о том, зачем, почему и как я начал делать сайты на паскале: Delphi / FPC.
    Вероятно, «сайт на паскале» ассоццируется с чем-то вроде:

    writeln('Content-type: text/html');

    Но нет, всё гораздо интереснее! Впрочем, исходный код реального сайта (почти весь) доступен на GitHub.

    Зачем?


    Вообще я ни разу не профессиональный веб-разработчик — я делаю игры. А игре, особенно онлайновой, нужен сайт. Поэтому так сложилось, что я стал делать ещё и сайты для своих игр. Используя CGI на Perl — в начале/середине 2000-х это было популярно. Всё было хорошо, пока не возникла проблема.

    В 2013 году мы начали проводить онлайн-турниры по игре "Спектромансер", для этого на сайте игры я сделал турнирную страничку, где показывается кому с кем играть, текущие результаты и т.п. В момент старта турнира страничка у игроков обновилась и… не загрузилась. Люди нажимали F5, чем ещё больше усугубляли проблему. Оказалось, что даже 4-5 запросов в секунду к CGI-скрипту, запускаемому в виде отдельного Perl-процесса, ощутимо замедляют сервер, а >10 запросов в секунду делают его совсем недоступным.

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

    Почему?


    Таким образом, когда возникла необходимость делать вот этот сайт для новой игры, возник вопрос — на чём? Тормозной CGI на Perl — не вариант. FastCGI на Perl? Не представляю как писать и отлаживать многопоточную программу на Perl, мне и с обычными-то скриптами проблем хватало. Node.js? Наверно это был бы наилучший выбор, если бы не некоторая неприязнь к JS. А поскольку сама игра и её сервер написаны на паскале (на самом деле Delphi, но FPC тоже годится), возникла идея — а не сделать ли сайт на этом же языке? Это упростит интеграцию с сервером игры. «Попытка — не пытка!» — подумал я, и решил попробовать.

    Как?


    В качестве интерфейса выбрал SimpleCGI (SCGI): он несколько проще FastCGI, а преимущества последнего для меня неактуальны — нет необходимости разносить бэкенд на разные сервера, всё крутится на одном сервере. Так что задача свелась к разработке некоего SCGI-фреймворка, обрабатывающего запросы от сервера и генерирующего в ответ HTML-страницы из неких заготовок, шаблонов. В результате получился вот такой модуль-фреймворк. Он состоит из следующих частей:

    • Главный цикл: принимает входящие соединения, считывает запросы и складывает их в очередь для обработки. Готовые ответы на обработанные запросы записывает в сокеты соединений и закрывает их.
    • Рабочие потоки (N штук): достают запросы из очереди, парсят их заголовки и вызывают для исполнения пользовательские обработчики. У каждого worker'а — своё собственное постоянное подключение к БД.
    • Система трансляции шаблонов: служит для генерации HTML-кода (или любого произвольного текста) путём рекурсивной трансляции шаблонов. Шаблоны грузятся из текстовых файлов.
    • Набор вспомогательных функций: предназначен для использования обработчиками запросов (аналогично модулю CGI.pm в Perl). Получение параметров, установка куки и т.п.

    Шаблоны


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

    Работает она так. В папке «templates» лежат файлы шаблонов: они загружаются при запуске процесса а также перезагружаются при изменении — таким образом можно изменять динамический контент не перезапуская процесс. В каждом файле может быть один или несколько шаблонов. Все вместе они образуют словарь (или хэш) шаблонов: {«имя»->«значение»}. Это статический словарь шаблонов — он общий для всех запросов и его содержимое неизменно (пока не изменится содержимое файлов). Есть ещё второй — динамический словарь, он создаётся пустым для каждого запроса и заполняется обработчиком динамическими данными — например из БД. Комбинируя статические и динамические данные и формируется итоговый результат.

    Пример декларации шаблона:

    #NEWSFEED_ITEM:
    <div class=NewsHeader>
     <a href='/$LANG_LC/forum/thread/$NEWS_ID'><IF_NEWS_PINNED>[TOP]  </IF_NEWS_PINNED>$NEWS_DATE   $NEWS_TITLE</a>
    </div>
    <div class=NewsText>$NEWS_TEXT
     <div align=right>
      <a href='/$LANG_LC/forum/thread/$NEWS_ID'>$COMMENTS</a>
     </div>
    </div>

    Это статический шаблон записи в ленте новостей с именем NEWSFEED_ITEM, внутри он содержит включения нескольких других шаблонов, например NEWS_TEXT — динамический шаблон, содержащий текст новости, загруженный из БД. Трансляция заключается в том, что все подстроки вида $ИМЯ_ШАБЛОНА рекурсивно заменяются на значение этого шаблона.

    Здесь можно также заметить псевдотэг для условной трансляции: <IF_ИМЯ_ШАБЛОНА> — в процессе трансляции такие тэги удаляются а их содержимое оставляется либо также удаляется — в зависимости от значения указанного шаблона. Я специально выбрал такой формат условий — в виде HTML-тэгов, чтобы при редактировании в текстовом редакторе работала подсветка синтаксиса и чтобы было легко видеть парный тэг.

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

    
        result:='';
        // Для каждой новости выполняем трансляцию шаблона NEWSFEED_ITEM и складываем всё в строку result
        for i:=0 to n-1 do begin
          id:=StrToIntDef(sa[i*c],0);
          title:=sa[i*c+1];
          cnt:=StrToIntDef(sa[i*c+2],1)-1;
          flags:=StrToIntDef(sa[i*c+3],0);
          // запрашиваем текст и дату новости
          db.Query('SELECT msg,created FROM messages WHERE topic=%d ORDER BY id LIMIT 1', 
            [id]);
          if db.lastErrorCode<>0 then continue;
          text:=db.Next;
          date:=db.NextDate;
          // Заполняем динамические шаблоны (словарь temp)
          temp.Put('NEWS_ID',id,true);
          temp.Put('NEWS_DATE',FormatDate(date,true),true);
          temp.Put('NEWS_TITLE',title,true);
          temp.Put('NEWS_PINNED',flags and 4>0,true);
          comLink:='$LNK_READ_MORE | ';
          if cnt>0 then comLink:=comLink+inttostr(cnt)+' $LNK_COMMENTS'
            else comLink:=comLink+'$LNK_LEAVE_COMMENT';
          temp.Put('NEWS_TEXT',text,true);
          temp.Put('COMMENTS',comLink,true);
          // Выполняем трансляцию шаблона
          result:=result+BuildTemplate('#NEWSFEED_ITEM');
        end;
    

    Локализация


    Шаблоны также удобно использовать для локализации. Для этого используется глобальная (в контексте запроса) переменная clientLang. Работает это так: если обработчик запроса выясняет, что клиенту нужна страница на русском языке — он записывает в clientLang значение «RU», после чего транслятор шаблонов, обнаружив в тексте $ИМЯ_ШАБЛОНА, всегда пытается сперва применить $ИМЯ_ШАБЛОНА_RU. Таким образом, для локализации нужно всего лишь для каждого шаблона с текстом создать его вариант для другого языка:

    #TITLE_NEWS:News
    #TITLE_NEWS_RU:Новости
    

    Пример использование фреймворка


    Пример кода простого сайта:

    program website;
    uses SysUtils, SCGI;
    
    // Обработчик запроса главной страницы
    function IndexPage:AnsiString; stdcall;
     begin
       result:=FormatHeaders('text/html')+BuildTemplate('#INDEX.HTM');
     end;
    
    begin
     SetCurrentDir(ExtractFileDir(ParamStr(0)));
     SCGI.Initialize; // Загрузка конфига
     AddHandler('/',IndexPage); // Устанавливаем обработчик для запроса '/'
     SCGI.RunServer; // запускаем рабочие потоки и главный цикл
    end.
    

    Итого


    Описываемый фреймворк я написал в процессе создания реального сайта astralheroes.com в конце 2015 года. Как это обычно бывает, первый блин вышел немножко комом — код получился несколько сумбурным и запутанным, следующий сайт получается уже лучше. Тем не менее, и процессом и результатом я доволен: сайт работает хорошо, легко отлаживается и обновляется.

    Выводы:

    • Я ожидал, что по сравнению с компактным Perl код сайта сильно раздуется, но нет — та же функциональность, написанная на паскале, занимает лишь примерно вдвое больше, чем на Perl. Но при этом выглядит более понятно.
    • Радует отладка! Perl — замечательный язык, если нужно написать что-то в пределах 100 строк, такое, что не требует отладки. Но как только нужно сделать что-то более-менее сложное — отладка превращается в кошмар. В Delphi же заниматься отладкой легко и удобно.
    • Часть функционала сайта осталась на Perl. Потому что во-первых, часть функций осталась неизменной с предыдущего сайта, поэтому нет смысла переписывать то, что уже написано и исправно работает. А во-вторых, некоторые некритичные к скорости вещи гораздо проще реализовать на Perl, если там для этого есть готовая библиотека, а на паскале её нет.
    • Работать с шаблонами довольно удобно: они позволяют структурировать сайт, разбить его на отдельные блоки, избегать дублирования текста. И еще упрощают локализацию.
    • Радует производительность. Ведь я экономлю время не только на запуске процессов, загрузке библиотек, подключении к БД (что само по себе немаловажно), но и имею возможность сохранять контекст, глобальные данные и использовать их для обработки множества запросов. Например, для реализации поиска по форуму используется глобальный индекс, который постоянно доступен в памяти — не нужно ничего грузить из БД. Данные рейтинга игроков также кэшируются.

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



      Подсветка названий карт выполняется динамически при загрузке страницы, а не заранее — при сохранении текста. Это хоть и более ресурсоёмко, но имеет свои плюсы.

    Так где же исходники сайта?


    Исходники на GitHub: github.com/Cooler2/ApusEngineExamples

    Обратите внимание, что в репозитории есть подмодуль, поэтому клонировать лучше с параметром "--recursive".

    Проект сайта находится в файле: «AH-Website\Backend\src\website.dpr»

    Это не совсем полная копия действующего сайта: понятно, что я не могу опубликовать содержимое БД с данными игроков, я также не публикую CGI-скрипты, поскольку они не имеют отношения к описываемой теме. Тем не менее, проект собирается, запускается и работает, полностью демонстрируя работу фреймворка.

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

    Спасибо за внимание!

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 191

      +7
      троллейбус_из_хлеба.jpg
        +20
        Я ждал этого коммента! Кажется, он неизбежно появляется в статье, где встречается слово «Паскаль» :)
          0
          А для непосвященных, в чём связь мема про буханку с Паскалем?
            +6

            Можно, но зачем?

        +8
        Открываешь проект обычного сайта. В одной папке: csv, js, ctl, txt, rus, dll.
        [Да ну нахер...].jpg

        Серьезно, автор, вы прям любитель БДСМ.
          +7
          Ну у нас, к счастью, пока нет закона о сегрегации файлов по их типам :)
          А если серьезно, можете привести аргументы, почему этим файлам не стоит лежать в одной папке? (кроме js — это случайный мусор, уберу).
            +1
            Дело не в самих типах, а в том, что в проекте обычного сайта такие зоопарки обычно не встречаешь :)

            А чем nodejs не угодил? Ну кроме мифической неприязни к JS (вам все равно пришлось на нем писать, ибо на сайте есть интерактив).
              +2
              Да вполне угодил — я уже собирался начинать изучать Nodejs, но решил сперва попробовать так. Результат понравился, поэтому необходимость в ноде отпала.
                +7
                Результат на самом деле крут, тут не спорю :)
                Просто веб на паскеле это прям отдельное извращение :) Но раз нравится, что ж )
                  +2

                  Ой, да ладно. Серверу плевать, на чём быть написанным. Я в детстве на Visual Basic-е писал.

                    +1
                    Серверу — да. А вот поддержка такого сайт усилиями не-автора будет мучением, т.к. попробуй найди веб-разработчика на паскале.
                –1
                Поддержка WebAssembly есть в GNAT и FPC
            +2

            Для обучения неплохо.
            Но если вам для работы, то лучше использовать mORMot (https://synopse.info/).

              +2
              Спасибо, интересно взглянуть!
                +4
                Посмотрел — выглядит как-то очень сложно. Простота — залог надёжности.
                  0

                  На самом деле не так он сложен как кажется. Так как с актуальными библиотеками на Паскале (особенно с поддержкой как Delphi так и FPC) все плохо, проект реализует почти весь функционал необходимый для разработки бизнес приложений. Никто не запрещает пользоваться только отдельными кусками. Работа с HTTP там реализована очень неплохо.

                0
                Не совсем понял, на Паскале и шаблонах сделан только сайт, или форум тоже?
                  +2
                  Форум тоже, он — часть сайта, причём бОльшая.
                  +3
                  Есть же готовые фреймворки для написания бэка. Например dmvc бесплатный, прекрасно покрыт примерами, пиши что хочешь. Компилируй хочешь под win, хочешь под linux.
                  Из понавороченнее TMS XData платный, там вообще чуть ли не автоматом встроенный swagger для тестирования и документации.
                    0
                    Люди вот форум на ассемблере написали, да proof-of-concept, работает, но стоит ли тех усилий, да и выигрыш сомнительный.
                      +2
                      Ну я делал не «because I can». Целью эксперимента было сравнить разработку сайта на Перле и на Паскале: по трудозатратам, удобству сопровождения и т.д. Если бы оказалось, что усилий приходится затрачивать больше, то ну его нафиг…
                        0

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

                      +1
                      Наверное, некритично, но
                      Немного кракозябров в коде
                      image
                        +3
                        Да, постоянно забываю сохранять исходники в utf-8, спасибо!
                        0
                        db.Query('SELECT msg,created FROM messages WHERE topic=%d ORDER BY id LIMIT 1', 
                        [id]);

                        А вы не боитесь SQL injection?

                          +4

                          В данном случае ничего страшного нет.
                          А вот в функции SQLSafe я не увидел обработки одинарной кавычки. Вообще, для SQL родные кавычки одинарные. Двойные БД автора видимо тоже понимает, но могут быть нюансы.

                            0

                            Здесь MySQL, кавычки повсюду использую двойные, поскольку запросы со строками обычно выглядят так:


                            db.Query('SET param="%s"', [value]);

                            т.е. поскольку одинарные уже задействованы, логично использовать двойные.


                            Но вообще спасибо за замечание, действительно стоит обрабатывать и одинарные.

                              0
                              Да что ж такое? Когда уже люди, наконец-то, научатся плейсхолдеры использовать? :(
                                0

                                Какие плейсхолдеры?

                                  0

                                  SELECT * FROM whatever WHERE foo=?

                                    0

                                    И в чём разница?
                                    Для типичных запросов там есть QueryHash() и QueryValues() — это устраняет дублирование кода, но в целом его очень немного.


                                    Для больших структур есть генератор кода для импорта/экспорта этих структур в БД, но в данном проекте это неактуально.

                                      0
                                      И в чём разница?

                                      Возьмем этот же зпрос выше: db.Query('SET param="%s"', [value]);

                                      что будет если в переменной value будет " где то в строке?
                                        0

                                        Оно преобразуется в \", поскольку все строки, передаваемые в Query(), проходят обработку.

                                          0
                                          а имплементация процедуры db.Query выложена на гитхаб тоже? Я не нашел… Хотя признаюсь особо и не искал :) Скиньте пожалуйста линк на файл где это реализовано.
                                          Или вы говорите что перед передачей в Query оно проходит обработку?
                                          Если так — то есть высокая вероятность «забыть» эту обрабаботку. И если не сложно — где эта «обработка» происходит?
                                +2

                                У автора по сути тоже плейсхолдеры, только с наивной реализацией

                          +2

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


                          Ну и сам сайт выдает очень странные ворнинги. О каких таких "плохих последствиях" идет речь боюсь даже представить:


                          img




                           function InsertCardHints(const msgText:AnsiString):AnsiString;
                            var
                             i,j,k,l,m,p,f,d1,d2,w,words:integer;

                           function FormatForumMessages(condition:AnsiString;const profile:TUserProfile;cutNearMsgID:integer=-1):AnsiString;
                            var
                             key,key2,list,msgtext,author,pFlags:AnsiString;
                             messages:THash;
                             profiles:THash;
                             players:THash;
                             attachments:THash;
                             lastread:THash;
                             plrID,profileID,face,topicID:variant;
                             i,n,cnt:integer;
                             attList,lrd,levelLabel:AnsiString;
                             arr:IntArray;
                             attType,attThumb:AnsiString;
                             moderator:boolean;
                             r1,r2:TRegExpr;
                             date:TDateTime;
                             skipFrom,skipTo,SkipAfter:integer;

                          Очень сложно.

                            0

                            Обратите внимание, все эти warning'и происходят из сторонних скриптов.


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

                              0

                              А можно увидеть этот более лучший код? Хотелось бы оценить, насколько удобно получается.

                                0

                                Пока к сожалению нельзя.

                            0
                            Эххх… когда-то пришлось на www.delphitools.info/dwscript писать :)
                              +1

                              Cooler2 Уже давно есть более гибкие способы запуска перл на том же mojo. Вообщем всем советую по перлу наш telegramm канал ( modernperl.ru )

                                0

                                Как с юнит тестированием на паскалях?

                                  0
                                  DUnit и тестируемся на ура (правда в делфи)
                                    0

                                    Не очень, но жить можно. Остановился на fptest.

                                      0

                                      А как тестировать контроллеры, вроде вот этого? В том же дотнете контроллер это обычная функция, её можно вызвать, получить IActionResult и проинспектировать, а всё взаимодействие с HTTP описывается атрибутами, которые в тестах игнорируются, а рантаймом HTTP сервера — используются.


                                      В коде который я смотрел выше у функии параметров нет, она сама достает что-то из эмбиент контекста через всякие Param/IntParam, и возвращает просто строку.

                                        0

                                        К чему вопрос? Вы сами прекрасно понимаете что это не тестируемый код. Автор отметил что он не профессиональный разработчик, так что это простительно.

                                          0

                                          А, этот момент я пропустил. Тогда, конечно, вопросов не имею.

                                            0

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

                                              +2

                                              А у разработчиков игр которых я знаю (в частности, пара работала в нивале и обсидиане) тесты есть.

                                                0

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


                                                Тогда можно вопрос? Почему именно Delphi для разработки игр, если это источник заработка? Все дело в поддержке проектов, или нет желания менять платформу?

                                                  0

                                                  Дело и в поддержке, и в преемственности, и в опыте: куда как проще писать новую игру на хорошо знакомом языке, на своём движке. Чем с нуля начинать на Unity и C#. Путь наименьшего сопротивления. Хотя с точки зрения востребованности на трудовом рынке, это, конечно, большой минус.

                                                    +2

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

                                                      0

                                                      Несколько лет назад была возможность поработать на lua, но предпочёл Java. Писать на Java в Idea — одно удовольствие :)

                                                        0

                                                        А как обстоят дела с востребованностью геймдева на Java за пределами Andorid и разработки бекенда к играм?

                                                          0

                                                          Не знаю, не интересовался. Но в целом десктопный геймдев сейчас — это либо C++ (UE), либо Unity.

                                        +2

                                        Есть же стандартные решения в Lazarus — и cgi, и fcgi, и даже стенделон для всякого реста
                                        https://wiki.freepascal.org/fcl-web

                                          0

                                          И шаблоны там выглядят как-то так:


                                          <br>
                                          Something here for the body
                                          
                                          <table border=1>
                                           <tr>
                                            <td valign="center" width=200 height=200>
                                          {+INCLUDETEMPLATE [-TEMPLATEFILE=body_left.html-]+}
                                            </td><td valign="center" width=200 height=200>
                                          {+INCLUDETEMPLATE [-TEMPLATEFILE=body_right.html-]+}
                                            </td>
                                           </tr>
                                          </table>

                                          Но писать в Лазарусе — это боль.

                                            0
                                            Но писать в Лазарусе — это боль.

                                            Почему?

                                              +1

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


                                              Другой пример:


                                              var s:string
                                              ...
                                               s.ToUpper;
                                              

                                              В mode=Delphi — работает, в mode=DelphiUnicode — ошибка. А по документации должно работать.

                                                0
                                                Да, с вот этой фигней из Дельфей он фигово работает. Очень уж ему нужна кроссплатформенность. Считается, что нужно использовать нормальный ObjFPC, в котором адекватный Юникод вместо UTF16
                                                  0

                                                  Кстати я тоже не в восторге от того, что в Delphi сделали со строками, считаю это большой глупостью. Нормально же всё было! Захотели сократить зоопарк строковых типов — добавили ещё один :(

                                                  0

                                                  Нужно ставить правильные версии, тогда все работает.
                                                  Рекомендую установить FPC и Lazarus по следующей инструкции:
                                                  26.4.2. Setup your dedicated environment with fpcupdeluxe
                                                  Затем довести IDE до привычного вида, как в Delphi:
                                                  Lazarus Docked Desktops

                                                    +1

                                                    То есть на официальном сайте Lazarus — неправильная версия? Ну Ok.


                                                    Вообще я в курсе, что в инете есть допиленные версии Лазаруса, но сам факт того, что такие версии нужно где-то искать, вместо того, чтобы взять на официальном сайте — уже о чём-то говорит!

                                                      0

                                                      На официальном сайте версия просто очень старая — 3.0 была выпущена в 2015 году. И Юникод в ней нормально не работает, для него нужна версия хотя бы 3.1.
                                                      Актуальная версия сейчас это 3.3, но так как она находится в активной разработке, то нельзя просто взять любую ревизию из ветки 3.3.

                                                        +1

                                                        Вы про версию FPC или Лазаруса?
                                                        Сайт FPC гласит: "The latest release is 3.0.4." (ноябрь 2017).
                                                        Сайт Лазаруса: 2.0.6 — ноябрь 2019, на базе FPC 3.0.4.


                                                        Связываться с версиями, которые в разработке — ну, такое… По-моему проще взять Delphi.

                                                          +1

                                                          Если есть лишние $1800 ($4500 если нужен Linux), то конечно Delphi во всех отношениях лучше.
                                                          Лично я использую FPC 3.3.1 и Lazarus 2.1.0, установка и настройка занимает пару часов, ссылку на инструкцию я выше приводил.

                                                            0

                                                            Поставил 3.3.1/2.1 — работает хорошо! Спасибо :)

                                                        +1
                                                        На официальном сайте — «Debian Stable»-стайл, окаменелый, но надежный.
                                                        Если хочется фич — типа наконец-то добавленных Generics.Collections с TDictionary и прочее — нужно брать trunk из SVN/git и собирать самому — wiki.lazarus.freepascal.org/Installing_Lazarus/ru (именно /ru — она почему-то поадекватней)
                                                  0
                                                  Вот, кстати, их шаблонизатором я почти не пользовался, писал свой со StringReplace.
                                                  А что не так с Лазарусом? Одна только фича с CodeTemplates по Ctrl-J чего стоит
                                                0
                                                Интересно было бы увидеть результаты тестов под нагрузкой хотя бы с десяток запросов в секунду. Кеширования не заметил в коде.

                                                Когда-то тоже пилил на Delphi, но попробовав JS, PHP и Python, не понимаю почему Паскалевская грамматика застряла в прошлом веке. Документации толком нет. С примерами тоже все грустно.
                                                И при всех недостатках скриптовых языков, на написание того же самого функционала и на его поддержку нужно гораздо меньше времени.
                                                  +1
                                                  Если что, мой коммент выше не ради холивара, а просто сожаление об отличном когда-то инструменте, который не вписался в современные реалии.
                                                    0

                                                    Imho с грамматикой проблем нет. Основных проблем на мой взгляд две:


                                                    • Долгое время не было бесплатного инструмента, тогда как C++, Java, Nodejs, Python — всё бесплатно.
                                                    • Долгое время была фактически монополия на язык, который был железобетонно связан с библиотеками. Получается закрытая проприетарная экосистема, которая пусть и хороша как коммерческое решение, но долгосрочно с ней связываться стрёмно: мало ли что… С развитием FPC/Lazarus стало менее стрёмно.
                                                      –2
                                                      Я опечатался в своем комменте — имел ввиду синтаксис языка, конечно же. Он очень многословный, и требует большого количества ненужных символов. Тот же Java у которого строгая типизация, но гораздо более лаконичный.

                                                      Насколько я помню — платным была только IDE, которая по удобству тогда была просто революционной. Бесплатных IDE с подобным функционалом для других языков на то время (1995-2005) я просто не помню. Ну разве что Eclipse для Java.

                                                      А Lazarus действительно хорош (для своего круга задач), только не понимаю, почему вы назвали разработку на нем болью.
                                                        0

                                                        Синтаксис — это все фантики, за пару недель привыкаешь. Если рассматривать другие языки похожего назначения они все будут достаточно многословны. А вот проблемы с библиотеками куда существеннее.

                                                          0
                                                          Да, к синтаксису привыкаешь быстро, это не проблема. Проблема конечно в отсутствии нормально развитого сообщества и поддержки, а отсюда и проблемы с библиотеками, компонентами, документацией.
                                                          +1
                                                          Жава вообще существенно более многословна, что мало кому мешает, судя по распространенности.
                                                            0
                                                            Опять же не холивара ради, но дабы не быть голословным.

                                                            Минимальное консольное приложение Java
                                                            public class Application {
                                                                public void init() {
                                                                }
                                                            
                                                                public void run() {
                                                                }
                                                            
                                                                public static void main(String[] args) {
                                                                    Application application = new Application();
                                                                    application.init();
                                                                    application.run();
                                                                }
                                                            }


                                                            Минимальное консольное приложение FPC (Lazarus)
                                                            program Project1;
                                                            
                                                            uses
                                                              CustApp ;
                                                            
                                                            type
                                                            
                                                              TMyApplication = class(TCustomApplication)
                                                              protected
                                                                procedure DoRun; override;
                                                            
                                                              end;
                                                            
                                                            procedure TMyApplication.DoRun;
                                                            begin
                                                              Terminate;
                                                            end;
                                                            
                                                            var
                                                              Application: TMyApplication;
                                                            begin
                                                              Application:=TMyApplication.Create(nil);
                                                              Application.Run;
                                                              Application.Free;
                                                            end.         
                                                             


                                                            Спрашивается, почему декларация класса вынесена отдельно от имплементации в Delphi? Почему надо дублировать описания методов? Почему begin-end не заменить хотя бы на скобки?
                                                              +1

                                                              На самом деле минимальное консольное приложение сравнимо


                                                              program helloworld;
                                                              begin
                                                                WriteLn('Hello World!');
                                                              end.

                                                              class HelloWorld {
                                                                  public static void main(String[] args) {
                                                                      System.out.println("Hello World!");
                                                                  }
                                                              }

                                                              Что касается отдельного декларирования классов, функций, процедур — это особенность похожих языков, такая же как в С/С++. Зато скорость компиляции одна из самых высоких в своем классе.

                                                                0
                                                                • Во-первых джава тоже достаточно быстро собирается.
                                                                • Во-вторых в эпоху микросервисов ждать 1 секунду или 2 на полную пересборку приложения — не так уж критично? Особенно если собирать инкрементально, тогда на моей машине (при редактировании одного файла контроллера) сборка занимает 600мс.
                                                                • В-третьих даже если разница в пару секунд (а как мы помним, даже её нет), оно не стоит той когнитивной нагрузки, которую оно с собой несет. Всё же сейчас 2020 год, и трейдофы сильно отличаются от принятых в 1970.
                                                                  0

                                                                  Никто не говорит что это уберфича. Просто надо же хоть какие-то достоинства из этого факта вынести.

                                                                  0
                                                                  Нет, вопрос был в другом. Показать разницу в объеме синтаксиса при прочих равных условиях.
                                                                  +1

                                                                  Справедливости ради, минимальное консольное приложение выглядит так:


                                                                  {$APPTYPE CONSOLE}
                                                                  begin
                                                                  end.

                                                                  Многословность не есть недостаток, зачастую она повышает читаемость кода. Код гораздо чаще читают, чем пишут, поэтому читабельность важнее "писабельности", тем более что с последней хорошо помогает IDE — автодополнение, шаблоны.

                                                                    0
                                                                    почему декларация класса вынесена отдельно от имплементации в Delphi


                                                                    Возможно, вам бы понравился Оберон. А мне не понравился. Мусорка.

                                                                    Мне нравится вот так:

                                                                    package Ada.Real_Time
                                                                      with Nonblocking is
                                                                    
                                                                      type Time is private;
                                                                      Time_First : constant Time;
                                                                      Time_Last : constant Time;
                                                                      Time_Unit : constant := implementation-defined-real-number;
                                                                    
                                                                      type Time_Span is private;
                                                                      Time_Span_First : constant Time_Span;
                                                                      Time_Span_Last : constant Time_Span;
                                                                      Time_Span_Zero : constant Time_Span;
                                                                      Time_Span_Unit : constant Time_Span;
                                                                    
                                                                      Tick : constant Time_Span;
                                                                      function Clock return Time;
                                                                    
                                                                      function "+" (Left : Time; Right : Time_Span) return Time;
                                                                      function "+" (Left : Time_Span; Right : Time) return Time;
                                                                      function "-" (Left : Time; Right : Time_Span) return Time;
                                                                      function "-" (Left : Time; Right : Time) return Time_Span;


                                                                    То есть, вот есть Time и Time_Span. Если к Time прибавить Time_Span, получим Time. Time можно получить у функции Clock, а Time_Span можно получить как разность двух Time. Самая суть выражается, читать одно удовольствие. А детали выносятся в «примечания» (private).

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

                                                                    Вот аналог на Delphi.

                                                                    unit System.Diagnostics;
                                                                    
                                                                    interface
                                                                    {$HPPEMIT LEGACYHPP}
                                                                    
                                                                    uses System.Classes, System.TimeSpan;
                                                                    
                                                                    type
                                                                      TStopwatch = record
                                                                      strict private
                                                                        class var FFrequency: Int64;
                                                                        class var FIsHighResolution: Boolean;
                                                                        class var TickFrequency: Double;
                                                                      strict private
                                                                        FElapsed: Int64;
                                                                        FRunning: Boolean;
                                                                        FStartTimeStamp: Int64;
                                                                        function GetElapsed: TTimeSpan;
                                                                        function GetElapsedDateTimeTicks: Int64;
                                                                        function GetElapsedMilliseconds: Int64;
                                                                        function GetElapsedTicks: Int64;
                                                                        class procedure InitStopwatchType; static;
                                                                      public
                                                                        class function Create: TStopwatch; static;
                                                                        class function GetTimeStamp: Int64; static;
                                                                        procedure Reset;
                                                                        procedure Start;
                                                                        class function StartNew: TStopwatch; static;
                                                                        procedure Stop;
                                                                        property Elapsed: TTimeSpan read GetElapsed;
                                                                        property ElapsedMilliseconds: Int64 read GetElapsedMilliseconds;
                                                                        property ElapsedTicks: Int64 read GetElapsedTicks;
                                                                        class property Frequency: Int64 read FFrequency;
                                                                        class property IsHighResolution: Boolean read FIsHighResolution;
                                                                        property IsRunning: Boolean read FRunning;
                                                                      end;
                                                                    
                                                                    implementation
                                                                    


                                                                    Ну что, приятно такое читать? А со встроенными телами методов ещё больший кошмар.
                                                            0

                                                            Стресс-тест: 20 запросов в секунду в течение 20 секунд.
                                                            Домашняя страница (самая тяжелая):

                                                              0
                                                              Спасибо за графики. Да, начальные 100 мс на генерацию/отдачу вроде как хорошо. Потом понятно будет лагать. Но если прикрутить кеширование, все должно быть веселее.

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

                                                                Не упадёт — всё везде завёрнуто в try/except. Ну и есть же способы следить за процессом и запускать его в случае падения.
                                                                Перезапуск при обновлении — да, на 2-3 секунды сайт отключается. При большом желании можно повозиться чтобы этого избежать.

                                                                  +2
                                                                  Ну да, есть варианты. Однако сюда еще можно добавить memory leaks в компонентах и коде. В результате чего нужно регулярно перезапускать процесс. В целом все это не критично, но держит в напряге. В случае со скриптовыми языками проще. Отработал скрипт, клиенту отдал содержимое и умер.
                                                                  Я как раз на Лазарусе пытаюсь скрестить мощь Питона и удобство IDE. Интересный должен быть гибрид.
                                                                  А вообще мне ваш подход нравится, пока другие спорят про умер ли Delphi, вы просто на нем делаете новые продукты. Искренне желаю вам удачи!
                                                                    +1

                                                                    Спасибо!
                                                                    Насчёт memory leaks и падений: у меня там запущено еще 2 сервера старых игр, написанных на Delphi, которые уже года 3-4 никто не трогал. Кроме рестартов, связанных с обновлением системы (примерно раз в полгода), они не перезапускались. И вот они работают, люди играют — ни одного падения за эти годы, и память не течет. Конечно, так получилось не сразу, но постепенно я пришел к простому выводу: если не создавать объекты, не выделять явно память, а использовать лишь managed-типы, то и течь нечему :) Включенный Range Check защищает от выходов за пределы массивов, тем самым предотвращая порчу памяти. А повсеместные блоки try/except не дают мелким проблемам перерасти в крупные.


                                                                    Вероятно в ближайшее время на Patreon'е будет достигнута следующая цель: тогда опубликую код сервера игры и напишу новую статью о его устройстве.

                                                                  +1
                                                                  Всего один процесс, и если какой-то поток словит ошибку, все приложение упадет.
                                                                  Это не так. Потоки можно вполне перезапускать и без try/except (это как раз таки скорее вредно). По опыту разработки серверных приложений с сотнями потоков на Delphi).
                                                                  Однако сюда еще можно добавить memory leaks в компонентах и коде. В результате чего нужно регулярно перезапускать процесс. В целом все это не критично, но держит в напряге. В случае со скриптовыми языками проще. Отработал скрипт, клиенту отдал содержимое и умер.
                                                                  Лики довольно просто чистятся — есть как минимум штук 5 инструментов для Delphi, которые прямо строчку кода могут указать где случилась утечка. Ничто не мешает, и Делфи приложения так же как скрипты: запускать — забирать результат. Но, как правило, это непрактично, так не делают.
                                                                  Вообще — наших веб-серверов на Delphi по стране стоят сотни, работают круглосуточно месяцами и годами, достаточно нагруженные и ответственные приложения (медицина). В том числе, бывает, смотрят и в интернет. Пока не заломали ни один (тьфу * 3).
                                                                  Но, конечно, так как автор, мы не пишем :) (по поводу sql инжекции).
                                                                    0
                                                                    Как самообразовательный проект может быть полезным. Как продакшн решение явно нет.

                                                                    Выложите код, напишите статью о том, как пишете вы — будет интересно посмотреть! :)

                                                                0

                                                                Вообще результат сильно зависит от того, как написана реализация конкретной страницы. Можно запросто обрабатывать и тысячи запросов в секунду, если не делать в каждом запросе десятки обращений к БД, а использовать только данные в памяти.

                                                                  0

                                                                  Другой тест — на 150 клиентов, тут уже видно, что некое равновесие наступает при нагрузке в ~45 запросов в секунду, сайт при этом уже тормозит:

                                                                  Судя по логам, worker тратит на выполнение запроса 20-100 мс, в среднем примерно 40 мс. Запросы сложились в очередь — отсюда большое время ожидания.

                                                                0
                                                                Почему нет, если автору так было удобно. Но что будет делать с этим счастьем другой web-разработчик, пришедший в помощь или на замену? Боюсь даже представить его удивление. Если серьезно, то лучше брать стандартные решения с большим community и большим количеством плагинов.
                                                                  +2
                                                                  Если другой «web-разработчик» профессионал, то совершенно наплевать написан код на Golang, Node.js, Pascal или C/C++ для него просто будет новый интересный опыт. Более того возможно он получит новые знания, а относительно удивления, так это скорее возникнет у типового сайтоклепа возникнет. Сообщество с плагинами возникает при популярности. Другое дело, что на мой взгляд разработчику нужно было бы сначала выделить библиотеки вроде libscgi и подобные для переиспользования (простите я уже паскаль почти забыл — и не помню модули там или библиотеки).
                                                                    0
                                                                    Вы ошибаетесь. Профессионал это когда знает тонкости языка а не когда скачет по всем языкам одновременно. Это новички обычно страдают «я пишу на всех языках» не понимая что писать в с-like стиле это не программирование. Иначе после таких вот «профессионалов» приходится разгребать wtf в коде. То в ларавел проекте вместо встроенных обьектов работает с прямым sql запросами и глобальными обьектами запросов. То в typescripte не разобравшись пишет какую-то муть. То вместо правки скрипта сборщика пишет изменения прямо в результирующие js,css файлы.

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

                                                                    Как самообразовательный проект может быть полезным. Как продакшн решение явно нет.
                                                                      0
                                                                      Любой продакшн же с чего-то начинался
                                                                        0
                                                                        Как самообразовательный проект может быть полезным. Как продакшн решение явно нет.

                                                                        Тем не менее, сайт в продакшене, сервер игры — тоже, как и сервера еще 3-х игр. В продакшене с 2004-го (один правда уже закрылся).

                                                                          +1
                                                                          А теперь представьте сколько времени вы бы сэкономили. начни писать сайты на каком-то подходящем веб фреймворке. Огромная куча ошибок просто бы не возникла. В этом то и смысл использования наиболее подходящего инструмента. Можно гвозди и граблями забить но зачем если есть молоток.
                                                                            +2
                                                                            Огромная куча ошибок просто бы не возникла.

                                                                            А где можно посмотреть на эту кучу? И вообще, откуда вы решили что эта куча существует?

                                                                              +1

                                                                              Из опыта. Или вы думаете, у автора с первого раза все получилось и работало без ошибок и исправлений? Чем больше кода написано вручную, тем больше возможных ошибок и исправлений.


                                                                              Как думаете, где проще совершить ошибку? Здесь


                                                                              db.Query('UPDATE profiles SET notify="%s" WHERE id=%d',[profile.id,profile.notificationMode]);

                                                                              или здесь?


                                                                              profile.save();
                                                                                0

                                                                                А profile.save(); это нам наверное господь спустил с небес? Потихоньку подключается по ночам к github и пилит веб фреймворки?


                                                                                Нет – там тоже какой нибудь update profiles set... точно так же возможно написанный криво и уязвимо человеком. Но закопанный глубоко в сорсы в которыми вы никогда не заглянете. И кроме разработчики и искатели 0-day никто и не заглядывает.

                                                                                  0
                                                                                  Нет – там тоже какой нибудь update profiles set

                                                                                  Да, там именно update, и именно поэтому его надо использовать. Потому что он там уже написан и проверен, и вам не надо его писать самому. Только там не update profiles, а что-то вроде этого:


                                                                                  $primaryKeyField = $this->getPrimaryKey();
                                                                                  $values = $this->getFieldValues();
                                                                                  $sql = "update " . $this->table
                                                                                      . " set " . implode(' = ?, ', array_keys($values)) . " = ?"
                                                                                      . " where " . $primaryKeyField  . ' = ' . $values[$primaryKeyField];
                                                                                  $this->db->query($sql, $values);

                                                                                  и работает оно не только для profiles, а вообще для любых сущностей в проекте. И для них вам тоже не надо это писать самому.


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

                                                                                  +1

                                                                                  К сожалению, чудес не бывает: если нужна определенная логика — её нужно где-то написать. За исключением фантастического случая, когда готовое решение реализует на 100% то, что нужно. Вопрос лишь в том, что выгодней: допиливать чужое решение под свои условия, или реализовать своё. Выбор не всегда очевиден.

                                                                                    +1
                                                                                    если нужна определенная логика — её нужно где-то написать

                                                                                    Да. И зачем вам писать логику генерации SQL-запроса, которая уже написана?


                                                                                    Вопрос лишь в том, что выгодней: допиливать чужое решение под свои условия, или реализовать своё.

                                                                                    Фреймворки не допиливаются, фреймворки используются.

                                                                                      +2

                                                                                      В логике генерации запроса есть смысл, если есть множество однотипных запросов. Например, у меня есть много однотипных SELECT'ов — для них написаны обобщённые методы. А если запрос уникальный или их пара штук, то замена их на генератор выглядит как создание избыточного уровня абстракции. Это снижает понятность кода: когда видишь "UPDATE xxx WHERE yyy" — сразу понятно что это и как работает, потому что это SQL. А когда видишь this->update('xxx','yyy') — уже не очень понятно, потому что это придуманный кем-то интерфейс, у которого неизвестно что под капотом.


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

                                                                                        0
                                                                                        this->update('xxx','yyy')

                                                                                        Я же выше привел пример, там не this->update('xxx','yyy'), а profile->save(). Это не замена одного update на другой. Кроме того, в первом примере у меня намеренная ошибка, на которую никто не обратил внимания. Во втором примере такую ошибку в принципе нельзя допустить.

                                                                                      +1
                                                                                      Вопрос лишь в том, что выгодней: допиливать чужое решение под свои условия, или реализовать своё

                                                                                      Добавлю, что вы неправильно оцениваете масштабы. В данном случае такого вопроса нет. Вам несколько человек говорит про фреймворки, потому что то своё, которое вы реализовывали, в 90% функциональности ничем не отличается от чужого. Сколько времени вы разбирались со спецификацией CGI, неделю, две? А можно было в это время разбираться с PHP. FastCGI сервер там уже есть готовый.


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

                                                                                        0

                                                                                        Описание SCGI в вики занимает страницу текста, чтобы с ней разобраться, достаточно 10 минут. Час-полтора — написать реализацию. После написания и отладки эту инфу можно навсегда выбросить из головы.


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


                                                                                        Что касается PHP, то я его в принципе не рассматривал из-за его репутации. Может быть в современном PHP всё не так, как было раньше, но в памяти отложилось, что с PHP лучше не связываться, т.к. на каждом шагу — то выстрел в ногу, то уязвимость.


                                                                                        В принципе любой интерпретируемый язык, в котором есть eval() — это пороховая бочка.

                                                                                          0
                                                                                          Добавлю, что вы неправильно оцениваете масштабы.

                                                                                          Добавлю, что на фоне общего времени, потраченного на создание сайта, время на разработку этого модуля SCGI — это просто капля в море. Основное время занимают создание макета, нарезка HTML, написание кода на JS и кода функционала бэкенда, локализация, тестирование и т.д.

                                                                                            +1
                                                                                            это придуманный кем-то интерфейс, у которого неизвестно что под капотом

                                                                                            Почему "this->update" это "интерфейс, у которого неизвестно что под капотом", а "mysql_real_query" это не такой интерфейс? И то и то это сторонний код, и на оба из них есть документация, которую надо изучить, чтобы узнать как их использовать.


                                                                                            А что касается фреймворков, которые не допиливают: наверно их бы просто не было в таком количестве, если бы их создатели

                                                                                            Так мы не говорим про создание фреймворка, мы говорим про его использование. Вы в своем проекте фреймворк не допиливаете, а используете как есть.


                                                                                            Час-полтора — написать реализацию. После написания и отладки

                                                                                            Ну а можно не писать и не отлаживать, а вместо этого заняться логикой самого сайта. Тем более вы же simple написали, а на полную реализацию ушло бы больше времени.


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

                                                                                            Для изучения PHP после Delphi/C++ не надо много времени. Функции запоминать вообще мало смысла, в PHP они одни, в JavaScript другие, в Delphi третьи. Достаточно поиска в интернете и документации.


                                                                                            Что касается PHP, то я его в принципе не рассматривал из-за его репутации.

                                                                                            А уж у Delphi-то репутация на высоте)


                                                                                            В принципе любой интерпретируемый язык, в котором есть eval() — это пороховая бочка

                                                                                            А вас кто-то заставляет его использовать?) В JS тоже есть eval, вы же этот язык используете, и ничего.


                                                                                            Добавлю, что на фоне общего времени, потраченного на создание сайта

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

                                                                                            +1
                                                                                            По сравнению с тем, что есть в Delphi, современный PHP это шаг вперед.
                                                                                            Ого, соревнование по остроте каменных топоров накаляется! =)
                                                                                              0

                                                                                              Для сайтов PHP вполне себе нормальный топор)

                                                                                      0

                                                                                      Дейстивтельно, какая куча ошибок? Как-раз таки куча ошибок возникла бы начни я писать всё это на каком-нибудь PHP-фреймворке. Из-за незнания особенностей языка, фреймворка, незнакомых и непривычных инструментов разработки и отладки.


                                                                                      Собственно, достаточно взглянуть на JS-код этого же сайта, чтобы понять, как мог бы выглядеть код сайта на PHP :-) ПРи том, что JS для меня не такой уж незнакомый, ведь я использую его для фронтенда сайтов достаточно давно.

                                                                                        +3
                                                                                        посмотрел на форму логина у вас там нет anti-CSRF token. Для чего это надо Разумеется это не сложно написать на паскале но это уже есть готовое в веб фреймворках. Экономите свое и работодателя время.
                                                                                          +1
                                                                                          Собственно, достаточно взглянуть на JS-код этого же сайта, чтобы понять, как мог бы выглядеть код сайта на PHP

                                                                                          А вот для этого как раз и нужны фреймворки. Они вас ограничивают, показывают как надо делать правильно стандартные вещи.

                                                                                      0
                                                                                      Вы ошибаетесь. Профессионал это когда знает тонкости языка а не когда скачет по всем языкам одновременно.

                                                                                      С чего бы это? Вот мой личный пример: я на сишарпе в основном пишу, фулл бекенд разработчик уже 4 года, веб не трогал очень давно, еще со времен jquery-UI. И вот понадобилось мне пдфку рисовать. Смотрю библиотеки на этом моём сишарпе — а они все платные, с ценами сравнимыми с годовым бюджетом небольшого города


                                                                                      img


                                                                                      Пошел гуглить, нашел PDFKit — бесплатную простую либу на жс. Скачал ноду, поставил тайпскрипт, запилил сервис, настроил сваггер (опять же с помощью гугла). В итоге за пару дней задача решена, и дешевле чем за 70к$.


                                                                                      typescript-eslint — 0 варнингов выдает, с кодом ощущения что он плохо написан и не масштабируется нет.


                                                                                      Какой ваш совет "нескакателя по языкам" в такой ситуации?

                                                                                        +1
                                                                                        У вас какой то странный гугл раз вы не смогли найти бесплатную библиотеку для рисования пдф на шарпе.
                                                                                          0

                                                                                          Ну покажите пару примеров. Сразу скажу, что нужно именно рисовать, поэтому всякие wkhtmltopdf не подходят. Syncfusion платный, ironpdf не умеет что нужно, PdfiumLight имеет нативные зависимости,…


                                                                                          Вот 3 первых строчки гугла. Дальше всё то же самое. Больше всего порадовала библиотека libharu, которая вообще даже мсбилд не использует, а для сборки нужно руками в csc файлы совать.




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

                                                                                            0

                                                                                            Всё еще надеюсь получить пример библиотеки из "вашего" гугла.

                                                                                            +1
                                                                                            Ну вот в сишарпе вас возможно можно назвать профессионалом. А так вы просто решали задачу оптимальным способом. Я больше про то когда берутся за любые проекты по типу «умею писать на одном языке значит умею на всех.»
                                                                                              0
                                                                                              PDF вывод есть в Cairo, а привязки к Cairo стараниями Мигель де Каза (GNOME) я бы ожидал найти в Mono
                                                                                                0

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


                                                                                                А тайпскрипт очень привычен C#-разработчикам, поэтому я решил что небольшая потеря в том, чтобы сделать на ноде (которая уже у всех стоит, т.к. требуется для запуска фронтенда).

                                                                                              0
                                                                                              Профессионал это когда знает тонкости языка а не когда скачет по всем языкам одновременно.

                                                                                              Профессионал — это когда есть результат: задачи закрыты, оплата получена.

                                                                                                0
                                                                                                то есть студенты с фриланс сайта это профессионалы?
                                                                                                  +1
                                                                                                  Точнее, получена достаточная оплата [регулярно], чтобы этим жить =)
                                                                                                  0
                                                                                                  > Профессионал это когда знает тонкости языка

                                                                                                  Это профессионал по тонкостям языка и такой профессионал востребован в области разработки языков программирования скорее всего, а с точки зрения бизнеса он только вредит — поднимая планку требований к программистам в команде (делая стоимость часа команды суммарно выше).

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

                                                                                                  Чаще всего это герои одиночки и с ними крайне сложно работать коллегам.

                                                                                                  > То в ларавел проекте вместо встроенных обьектов работает с прямым sql запросами
                                                                                                  и глобальными обьектами запросов

                                                                                                  А причем тут языки программирования? Это культура программирования и желание переиспользовать кода фреймворка и к знанию языков программирвоания отношения не имеет. Более того я могу скзаать, что в какой-то ситуации это может быть оправдано особенно если решение MVP и сроки сдачи очень небольшие, то можно и вовсе ограничиться интерфейсом на jQuery.

                                                                                                  > То вместо правки скрипта сборщика пишет

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

                                                                                                  > Вот автора поста как раз можно упрекнуть в недостатке любопытства

                                                                                                  А почему Вы считаете, что Ваша ценность «любопытство» (прим. любопытство к уже готовым продуктам) должна быть у автора поста? Это разновидность экономии денег заказчика за счет использования чужого кода и многих разработчиков заставляют учитывать это в разработке, что в каждом конкретном случае приводит как к ряду достоинств так и ряду недостатков.

                                                                                                  > Вместо того чтоб взять наиболее подходящий инструмент для веба он костылит свое решение

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

                                                                                                  > на мертвом паскале

                                                                                                  В смысле мертвый? Основы синтаксиса языка можно освоить за несколько часов. Интерпретатор FPC работает под все популярные платформы (хотя я не совсем понял ситуацию с x86_64). Исходный код открыт и можно дописать необходимый функционал в RTL при острой необходимости. Рынок труда Pascal сегодня в основном конечно жив благодаря банковским решениям, но все равно специалистов на рынке найти можно. А Вы скорее говорите про модные языки вроде: Ruby, JavaScript и PHP говорите, так как любой школьник в любом форуме найдет решение, так не думаю, что это как раз хорошо. Это огромная проблема, так как происходит переход в ИТ людей далеких от программирования (т.е. без технического образования). С другой стороны они тоже нужны типовые сайты делать.

                                                                                                  > в итоге воюет с собственным поделием

                                                                                                  По подробнее с чем у него проблема. Я возможно пропустил.

                                                                                                  > Как продакшн решение явно нет.

                                                                                                  Так основная проблема это низкая популярность языка программироания Pascal? Высокая стоимость специалистов? В чем проблема для бизнеса здесь?
                                                                                                    +1
                                                                                                    приложение на паскале в вебе(в любом не популярном для паскале направлении) обходится дороже для бизнеса. Тут проблема найти спецов которые напишут это и проблема найти замену уволившимся. Так как их мало соотвтственно денег платить придется больше. Так же на разработку решения уйдет больше времени а значит и больше денег в итоге. Поэтому бизнес строит сайты на веб фреймворках а не на паскале как Cooler2 или на ассемблере как johnfound. как хобби эти проекты вполнее имеют право на жизнь как бизнес решения явно нет.
                                                                                                      0

                                                                                                      Ну, найти спецов которые пишут на ассемблере, конечно труднее. Но я бы не сказал что на паскале нельзя найти хороших программистов. Тем более в России где традиции Паскал/Делфи все еще не исчезли совсем.


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

                                                                                                        +1

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

                                                                                                      +2

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

                                                                                                      0

                                                                                                      Модули. Именно это я и сделал — выделил модуль SCGI для самостоятельного использования.

                                                                                                        0
                                                                                                        Так это я видимо пропустил. А можно какой-то пример с «Hello, world» на Pascal с использованием вашего модуля SCGI. Кстати чем установить этот модуль есть ли в Pascal какой-то менеджер пакетов? Возможно есть смысл сделать какой-то фреймворк вроде популярных и упомянутых тут вроде Lavarel. Я конечно понимаю, что автору это все не очень нужно, но было бы полезно на случай если кто-то потом пойдет по стопам — не прокладывать же лыжню каждый раз.
                                                                                                          0

                                                                                                          Так я в статье как-раз и привел пример "Hello World" на SCGI.


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


                                                                                                          Сейчас в Delphi есть GetIt Package Manager, но там ловить в общем-то нечего — все классные библиотеки нужно искать на сайтах.

                                                                                                    +1

                                                                                                    Perl, CGI, Pascal… Сколько ж лет с тех времён прошло, 20 так уж точно. Прям машина времени ) Интересно жив ли ещё mod_perl апачевский.

                                                                                                      0

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

                                                                                                      +2
                                                                                                      Люди нажимали F5, чем ещё больше усугубляли проблему. Оказалось, что даже 4-5 запросов в секунду к CGI-скрипту, запускаемому в виде отдельного Perl-процесса, ощутимо замедляют сервер, а >10 запросов в секунду делают его совсем недоступным.


                                                                                                      1. Нет смысла писать на голом CGI и Perl, когда есть uWSGI Perl.
                                                                                                      2. Можно кешировать таблицу веб-сервером (nginx)
                                                                                                        0
                                                                                                        1. Так есть и FastCGI и SCGI. Но идея писать, а тем более дебажить такое на Perl меня весьма пугала. Хотя вероятно для опытного Perl-разработчика это норм.


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


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


                                                                                                          Простите, я больше сисадмин, чем программист. Но зачем мучаться и делать статический контент самому, когда кеш в вебсервере — 1 строка конфига?

                                                                                                          И да. uWSGI точно выдержали бы ту нагрузку, от которой падал CGI.
                                                                                                            0

                                                                                                            В конфиге nginx вроде можно указать, что кеш ответа бекенда будет валиден, допустим, 1 секунду. Этого хватит, чтобы выдержать любой наплыв посетителей.

                                                                                                              0

                                                                                                              Кэш валиден только для того конкретного пользователя, для которого этот ответ сформирован.


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

                                                                                                                0

                                                                                                                В IIS'е давно была реализована штука под название donut caching — это когда у вас статический контент кэшируется, а динамический туда подсовывается. У вас наверное все же не 100% различающихся страниц для каждого пользователя?


                                                                                                                Уверен, в nginx есть похожий механизм.

                                                                                                              0

                                                                                                              Да полноте, на FastCGI обычный скрипт даже в те времена переписывается банальным оборачиванием в


                                                                                                              while (my $cgi = CGI::Fast)

                                                                                                              Проблемы с отладкой совершенно непонятны — какая разница с другими языками?

                                                                                                            +3
                                                                                                            В каком-то смысле, это меня впечатлет. Игры, которыми кто-то пользуется; сайты, на которые кто-то заходит; на форуме жизнь теплится; патроны на патреоне (внезапно!). Всё это на лютых велосипедах и полумёртвом языке. И выглядит криво и косо и снаружи и внутри, но работает и пилится годами! Это настолько удивительно и непонятно для меня…

                                                                                                            Я могу неделями мучаться мыслями о том, что ну вот это технология вроде более популярна, а вот этот язык вроде лучше будет использовать вот в этом сценарии, а вот так писать как-то неправильно, а вот этот кусок кода какой-то не такой. И при этом у меня нет ни одного законченого pet projec'a (что логично). Как вам это удаётя? У вас настолько стабильная самооценка? Если да, то за счёт чего? Программирование — ваша основная работа?

                                                                                                            Извините за такой лютый офтоп, но мне правда очень интересно узнать.
                                                                                                                +1
                                                                                                                Всегда считал, что умение сомневаться в себе — основное отличие разумного человека от болвана. Видимо, нужно ещё уметь НЕ сомневаться в себе, когда это может помешать достижению цели [в голове, правда, сразу всплывает вопрос «а стоит ли эта цель того, чтобы её достигать?» :) ]
                                                                                                                Спасибо за ответ.
                                                                                                              +1
                                                                                                              function UpdateAccount
                                                                                                              
                                                                                                                    db.Query('UPDATE profiles SET notify="%s" WHERE id=%d',[profile.notificationMode,profile.id]);
                                                                                                              
                                                                                                                    if db.lastError='' then result:='OK'
                                                                                                                    else result:='Internal error';

                                                                                                              Результат конечно занимательный, но так уже даже на PHP не пишут)
                                                                                                              Серьезно, со знаниями Delphi разобраться в PHP можно за пару недель. Но на чистом PHP тоже писать не надо, лучше использовать фреймворк. Там уже предусмотрены защиты от основных уязвимостей и работа с базой. Для начинающего подойдет Yii 2, он простой и у него неплохая документация.

                                                                                                                0

                                                                                                                А кстати, какие уязвимости есть конкретно в этом коде?

                                                                                                                  +1

                                                                                                                  Ну я скорее не про уязвимости говорил, а про архитектуру и поддерживаемость.

                                                                                                                  0

                                                                                                                  Тут явно параметризованный запрос, SQL-injection не пройдет. (Если, конечно, внутри Query не sprintf)

                                                                                                                  +1
                                                                                                                  Да вашу-ж, ладно этот трамвай из хлеба (всякое бывает)…

                                                                                                                  Но форматирование кода в примерах это ад какой-то. Пробелы Вам кто запретил использовать?
                                                                                                                    +1
                                                                                                                    Респект разработчику системы и уважение за смелость. Первая мысль которая у меня возникла, что Pascal использует всегда стековую память, а следовательно производительность сайта будет максимальной из всех возможных (т.е. возможно быстрее реализаций на C/C++ с хипом), но с другой стороны непонятно, что там с потоками, асинхронной обработкой запросов и реализацией уймы вещей вроде: списков, словарей, соединений с базой данных и т.д. В целом респект и удачи в дальнейших разработках и конечно шаблоны нужно загрузить и закешировать при запуске прилоежния.
                                                                                                                    P.S. В целом хотел бы попробовать разработать что-то на FPC для сайта, но сотанавливает какая-то темнота во всех WSGI, uWSGI, SCGI и прочих протоколах, а орагнизовать парсер HTTP на Pascal на мой взгляд задача сложная (дорогая). Так что было бы интересно увидеть библиотеки или даже какой-то форум по разработке Web решений на Pascal.
                                                                                                                    P.P.S. Удачи и успешного движения вперед.
                                                                                                                      +3
                                                                                                                      Delphi/FPC хорошо продвинулся для написания веба (особенно фронта, бэк уже давно хорошо работал) в последние годы. Вот несколько ссылок:
                                                                                                                      Список множества Web фреймворков Delphi:
                                                                                                                      community.idera.com/developer-tools/b/blog/posts/evaluating-web-development-frameworks-for-delphi
                                                                                                                      От себя отмечу:
                                                                                                                      unigui.com
                                                                                                                      www.tmssoftware.com/site/tmswebcore.asp
                                                                                                                      С первым работаю плотно сам. О втором хорошие отзывы. Но, правда, оба платные.
                                                                                                                      FPC/Lazarus:
                                                                                                                      wiki.lazarus.freepascal.org
                                                                                                                      forum.lazarus.freepascal.org/index.php?topic=47999.0
                                                                                                                      Delphi Community Edition, бесплатная версия (с условиями):
                                                                                                                      www.embarcadero.com/ru/products/delphi/starter
                                                                                                                      Lazrus/FPC весь бесплатный. Проще всего его устанавливать с помощью fpcupdeluxe:
                                                                                                                      wiki.freepascal.org/fpcupdeluxe
                                                                                                                      Поддерживаемый список бесплатных компонент и библиотек:
                                                                                                                      github.com/Fr0sT-Brutal/awesome-pascal
                                                                                                                      Платных живых пакетов можно найти намного больше, по вебу конкретно — по ссылкам выше.
                                                                                                                      но с другой стороны непонятно, что там с потоками, асинхронной обработкой запросов и реализацией уймы вещей вроде: списков, словарей, соединений с базой данных и т.д.
                                                                                                                      Всё конечно же со всем этим хорошо, больше проблема выбора чем наличия инструментов.
                                                                                                                      Можете с вопросами заходить поинтересоваться на телеграмм каналы (живые и весьма активные, не только веб):
                                                                                                                      t.me/Delphi_Lazarus
                                                                                                                      t.me/DelphiCommunity
                                                                                                                        0
                                                                                                                        непонятно, что там с потоками, асинхронной обработкой запросов и реализацией уймы вещей вроде: списков, словарей, соединений с базой данных и т.д.

                                                                                                                        Готовые решение есть в вышеупомянутом mORMot. Чтоб не заморачиваться с *SGI, разумно просто слушать порт, а впереди поставить тот-же nginx для удобного управления статикой, кешированием и т.п.

                                                                                                                          +1
                                                                                                                          Вот, Унигуй — готовое решение для фронта + бэка в одном пакете. Заморочек минимально. Бэк максимально реализован и скрыт в готовых пакетах. Фронт рисуется обычными формами. Готовых инструментов хватает (больше сотни компонент для десктопа и телефонов) + саппорт активно помогает на форуме. Вот результаты поиска картинок по их форуму, можно посмотреть вопросы и результаты, выкладывают иногда:
                                                                                                                          Картинки форума Унигуя
                                                                                                                            +1

                                                                                                                            А сайт Унигуя сделан на Унигуе? ;)

                                                                                                                              0

                                                                                                                              Все конечно хорошо, только привязка к Delphi, который сам по себе не дешев + минимум $400 за unigui

                                                                                                                                0

                                                                                                                                Community Edition бесплатный, а если доход >$5K, то можно и раскошелиться на лицензию. Я слышал много нытья от разных людей про дороговизну лицензии, но серьёзно — на фоне burn rate программиста это не такая уж значительная сумма. Хотя я, конечно, предпочёл бы чтобы он стоил дешевле. Тот же 3D Max стоит дороже, но им вовсю пользуются, несмотря на наличие бесплатного Blender'а.


                                                                                                                                У меня сайт и сами игры написаны вообще в Turbo Delphi Explorer, который бесплатный без ограничений по доходу.

                                                                                                                                  0
                                                                                                                                  А какой смысл (кроме случаев когда основной код платформы: игры) использовать эти инструменты? Я думаю, что можно найти уйму открытых реализаций для C/C++ и компиляторов gcc, clang, Visual Studio в составе SDK вроде можно получить без дополнительных затрат? Я и говорю, что с доступными библиотеками есть дифицит.
                                                                                                                                  0
                                                                                                                                  GNAT и GNOGA бесплатные
                                                                                                                              +3

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


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

                                                                                                                                0
                                                                                                                                и аллокации в куче для всяких «динамических массивов» и прочего


                                                                                                                                Сейчас посмотрел ради интереса и действительно fpc_dynarray_setlength (rtl/inc/dynarr.inc) использует вызов getmem (подозреваю, что это аналог malloc), так что тоже хип.

                                                                                                                                Тогда с точки зрения производительности нет разницы использовать C/C++ или Pascal?
                                                                                                                                  0

                                                                                                                                  И то и то алгол, отличия только в синтаксисе по сути. Идеология за ними одна и та же, появились они с разницей в 2 года, ну и так далее. Как сишарп и джава — братья-близнецы. Разве что те еще и по синтаксису один в один. А вот если сравнить Java/F#, то получится очень похоже.

                                                                                                                                    +2
                                                                                                                                    В C++ ублюдочная модульность. Пространства имён с исходниками не связаны, кто угодно может подкладывать куда угодно.

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

                                                                                                                                      Ну инклюды это да, на любителя.

                                                                                                                                  0
                                                                                                                                  Строки на стеке — это Ада, но не Delphi
                                                                                                                                    0

                                                                                                                                    Строки на стеке — это где угодно. Я слышал в додо пицце их даже на сишарпе делали. А-ля


                                                                                                                                    struct String8
                                                                                                                                    {
                                                                                                                                        public char Char1 { get; set; }
                                                                                                                                        public char Char2 { get; set; }
                                                                                                                                        public char Char3 { get; set; }
                                                                                                                                        public char Char4 { get; set; }
                                                                                                                                        public char Char5 { get; set; }
                                                                                                                                        public char Char6 { get; set; }
                                                                                                                                        public char Char7 { get; set; }
                                                                                                                                        public char Char8 { get; set; }
                                                                                                                                    }

                                                                                                                                    Ну или более разумно (для общего случая):


                                                                                                                                    unsafe struct StackStirng 
                                                                                                                                    {
                                                                                                                                        public fixed char Value[8];
                                                                                                                                    }

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


                                                                                                                                    img

                                                                                                                                      0
                                                                                                                                      Я имел в виду: строки, размер которых известен динамически, но не статически, в языке Ада могут быть на стеке. Я имел в виду случай, когда выделяется не максимальный объём, а сколько надо.

                                                                                                                                      Да, в Расте строки делали по подобию адских
                                                                                                                                        0

                                                                                                                                        В расте тоже стековая строка будет фиксированного размера, см. smallvec или heapless.


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

                                                                                                                                          0
                                                                                                                                          EZ — внутри строки использовать alloca(). ну почти — в вызываемой функции стекфрейм то другой — т.е сначала выделили, потом вызвали что то
                                                                                                                                          {stackstring x; x += "added"} ->  
                                                                                                                                          { x.buf = alloca(x.len+5),  copy(oldbuf, newbuf)}
                                                                                                                                          да и с передачей таких параметров по ссылке проблема…
                                                                                                                                            0

                                                                                                                                            А если в стекфрейме нет столько места, то что делать?


                                                                                                                                            The alloca() function returns a pointer to the beginning of the allocated space. If the allocation causes stack overflow, program behavior is undefined.

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

                                                                                                                                              0
                                                                                                                                              Как всегда в таком случае, падать по переполнению стека.

                                                                                                                                              Впрочем, дефолтный размер стека уже давно не менее 1МБ (win), 10МБ (lin), так что на пару строчек должно хватить.

                                                                                                                                              Конечно, цикл вроде for i:=1 to 100000 do s := s + 'a' сломает такую систему
                                                                                                                                                0

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


                                                                                                                                                В любом случае остается вопрос — как эту строчку из функции вызывать? Потому что в сишарпе вон в примере выше я её могу вернуть — просто её содержимое будет скопировано в стекрейм вызывающей функции. А с этой штукой компилятор никак заранее не может узнать солько ему места резервировать под результат.

                                                                                                                                      +1

                                                                                                                                      В Pascal строка на стеке называется ShortString, может иметь длину до 255 символов.

                                                                                                                                    0

                                                                                                                                    Кстати, написать парсер (сервер) HTTP — задача не сложная и не дорогая даже без каких-либо библиотек. Протокол сложный в реализации на клиенте, а на сервере можно ограничиться весьма простой реализацией. У меня сервер игры как-раз работает как HTTP-сервер. А SCGI еще проще.

                                                                                                                                      +1

                                                                                                                                      HTTP относительно простой протокол, но он всё еще сложный, потому что начинаются приколы при попытки реализации:


                                                                                                                                      стриминга и пайплайнинга
                                                                                                                                      Keep-alive и бэкпрешура
                                                                                                                                      вебсокетов
                                                                                                                                      Прозрачной компрессии контента (br, gzip, deflate)
                                                                                                                                      Multipart стримов
                                                                                                                                      ССЛ


                                                                                                                                      И это я не говорю про корнер-кейсы, которые хттп разрешает (например, побить один файл на несколько мультипарт стримов).


                                                                                                                                      И это кстати не иезуитское знание, вполне реально словить sql injection атаку в общем случае.

                                                                                                                                    0
                                                                                                                                    Вот тут ещё движок блога сделали
                                                                                                                                      +1

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

                                                                                                                                        0
                                                                                                                                        Возникает уйма сложных мест при работе с современными диалектами Pascal. Когда в него притаскивают динамические списки и т.д. Тут уже нужно очень хорошо понимать, что происходит под капотом каждого вызова в противном случае получаем сплошное копирование памяти и как следствие потерю производительности.
                                                                                                                                          0
                                                                                                                                          Существуют определенные известные хорошие практики для избегания копирования. Есть несколько узких мест, их не так много. Новые версии библиотек постоянно чистят от лишних движений.
                                                                                                                                          –1
                                                                                                                                          А с чего бы ему не мочь?

                                                                                                                                          Другое дело, позор тем, кто для nginx выбрал не Аду или хотя бы Паскаль. Фу таким быть
                                                                                                                                          0

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


                                                                                                                                          Интересно было бы узнать на каком сервере крутится этот сайт. А также, какие-нибудь числа о производительности – например какое типичное время обработки запроса. (понятно, что это варьирует), какая СУБД использована и подобное.


                                                                                                                                          Ну, чтобы сравнить с моим наработкам на ассемблере.

                                                                                                                                            0

                                                                                                                                            Сервер: Xeon 3430@2.4GHz
                                                                                                                                            База: MySQL 5.1
                                                                                                                                            Типичное время обработки запроса к главной странице — 50 мс (12 SQL-запросов).
                                                                                                                                            В данном случае производительность упирается в БД, форматирование текста — это мизер. Если поставить задачу повысить производительность, то в первую очередь надо избавиться от лишних запросов к БД.

                                                                                                                                              0
                                                                                                                                              форматирование текста — это мизер

                                                                                                                                              Ну-у-у, я бы не сказал… У меня время получается вроде 50:50 запросы/текстообработка. Правда у меня БД SQLite — она может и побыстрее будет. Количество запросов сравнимое.


                                                                                                                                              А это физический сервер или VPS? И сколько ядер и RAM у него?

                                                                                                                                                +1

                                                                                                                                                Сервер физический, 4 ядра, 4GB RAM. Сайт работает с 2 worker threads, так что полностью загрузить процессор не может.

                                                                                                                                            +2
                                                                                                                                            Какой у вас интересный PHP получился.
                                                                                                                                              0
                                                                                                                                              Я тоже до того, как изучил PHP, делал сайты на Delphi. Но, вместе с Web-сервером, никаких CGI.

                                                                                                                                              По статье несколько вопросов.

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

                                                                                                                                              Про NodeJS. Напрасно вы так про JS. Я понимаю, конечно, когда есть неприязнь, например, к ФП. Но JS как сам ЯП ничем особым не выделяется, чтобы прямо совсем быть таким неприятным.

                                                                                                                                              Я бы и сам уже не делал ничего на JS. В двадцать первом веке есть Go. И даже Go медленно но верно сменяет поколение Rust. Но, опять же, я считаю, что бы эффективно программировать на Go и тем более на Rust, хороший большой опыт работы на NodeJS просто необходим. Это моё личное мнение. Был бы рад услышать обратное, если таковые программеры среди нас присутствуют.
                                                                                                                                                0

                                                                                                                                                Медленный скорее сам CGI, а не Perl (из-за создания процесса). Но даже в случае CGI, гораздо быстрее запустить скомпилированный бинарник, чем интерпретатор, который при запуске грузит либы (сотни файловых операций!) и парсит код. На этом фоне скорость выполнения собственно кода логики скрипта имеет мало значения.

                                                                                                                                                  0
                                                                                                                                                  Но даже в случае CGI, гораздо быстрее запустить скомпилированный бинарник, чем интерпретатор

                                                                                                                                                  perlcc поставляется вместе с perl. Но скомпилированный код запускается не на много быстрее скрипта. Та проблема требует кастомизации ядра ОС — настроить быстро можно, но на это уходит немного времени, так как это не универсальные настройки, а непосредственно под CGI.

                                                                                                                                              Only users with full accounts can post comments. Log in, please.