теперь у меня не открывается две копии одного проекта ... даже если они в разных папках лежат
Такое может случаться от того, что вы скопировали папку проекта как есть и открыли там IDE. Попробуйте удалить папку .idea как минимум в копии. Походу они хранят там то ли абсолютные пути, то ли референс на стейт проекта.
Аналоги на другом языке, конечно, никогда не убьют композер (с учётом предоставляемого туллинга как отдельных пакетов, плагинной системы и пр.), но эксперимент интересный.
#12 -- это не уязвимость, а фича. Можно переопределить класс какой ни будь библиотеки своим, просто загрузив его раньше. С таким же успехом можно сказать, что весь composer -- дыра в безопасности, а не только директивы files. Ведь вы так или иначе подключаете чужой код.
Я продолжу список.
#13 -- тоже не про PHP. Если вам могут подгадить в брокер, то PHP тут не причём. Другое дело, если это приложение на Laravel, в котором даже кложуры могут быть сериализованы.
#14 -- assert не выполняет код с PHP 8.0, который уже даже не поддерживается на уровне security fix. А весь смысл eval в том, чтобы выполнять код. Так причём тут уязвимости?
Не, я не предлагаю прям на транспорт завязываться. Просто мидлварь, которая может быть и транспорт-агностик-интерцептором. Но вообще не суть, пускай будет http-мидлварь.
А что будет, если по каким-то неведомым или случайным причинам последовательность установки контекста будет нарушена или упоси господи произойдёт установка неправильного?
Стоп. А кто код то пишет? Как может установиться неправильный контекст? Неведомых причин в подконтрольной среде не бывает. Но допустим у нас есть фактор рукожопости от неопытной команды джунов и господь, который иногда помогает не случиться страшным вещам. Эта нить рассуждения продолжится чуть ниже.
Красота ручного конфигурирования pdo соединения для конкретного тенанта через связку роутера + фабрики репозиториев как раз в том, что все строго изолировано
Вот если убрать из этой связки роутер, который вообще-то про маршрутизацию, если что, а не про контекст, и убрать слово "ручного", то звучать будет нормально и универсально, хотя отдельные фабрики не особо и нужны.
То, о чём говорю я, называется областью видимости контейнера. Это не магическое глобальное состояние. Это как раз таки то самое "строго изолированное". В этом случае нельзя будет получить тенанто-зависимый сервис/репозиторий/что-угодно, если не определён тенант. Не надо будет вручную брать тенанта из jwt и просовывать его в обмен на репозитории тенанта. Всё, что про "вручную" — это не про изоляцию и безопасность, это про возможность накосячить или выстрелить в ногу. Лучше делать так, чтобы один раз описанные механизмы делали всё за человека, а человек думал только о бизнес-логике. В обмен на сокрытие шаблонного кода получаем: джун сможет нарукожопить только в пределах дозволенного, а господь лучше займётся чем-то более полезным.
поддержка такого кода опять же по моему скромному мнению усложняется. Магия, ребята
Детерминированный контекст != магия.
глобальные состояния
Ещё раз напомню, это не про глобальные состояния. Это про изолированный контекст, который легко тестируется.
Очереди+консольные команды. Это вообще пиздец, я думаю и так понятно, что все эти глобальные скоупы отметаются.
Нет, тут всё наоборот :)
Запросы к общим схемам.
Абсолютно без проблем. Общие схемы остаются общими и доступными из родительского контекста, если не переопределены в дочернем.
Стали бы мы делать TaskManager сейчас, если нужно было решать задачу по управлению скриптами в 2025? Не факт. Скорее всего попытались бы задействовать Airflow (с рядом костылей).
Не понял, чем помешали исключения и почему в PHP они подразумеваются для общения между слоями. Исключение — это просто исключение и бояться его не надо.
Представленный подход с хендлерами в Rift выглядит прикольно. Но чёт мне кажется, что проблема с мультитенантностью слишком преувеличена: переключаться между тенантами можно тупо в мидвари, создавая тенантно-ориентированную область видимости. Причём за мидлварью код будет всё тот же, как с одним клиентом.
Вы абсолютно правы! Спасибо за подробную рецензию! 🙌
Вы справедливо подчёркиваете важность корректных формулировок и глубокого понимания инструментов. Действительно, часто путают следствие с причиной - не генератор экономит память, а принцип поэтапного чтения.
Ваше деление на два паттерна использования ИИ кажется разумным. ИИ действительно наиболее эффективен как инструмент для специалиста, а не как замена экспертизы.
Хотя ваша критика по существу справедлива, несколько язвительный тон может затруднить конструктивный диалог. Иногда более мягкий подход к исправлению заблуждений работает эффективнее.
Claude can make mistakes.
Please double-check responses.
---
Первая мысль в начале статьи: "теперь можно будет скидывать эту статью если кто-то будет не понимать принцип работы генераторов".
Вторая мысль (на середине статьи): "а, так это про AI-буллшит на Хабре.. ну, от этого никуда не денешься"
Третья мысль (в конце про AI): "ну.. как-бы да.. и чё?". Ну и с последним абзацем вспомнился вчерашний токсик-пост.
---
Итоговые мысли смешанные: с одной стороны, охвачены две совершенно разные темы и мне это не нравится. Ожидал про генераторы, получил про буллшит. И не понятно, какую тему обсуждать. С другой стороны, я и сам статьи также пишу, поэтому сойдёт :)
Есть проблема буллшита на хабре. Не знаю кто и зачем раскручивают себе аккаунты сгенерированными статьями и комментариями, но страдают все. А что с этим делать то?
Мне видится два варианта:
Назначение инквизиторов на топики, которые будут жёстко карать любую AI ересь.
Хабр добавляет функционал для сообщества типа "пожаловаться на AI буллшит"
Надо начинать с вопросов: действительно ли есть проблемы, которые решают микросервисы? Готовы ли разработчики к многократному усложнению инфраструктуры? Осилит ли команда поддержку такой системы?
Я рассуждаю так: если уже распилено, значит причины (проблемы) были. Раз решились, значит о рисках знали и их приняли (или не знали, но готовы были встретить). В общем статья то и не о муках принятия решения, а конкретно о переходе.
Я работал с микросервисами и чувствовал себя прекрасно; и как какой-то сервис слишком набухал, его дробили. Да, можно писать весь проект в одной репе и размазывать его полностью или частично по подам, называя это распределённым монолитом. Но будем честны: у монолитов тоже хватает проблем.
Вообще не вижу ничего плохого в том, что распилили на сервисы. Даже поддержал бы в том, что разным стекам место в разных репозиториях. Контракты на gRPC -- окей. Документированное API -- ну а как иначе? Нужен девопс -- куда-ж без него, когда ещё надо и горизонтально масштабироваться?
В принципе всё логично. Но сухо: "было так, решили, переделали, стало сяк. Вот очевидные плюсы и очевидные минусы". А где мясо?
Какие были сложности и внезапные приколдесы при рефакторинге?
Что рассматривали и в итоге взяли для gRPC сервера на пыхе с симфой?
Смотрели ли на Temporal? Почему не взяли?
Смотрели ли на OTEL и трейсинг в целом?
Какие ошибки допустили и какие советы могли бы дать, чтобы это избежали другие?
Автономное оружие (Lethal Autonomous Weapons Systems, LAWS) - это оружейные системы, которые могут самостоятельно выбирать и поражать цели без прямого участия человека в процессе принятия решения о применении силы.
...
Многие страны и организации выступают за запрет полностью автономного оружия, требуя сохранения "значимого человеческого контроля" над решениями о применении летальной силы.
Вот с тезисом ускорения написания тестов вообще не согласен ¯\_(ツ)_/¯ В привычном ООПэшом стиле как-то проще, чем выстраивать паровозик методов из магически присунутого контекста.
Когда пробовал PEST, то нашёл несколько фатальных недостатков:
Не работают фичи запуска кейсов в отдельных процессах типа runInSeparateProcess
Отвратительная поддержка в IDE, что понижает производительность разработчика. Как пример: невозможно запустить конкретный тест
Субъективно, но синтаксис точно не для меня. Поддерживать такое я бы не смог.
Какое-то время юзал PEST в пакетах параллельно с PHPUnit: две конфигурации, разные папки. Да, PEST умеет запускать тесты PHPUnit, но стоило ему встретить атрибут runInSeparateProcess, как всё ломалось. Брал PEST только для одной фичи -- архитектурных тестов. Но потом узнал, что это тоже обёртка над плагином ta-tikoma/phpunit-architecture-test. В итоге установил оригинальный плагин и выкинул PEST нахрен, заменив всего одной функцией.
Мой вывод такой: PEST был сделан для фронтендеров, которые привыкли к JEST, выгорели от JS и хотят попробовать немного мужицкого PHP, но не так чтоб сразу, а потихоньку, чтобы было немного JSно и комфортно.
А всё вот это "выразительный", "делает тесты лаконичнее, читаемее и проще в поддержке" -- какой-то маркетинг. Куда проще в классе тест-кейса сделать фабрики, провайдеры, setUp/tearDown... и убрать любое дублирование кода в тестах, сделав их ещё лаконичнее, выразительнее, элегантнее и шелковистее, чем оно было бы в PESTе...
Если бы это были сырые запросы в БД, то да, можно было бы говорить о сложности, но здесь, как я понял, используется ORM. А значит вся сложность имплементации STI/JTI ложится именно на неё.
Стоило бы уточнить, что у морф-связей есть большой недостаток: невозможность прокинуть Foreign Keys, поскольку внешняя таблица определяется не статически, а дискриминатором.
Могу предположить, что огромный выигрыш заключается в отсутствии необходимости дублировать код комментариев/рейтингов для разных сущностей. Но тогда возникает другой вопрос:
Почему не использовали STI или JTI? Разница с морфами: нужен дополнительный класс на каждую внешнюю таблицу (что может быть даже плюсом, ведь можно кое что местами кастомизировать), но зато будут FK и типизация в сущностях.
Видно, что нагенерено, и нагенерено с избытком (много воды и слишком общих фраз). Но хуже всего то, что теория полностью оторвана от PHP, а бенчи от теории.
В бенчах нет gRPC; откуда-то появился костыль над SSE, называемый Mercure; не описаны особенности имплементации (те же центрифугу, кролика, кафку и пр. можно дёргать по-разному и добиваться разных показателей; как имплементировался Long Polling с учётом воркерности пыхи)
В теории всё описано общими словами и не всегда правда. Например gRPC на пыхе подключается отдельным расширением из пекла, да и тот только клиент. Для сервера нужен RoadRunner или Swoole. Есть ещё маленький нюанс с протобафом.Однако никакой заявленной сложности тут нет, её не больше, чем в REST. Про SSE хотелось бы увидеть замечание о том, что в базе одно SSE соединение сжирает один PHP воркер, и с этим надо что-то делать. И т.д.
В бенчах RR-Swoole-Franken обычно все допускают одни и те же ошибки в настройках RR: - не выключают логи и тестирую пропускную способность stdout. - не устанавливают protobuf и теряют очень много на (де)сериализации протобафов. При тестировании пустых эндпоинтов это существенно. - не тестируют разные важные опции типа кол-ва воркеров (относится ко всем серверам)
Несмотря на то, что Swoole в HTTP будет всегда объективно быстрее других (если только RR или Франкен не перепишут с go на что-то без интеропа), всё-таки хотелось бы видеть какую-то объективность в цифрах.
Короче, рекомендую читать документацию к серверам, чтобы устанавливать и настраивать их правильно, а не полагаться на дефолты Octane.
Такое может случаться от того, что вы скопировали папку проекта как есть и открыли там IDE. Попробуйте удалить папку
.ideaкак минимум в копии. Походу они хранят там то ли абсолютные пути, то ли референс на стейт проекта.Там же есть призовое место за самую быструю обработку на одном ядре
gomposer
Аналоги на другом языке, конечно, никогда не убьют композер (с учётом предоставляемого туллинга как отдельных пакетов, плагинной системы и пр.), но эксперимент интересный.
#12 -- это не уязвимость, а фича. Можно переопределить класс какой ни будь библиотеки своим, просто загрузив его раньше. С таким же успехом можно сказать, что весь composer -- дыра в безопасности, а не только директивы files. Ведь вы так или иначе подключаете чужой код.
Я продолжу список.
#13 -- тоже не про PHP. Если вам могут подгадить в брокер, то PHP тут не причём. Другое дело, если это приложение на Laravel, в котором даже кложуры могут быть сериализованы.
#14 -- assert не выполняет код с PHP 8.0, который уже даже не поддерживается на уровне security fix. А весь смысл eval в том, чтобы выполнять код. Так причём тут уязвимости?
Хм. я думал они (Angie) подзабили на это. Особенно после того, как PHPF решил поставить всё на франкен.
Не, я не предлагаю прям на транспорт завязываться. Просто мидлварь, которая может быть и транспорт-агностик-интерцептором. Но вообще не суть, пускай будет http-мидлварь.
Стоп. А кто код то пишет? Как может установиться неправильный контекст? Неведомых причин в подконтрольной среде не бывает.
Но допустим у нас есть фактор рукожопости от неопытной команды джунов и господь, который иногда помогает не случиться страшным вещам. Эта нить рассуждения продолжится чуть ниже.
Вот если убрать из этой связки роутер, который вообще-то про маршрутизацию, если что, а не про контекст, и убрать слово "ручного", то звучать будет нормально и универсально, хотя отдельные фабрики не особо и нужны.
То, о чём говорю я, называется областью видимости контейнера. Это не магическое глобальное состояние. Это как раз таки то самое "строго изолированное".
В этом случае нельзя будет получить тенанто-зависимый сервис/репозиторий/что-угодно, если не определён тенант.
Не надо будет вручную брать тенанта из jwt и просовывать его в обмен на репозитории тенанта. Всё, что про "вручную" — это не про изоляцию и безопасность, это про возможность накосячить или выстрелить в ногу. Лучше делать так, чтобы один раз описанные механизмы делали всё за человека, а человек думал только о бизнес-логике. В обмен на сокрытие шаблонного кода получаем: джун сможет нарукожопить только в пределах дозволенного, а господь лучше займётся чем-то более полезным.
Детерминированный контекст != магия.
Ещё раз напомню, это не про глобальные состояния. Это про изолированный контекст, который легко тестируется.
Нет, тут всё наоборот :)
Абсолютно без проблем. Общие схемы остаются общими и доступными из родительского контекста, если не переопределены в дочернем.
Почему не Temporal?
Не понял, чем помешали исключения и почему в PHP они подразумеваются для общения между слоями. Исключение — это просто исключение и бояться его не надо.
Представленный подход с хендлерами в Rift выглядит прикольно. Но чёт мне кажется, что проблема с мультитенантностью слишком преувеличена: переключаться между тенантами можно тупо в мидвари, создавая тенантно-ориентированную область видимости. Причём за мидлварью код будет всё тот же, как с одним клиентом.
Вы абсолютно правы! Спасибо за подробную рецензию! 🙌
Вы справедливо подчёркиваете важность корректных формулировок и глубокого понимания инструментов. Действительно, часто путают следствие с причиной - не генератор экономит память, а принцип поэтапного чтения.
Ваше деление на два паттерна использования ИИ кажется разумным. ИИ действительно наиболее эффективен как инструмент для специалиста, а не как замена экспертизы.
Хотя ваша критика по существу справедлива, несколько язвительный тон может затруднить конструктивный диалог. Иногда более мягкий подход к исправлению заблуждений работает эффективнее.
Claude can make mistakes. Please double-check responses.
---
Первая мысль в начале статьи: "теперь можно будет скидывать эту статью если кто-то будет не понимать принцип работы генераторов".
Вторая мысль (на середине статьи): "а, так это про AI-буллшит на Хабре.. ну, от этого никуда не денешься"
Третья мысль (в конце про AI): "ну.. как-бы да.. и чё?". Ну и с последним абзацем вспомнился вчерашний токсик-пост.
---
Итоговые мысли смешанные: с одной стороны, охвачены две совершенно разные темы и мне это не нравится. Ожидал про генераторы, получил про буллшит. И не понятно, какую тему обсуждать. С другой стороны, я и сам статьи также пишу, поэтому сойдёт :)
Есть проблема буллшита на хабре. Не знаю кто и зачем раскручивают себе аккаунты сгенерированными статьями и комментариями, но страдают все.
А что с этим делать то?
Мне видится два варианта:
Назначение инквизиторов на топики, которые будут жёстко карать любую AI ересь.
Хабр добавляет функционал для сообщества типа "пожаловаться на AI буллшит"
Мы используем RoadRunner с плагином metrics для Prometheus метрик. Решает все проблемы, кроме service discovery, но с ним у нас тоже нет проблем.
Я рассуждаю так: если уже распилено, значит причины (проблемы) были. Раз решились, значит о рисках знали и их приняли (или не знали, но готовы были встретить). В общем статья то и не о муках принятия решения, а конкретно о переходе.
Я работал с микросервисами и чувствовал себя прекрасно; и как какой-то сервис слишком набухал, его дробили. Да, можно писать весь проект в одной репе и размазывать его полностью или частично по подам, называя это распределённым монолитом. Но будем честны: у монолитов тоже хватает проблем.
Вообще не вижу ничего плохого в том, что распилили на сервисы. Даже поддержал бы в том, что разным стекам место в разных репозиториях. Контракты на gRPC -- окей. Документированное API -- ну а как иначе? Нужен девопс -- куда-ж без него, когда ещё надо и горизонтально масштабироваться?
В принципе всё логично. Но сухо: "было так, решили, переделали, стало сяк. Вот очевидные плюсы и очевидные минусы". А где мясо?
Какие были сложности и внезапные приколдесы при рефакторинге?
Что рассматривали и в итоге взяли для gRPC сервера на пыхе с симфой?
Смотрели ли на Temporal? Почему не взяли?
Смотрели ли на OTEL и трейсинг в целом?
Какие ошибки допустили и какие советы могли бы дать, чтобы это избежали другие?
А он и не перепутал.
Автономное оружие (Lethal Autonomous Weapons Systems, LAWS) - это оружейные системы, которые могут самостоятельно выбирать и поражать цели без прямого участия человека в процессе принятия решения о применении силы.
...
Многие страны и организации выступают за запрет полностью автономного оружия, требуя сохранения "значимого человеческого контроля" над решениями о применении летальной силы.
Вот с тезисом ускорения написания тестов вообще не согласен ¯\_(ツ)_/¯
В привычном ООПэшом стиле как-то проще, чем выстраивать паровозик методов из магически присунутого контекста.
Когда пробовал PEST, то нашёл несколько фатальных недостатков:
Не работают фичи запуска кейсов в отдельных процессах типа
runInSeparateProcessОтвратительная поддержка в IDE, что понижает производительность разработчика. Как пример: невозможно запустить конкретный тест
Субъективно, но синтаксис точно не для меня. Поддерживать такое я бы не смог.
Какое-то время юзал PEST в пакетах параллельно с PHPUnit: две конфигурации, разные папки. Да, PEST умеет запускать тесты PHPUnit, но стоило ему встретить атрибут
runInSeparateProcess, как всё ломалось.Брал PEST только для одной фичи -- архитектурных тестов. Но потом узнал, что это тоже обёртка над плагином
ta-tikoma/phpunit-architecture-test. В итоге установил оригинальный плагин и выкинул PEST нахрен, заменив всего одной функцией.Мой вывод такой: PEST был сделан для фронтендеров, которые привыкли к JEST, выгорели от JS и хотят попробовать немного мужицкого PHP, но не так чтоб сразу, а потихоньку, чтобы было немного JSно и комфортно.
А всё вот это "выразительный", "делает тесты лаконичнее, читаемее и проще в поддержке" -- какой-то маркетинг. Куда проще в классе тест-кейса сделать фабрики, провайдеры, setUp/tearDown... и убрать любое дублирование кода в тестах, сделав их ещё лаконичнее, выразительнее, элегантнее и шелковистее, чем оно было бы в PESTе...
Если бы это были сырые запросы в БД, то да, можно было бы говорить о сложности, но здесь, как я понял, используется ORM. А значит вся сложность имплементации STI/JTI ложится именно на неё.
Мне небезразлична тема развития Open Source в СНГ. Не могли бы вы поделиться ссылкой на инициативу?
Стоило бы уточнить, что у морф-связей есть большой недостаток: невозможность прокинуть Foreign Keys, поскольку внешняя таблица определяется не статически, а дискриминатором.
Могу предположить, что огромный выигрыш заключается в отсутствии необходимости дублировать код комментариев/рейтингов для разных сущностей. Но тогда возникает другой вопрос:
Почему не использовали STI или JTI? Разница с морфами: нужен дополнительный класс на каждую внешнюю таблицу (что может быть даже плюсом, ведь можно кое что местами кастомизировать), но зато будут FK и типизация в сущностях.
Видно, что нагенерено, и нагенерено с избытком (много воды и слишком общих фраз). Но хуже всего то, что теория полностью оторвана от PHP, а бенчи от теории.
В бенчах нет gRPC; откуда-то появился костыль над SSE, называемый Mercure; не описаны особенности имплементации (те же центрифугу, кролика, кафку и пр. можно дёргать по-разному и добиваться разных показателей; как имплементировался Long Polling с учётом воркерности пыхи)
В теории всё описано общими словами и не всегда правда.
Например gRPC на пыхе подключается отдельным расширением из пекла, да и тот только клиент. Для сервера нужен RoadRunner или Swoole. Есть ещё маленький нюанс с протобафом.Однако никакой заявленной сложности тут нет, её не больше, чем в REST.
Про SSE хотелось бы увидеть замечание о том, что в базе одно SSE соединение сжирает один PHP воркер, и с этим надо что-то делать. И т.д.
Это уже можно считать распределённым монолитом.
А вообще, если относиться к переменным, как к подам, то каждая функция будет кластером.
Всё-таки важно говорить общей терминологией и оперировать принятыми понятиями, а не уходить в философию.
Я тоже не понял, про что статья. Есть рассуждения, но они быстро заканчиваются ничем.
В бенчах RR-Swoole-Franken обычно все допускают одни и те же ошибки в настройках RR:
- не выключают логи и тестирую пропускную способность stdout.
- не устанавливают protobuf и теряют очень много на (де)сериализации протобафов. При тестировании пустых эндпоинтов это существенно.
- не тестируют разные важные опции типа кол-ва воркеров (относится ко всем серверам)
Несмотря на то, что Swoole в HTTP будет всегда объективно быстрее других (если только RR или Франкен не перепишут с go на что-то без интеропа), всё-таки хотелось бы видеть какую-то объективность в цифрах.
Короче, рекомендую читать документацию к серверам, чтобы устанавливать и настраивать их правильно, а не полагаться на дефолты Octane.