<душнила_mode_on>
KDE кроссплатформенный, так что формально можно тоже самое реализовать и в винде.
А даже если бы и не был кроссплатформенным, то wsl позволяет пробросить иксы наружу, где со стороны клиента (винды) достаточно установить что-то вроде VcXsrv, чтобы использовать абсолютно любое линуксовое приложение (включая плазму) одной командой в консоли.
</душнила_mode_on>
Возможно вы не поняли. Предметная область любой игры не ограничивается персистентным состоянием позиции игрока. Это всего лишь одна ~десятая всех задач.
Я вот по должности своей как раз разрабатываю один известный MMO шутер-лутер. И http (и grpc) для идемпотентных и стейтлесс запросов вполне себе занимает бОльшую часть всей предметной области, а то о чём вы говорите - лишь сессионная составляющая самого режима игры, которая частично может быть рассчитана и на клиенте в т.ч. в отличие от какой-нибудь операции "покупки" товара у "торговца".
Так что списывать технологию со счетов просто "потому что" не вижу смысла.
Медленный для чего? Ну вот, например, дефолтный ответ "самого медленного фреймворка в мире" (ака Laravel) внутри докера на винде - 8-10мс в режиме дебага. Этих 10мс не хватит чтоб получить информацию о профиле игрока? Получить список предметов? Получить информацию о точках спауна? Где именно эти 10мс сыграют значительную роль в нагрузке, когда один селект из базы может и в два, и в десять раз дольше работать?
Да вполне нормальный протокол для RPC. Клацаешь по кнопочке, с сервера по хттп грузанулись настройки персонажа, например и отобразилось окошко с ним Причем всё готовое уже есть: Сервер, лоадбалансер, дебаггеры, клиенты. Ну и логи потом дебажить приятнее, нежели какой-нибудь grpc
А в каких-то распространённых языках есть строгое требование к виду имён переменных?
Я ответил: Да, в каких-то языках есть строгое требование к виду имён переменных. Даже привёл пример современных языков, где такие ограничения есть, т.к. в зависимости от того как оно выглядит — меняет свою семантику и поведение.
Go допускает и camelCase, и PascalCase, и snake_case.
И вы хотите сказать, что вообще ничего не изменится, если все ExampleVariable заменить на exampleVariable? А вот судя по этой ссылочке на туториал, кажется, это совсем не так: https://go.dev/tour/basics/3
Про руби вы тоже ответили: Язык явно диктует как именовать переменные/константы и от этого самого именования полностью зависит поведение языка.
Ну как минимум в Go и Ruby. Только там не то что бы "компилятор упадёт"… Скажем так, он может упасть при определённых обстоятельствах, т.к. от именования зависит вообще всё.
Не, понятно что в большинстве случаев это всё фигня, но как бы есть Half-Life 2, есть фантазмофобия, есть фаллаут, сабнавтика, но мэн скай, хитман 3 и прочее. Да, это всё порты, а не эксклюзивы, но тоже вполне себе прикольно играется. Тот же HL2 я прошёл с удовольствием.
Кстати, если уж говорить про стим, то не совсем понятно как Apple будет совместим с ним. Поддерживает ли он OpenVR стандарт? Как подключить контроллеры? Ну и прочее… А то что-то мне кажется, что в текущем виде это не конкурентный продукт. Тем более за цену в 4 раза превышающую всё тоже самое, что уже есть.
Я пока не могу понять зачем нужны вообще эти очки и какую задачу они будут решать? В голову приходит только просто отговорки на тему "чтобы были" + "экосистема эппл". А никаких объективных причин тратить четверть миллиона рублей на то, что будет пылиться на полке — не могу придумать.
Не знаю как в Go, но в JS async/await не решит этот придуманный сценарий, так как доходя до await выполнение "приостанавливается" и дальше ждет, что вернет вызов.
Это не так. await лишь делегирует задачу "наверх", т.е. это другая форма записи yield. Фактически альтернатива выглядела бы так:
// JS
let response = await request('...');
// PHP
yield from $process = request('...');
$response = $process->getReturn();
// PHP (или так, если верхний обработчик
// умеет сам разворачивать вложенные
// генераторы и возвращать результат через ->send(...))
$response = yield request('...');
Что фактически может быть в PHP упрощено в сторону:
// PHP
$response = request('...');
// где внутренности request
while (!feof($stream)) {
$body .= fread($stream, 1024);
Fiber::getCurrent() && Fiber::suspend();
}
Ну можно вместо встроенного select просто проверить на eof и попытаться считать, если делать влоб.
С другой стороны в пыхе можно доустановить libev, libevent, ev или libuv, а там уже на выбор, хоть poll, хоть epoll, хоть kqueue, хоть devpoll, хоть evport, хоть ещё что. Накрайняк есть ffi и руками можно допилить нужное. Было бы желание.
Как объясняется на RisingStack, главная причина в его неблокирующемся вводе-выводе и эффективной обработке параллельных подключений
Осталось понять откуда в PHP внезапно проблемы с блокирующим io, когда обычная функция stream_set_blocking превращает любой io в неблокирующий. Хоть чтение с файловой системы, хоть сокеты, хоть что угодно...
При этом наличие файберов в PHP делает не то что ненужным аналог в JS из async/await, но и вообще ставит под сомнение их существование в природе, т.к. JS-ный аналог становится просто неудобным.
Мне кажется, подобное актуально, когда в языке нет строгой типизации (в первую очередь) и нет конструкций, обеспечивающих удобное взаимодествие с нуллами.
Например в Java, где любой объект может быть как инстансом, так и null, и язык на уровне типов не обеспечивает гарантии того, что объект является корректным инстансом. Поэтому, в Java намного практичнее было бы использовать подобные конструкции, т.к. они предоставляют безопасный инструмент для работы с nullable объектами.
Если говорить про PHP, то этот язык при работе с nullable-объектами более строгий и на уровне типов гарантирует то, что объект не является null. Поэтому и смысла меньше.
// class Example
public Some obj = null; // Java: OK
public Some $obj = null; // PHP: TypeError
Во-вторую очередь, операторы ?->, ?? и проч. позволяют удобно работать с nullable-объектами, поэтому смысла в подобных монадах становится ещё меньше. Например optional:
Можно собрать и статик, для этого прописывается --with-embed=static, например:
./configure --with-embed=static --disable-all
make
В результате вместо so/dll собирается a файл.
Потом этот файл линкуется (плюс 4 обязательных зависимости в ядре):
target_link_libraries(target_name PRIVATE path/to/result/libs/libphp.a
m # математика
dl # это для функций подключения либ
resolv # это не помню, как и утилс
util
)
Если требуется какая-то доп.зависимость, то это просто расширяется, например:
sudo apt install libffi-dev
./configure --with-embed=static --disable-all --with-ffi
make
target_link_libraries(target_name PRIVATE
# список обязательных либ
ffi
)
Но у этого есть и обратная сторона, если собрать что-то более менее стандартное (например с расширениями:, Core, date, libxml, pcre, sqlite3, ctype, curl, dom, FFI, fileinfo, filter, hash, iconv, json, mbstring, standard, SPL, PDO, pdo_sqlite, Phar, posix, random, Reflection, shmop, SimpleXML, sockets, tokenizer, xml, xmlreader, xmlwriter), то в результате такой бинарь будет весить 45 мегабайт.
P.S. Причём стоит учитывать, что это вполне официальный способ, а не костыль:
Да мало ли что там приводится? Это тривиальная логика: Нейминг "Service" является мусорным и не несёт никакого смысла. Зачем оно нужно? Удалить его и ничего не изменится вообще.
Репозиторий — тоже является сервисом предоставления данных из внешнего источника. Энтити (если она анемичная и тонкая, как у вас в примерах) — тоже является сервисом репрезентации записи в БД. И т.д. Почему всё тогда не складывать в директорию "Service", если это тоже сервисы?
И да, директория (в т.ч. неймспейс) должен соответствовать не задаче, а области ответственности. Что изменится, если вместо примитивной структуры "для новичков":
1) Куда будете складывать ошибки, возникшие в процессе оформления заказа? Про второй случай всё очевидно, в заказах (с вариациями) Order\***\NotEnoughMoneyException. А в первом?
2) А где будет валидатор, который проверяет состояние заказа?
3) А как написать архитектурные тесты (например через https://github.com/carlosas/phpat), которые будут проверять, что "заказ" не имеет доступа и не обращается ни к кому, кроме соседних "сервисов" в том же неймспейсе?
Директория Services является вырожденной (Так же как и Entity), т.к. не соответствует никакой задаче. Это плохой пример и явно не соответствует понятию "чистая архитектура", но допустимо в рамках небольшого ПО.
Можно взять себе за правило, что любой кейс, который содержит кейворды Service, Util, Manager, Support, etc почти всегда (как и в вашем случае) является некорректным с точки зрения нейминга и построения структуры ПО.
<душнила_mode_on>
KDE кроссплатформенный, так что формально можно тоже самое реализовать и в винде.
А даже если бы и не был кроссплатформенным, то wsl позволяет пробросить иксы наружу, где со стороны клиента (винды) достаточно установить что-то вроде VcXsrv, чтобы использовать абсолютно любое линуксовое приложение (включая плазму) одной командой в консоли.
</душнила_mode_on>
Возможно вы не поняли. Предметная область любой игры не ограничивается персистентным состоянием позиции игрока. Это всего лишь одна ~десятая всех задач.
Я вот по должности своей как раз разрабатываю один известный MMO шутер-лутер. И http (и grpc) для идемпотентных и стейтлесс запросов вполне себе занимает бОльшую часть всей предметной области, а то о чём вы говорите - лишь сессионная составляющая самого режима игры, которая частично может быть рассчитана и на клиенте в т.ч. в отличие от какой-нибудь операции "покупки" товара у "торговца".
Так что списывать технологию со счетов просто "потому что" не вижу смысла.
Медленный для чего? Ну вот, например, дефолтный ответ "самого медленного фреймворка в мире" (ака Laravel) внутри докера на винде - 8-10мс в режиме дебага. Этих 10мс не хватит чтоб получить информацию о профиле игрока? Получить список предметов? Получить информацию о точках спауна? Где именно эти 10мс сыграют значительную роль в нагрузке, когда один селект из базы может и в два, и в десять раз дольше работать?
Да вполне нормальный протокол для RPC. Клацаешь по кнопочке, с сервера по хттп грузанулись настройки персонажа, например и отобразилось окошко с ним Причем всё готовое уже есть: Сервер, лоадбалансер, дебаггеры, клиенты. Ну и логи потом дебажить приятнее, нежели какой-нибудь grpc
Ещё раз повторю, что далеко не в любом. А если и можно, то сменой одной буковки можно всё поломать.
Видимо вы пропустили тред про го и руби чуть выше.
Вопрос был, цитата:
Я ответил: Да, в каких-то языках есть строгое требование к виду имён переменных. Даже привёл пример современных языков, где такие ограничения есть, т.к. в зависимости от того как оно выглядит — меняет свою семантику и поведение.
И вы хотите сказать, что вообще ничего не изменится, если все
ExampleVariable
заменить наexampleVariable
? А вот судя по этой ссылочке на туториал, кажется, это совсем не так: https://go.dev/tour/basics/3Про руби вы тоже ответили: Язык явно диктует как именовать переменные/константы и от этого самого именования полностью зависит поведение языка.
Ну как минимум в Go и Ruby. Только там не то что бы "компилятор упадёт"… Скажем так, он может упасть при определённых обстоятельствах, т.к. от именования зависит вообще всё.
Не, понятно что в большинстве случаев это всё фигня, но как бы есть Half-Life 2, есть фантазмофобия, есть фаллаут, сабнавтика, но мэн скай, хитман 3 и прочее. Да, это всё порты, а не эксклюзивы, но тоже вполне себе прикольно играется. Тот же HL2 я прошёл с удовольствием.
Кстати, если уж говорить про стим, то не совсем понятно как Apple будет совместим с ним. Поддерживает ли он OpenVR стандарт? Как подключить контроллеры? Ну и прочее… А то что-то мне кажется, что в текущем виде это не конкурентный продукт. Тем более за цену в 4 раза превышающую всё тоже самое, что уже есть.
Я пока не могу понять зачем нужны вообще эти очки и какую задачу они будут решать? В голову приходит только просто отговорки на тему "чтобы были" + "экосистема эппл". А никаких объективных причин тратить четверть миллиона рублей на то, что будет пылиться на полке — не могу придумать.
Это не так.
await
лишь делегирует задачу "наверх", т.е. это другая форма записиyield
. Фактически альтернатива выглядела бы так:Что фактически может быть в PHP упрощено в сторону:
Ну можно вместо встроенного select просто проверить на eof и попытаться считать, если делать влоб.
С другой стороны в пыхе можно доустановить libev, libevent, ev или libuv, а там уже на выбор, хоть poll, хоть epoll, хоть kqueue, хоть devpoll, хоть evport, хоть ещё что. Накрайняк есть ffi и руками можно допилить нужное. Было бы желание.
Осталось понять откуда в PHP внезапно проблемы с блокирующим io, когда обычная функция stream_set_blocking превращает любой io в неблокирующий. Хоть чтение с файловой системы, хоть сокеты, хоть что угодно...
При этом наличие файберов в PHP делает не то что ненужным аналог в JS из async/await, но и вообще ставит под сомнение их существование в природе, т.к. JS-ный аналог становится просто неудобным.
Мне кажется, подобное актуально, когда в языке нет строгой типизации (в первую очередь) и нет конструкций, обеспечивающих удобное взаимодествие с нуллами.
Например в Java, где любой объект может быть как инстансом, так и null, и язык на уровне типов не обеспечивает гарантии того, что объект является корректным инстансом. Поэтому, в Java намного практичнее было бы использовать подобные конструкции, т.к. они предоставляют безопасный инструмент для работы с nullable объектами.
Если говорить про PHP, то этот язык при работе с nullable-объектами более строгий и на уровне типов гарантирует то, что объект не является null. Поэтому и смысла меньше.
Во-вторую очередь, операторы
?->
,??
и проч. позволяют удобно работать с nullable-объектами, поэтому смысла в подобных монадах становится ещё меньше. Напримерoptional
:В чём принципиальное отличие от?
Не, не так уж и долго: гифка
Секунд 5 сборка занимает.
А если вместе с пересборкой всего PHP, то да, долго.
Можно собрать и статик, для этого прописывается
--with-embed=static
, например:В результате вместо
so/dll
собираетсяa
файл.Потом этот файл линкуется (плюс 4 обязательных зависимости в ядре):
Если требуется какая-то доп.зависимость, то это просто расширяется, например:
Или так:
Но у этого есть и обратная сторона, если собрать что-то более менее стандартное (например с расширениями:,
Core
,date
,libxml
,pcre
,sqlite3
,ctype
,curl
,dom
,FFI
,fileinfo
,filter
,hash
,iconv
,json
,mbstring
,standard
,SPL
,PDO
,pdo_sqlite
,Phar
,posix
,random
,Reflection
,shmop
,SimpleXML
,sockets
,tokenizer
,xml
,xmlreader
,xmlwriter
), то в результате такой бинарь будет весить 45 мегабайт.P.S. Причём стоит учитывать, что это вполне официальный способ, а не костыль:
В общем, дошли руки до того, чтобы поиграться с этой штукой. Сделал репку с примером: https://github.com/SerafimArts/PHP-Embedded/tree/master
В принципе всё очень просто:
Сами исходники PHP складываются, например, в
vendor/php-8.2.6
, затем требуется их собрать:./buildconf
(генерация скрипта конфигурации)./configure --with-embed
(конфигурация бинаря)make -j "$(nproc)"
(сборка)После make появляется
libs/libphp.so
, который и будет использоваться.Сам код с примером может быть таким (он просто подключает при запуске файл
entrypoint.php
):И CMake файлу для сборки, вроде такого:
После этого собираем и компилируем:
cmake
+cmake --build
Скорее уж лучше написать:
Как минимум читаемее будет
Да мало ли что там приводится? Это тривиальная логика: Нейминг "Service" является мусорным и не несёт никакого смысла. Зачем оно нужно? Удалить его и ничего не изменится вообще.
Репозиторий — тоже является сервисом предоставления данных из внешнего источника. Энтити (если она анемичная и тонкая, как у вас в примерах) — тоже является сервисом репрезентации записи в БД. И т.д. Почему всё тогда не складывать в директорию "Service", если это тоже сервисы?
И да, директория (в т.ч. неймспейс) должен соответствовать не задаче, а области ответственности. Что изменится, если вместо примитивной структуры "для новичков":
Будет более адекватная и очевидная?
Если считаете что это "не удобно", то:
1) Куда будете складывать ошибки, возникшие в процессе оформления заказа? Про второй случай всё очевидно, в заказах (с вариациями)
Order\***\NotEnoughMoneyException
. А в первом?2) А где будет валидатор, который проверяет состояние заказа?
3) А как написать архитектурные тесты (например через https://github.com/carlosas/phpat), которые будут проверять, что "заказ" не имеет доступа и не обращается ни к кому, кроме соседних "сервисов" в том же неймспейсе?
Директория Services является вырожденной (Так же как и Entity), т.к. не соответствует никакой задаче. Это плохой пример и явно не соответствует понятию "чистая архитектура", но допустимо в рамках небольшого ПО.
Можно взять себе за правило, что любой кейс, который содержит кейворды
Service
,Util
,Manager
,Support
, etc почти всегда (как и в вашем случае) является некорректным с точки зрения нейминга и построения структуры ПО.