Comments 85
Как вы думаете, на картинке PHP — это слон, а почему Ruby — собака? И кого изображают чайки? :)
+1
UFO just landed and posted this here
Лишние буквы можно убрать и получится:
$esQuery = (object) [
"query" => (object) [
"term" => (object) [
"name" => "beer"
]
],
"size" => 1
];
+1
UFO just landed and posted this here
>> Многим не нравится unless
Когда начинал только программировать на ruby, при встрече в чужом коде с unless мой «парсер кода» начинал жутко тормозить и уходить в свап.
Когда начинал только программировать на ruby, при встрече в чужом коде с unless мой «парсер кода» начинал жутко тормозить и уходить в свап.
+2
>Разные языки зачастую сравнивают друг с другом
Особенно зачастую посравнивать любят именно рубисты.
>Давайте жить дружно
Давайте код писать.
Особенно зачастую посравнивать любят именно рубисты.
>Давайте жить дружно
Давайте код писать.
+4
Особенности языка — это важно, но это не единственный и не всегда решающий фактор. Было бы интересно сравнение уровней ЗП, уровней разработчиков, культуре тестирования и типы компаний использующих эти языка.
0
Зачем литеральные объекты в php?
+1
Не претендуя на полноту и объективность…
Буквально недавно пересел с Symfony2 на Rails4.
* unless скорее порадовал
* byebug и REHL очень порадовал (потому что app-сервер в дебаг-режиме еле ползает, впрочем как и php5.5-fpm + Symfony2).
* жизнь без интерфейсов и type hinting — боль и тонны загадочного кода
* всякие динамические акссессоры и «вопросительные» методы где-то радуют, а где-то бесят. Вообще не кажется удобным, что каждый объект обладает невообразимой тучей методов и свойств, на все случаи жизни. Причём часть из них IDE не находит, хотя и поскрипывает по паре секунд на каждый запрос автокомплита.
* Жизнь без DI кажется ненадёжной и иллюзорной.
* RVM штука классная, но на фоне развития Docker-контейнеров уже не смотрится killer future.
* bundler по сравнению с Composer слабоват. Может я ещё не всё про него узнал
* конкретно Rails скорее разочаровал. До этого подходил к нему серьёзно ещё на второй версии. На фоне прогресса Symfony с первой до третьей версии, изменения в рельсах за это время ничтожны (включая и пятую версию тоже).
Но больше всего угнетает ActiveRecord и миграции. Раньше даже не осознавал, насколько это ловко сделано в Doctrine[Migrations] и сколько боли доставляет отсутствие «полной» конфигурации объектного мэппинга в рельсах.
Буквально недавно пересел с Symfony2 на Rails4.
* unless скорее порадовал
* byebug и REHL очень порадовал (потому что app-сервер в дебаг-режиме еле ползает, впрочем как и php5.5-fpm + Symfony2).
* жизнь без интерфейсов и type hinting — боль и тонны загадочного кода
* всякие динамические акссессоры и «вопросительные» методы где-то радуют, а где-то бесят. Вообще не кажется удобным, что каждый объект обладает невообразимой тучей методов и свойств, на все случаи жизни. Причём часть из них IDE не находит, хотя и поскрипывает по паре секунд на каждый запрос автокомплита.
* Жизнь без DI кажется ненадёжной и иллюзорной.
* RVM штука классная, но на фоне развития Docker-контейнеров уже не смотрится killer future.
* bundler по сравнению с Composer слабоват. Может я ещё не всё про него узнал
* конкретно Rails скорее разочаровал. До этого подходил к нему серьёзно ещё на второй версии. На фоне прогресса Symfony с первой до третьей версии, изменения в рельсах за это время ничтожны (включая и пятую версию тоже).
Но больше всего угнетает ActiveRecord и миграции. Раньше даже не осознавал, насколько это ловко сделано в Doctrine[Migrations] и сколько боли доставляет отсутствие «полной» конфигурации объектного мэппинга в рельсах.
0
И можно поподробнее о преимуществах Doctrine[Migrations]? Звучит любопытно.
Тут скорее преимущество доктрины и data mapper против active record. OO-first, генерация схемы их мэппингов сущностей и соответственно вместо ручного написания миграций частенько достаточно сделать migrations:diff.
Но вроде как для RoR тоже есть реализация data mapper вместо active record.
0
1) DB-first. Унаследованное приложение, нужно сгенерить сущности и связи из существующей схемы.
рельсы могут сделать файл schema.rb, которые по сути тот же sql дамп схемы, но на DSL. Делать модели — это уже дополнительные гемы неизвестной кривизны. Ввиду отсутствия явных атрибутов моделей и их типов, сама задача не так актуальна. Нафигачить руками has_one, belongs_to… — это не суперподвиг.
доктрина скафолдить модели умеет искаропки (а симфони на их основе скафолдит весь CRUD). Конфигурация мэппинга может храниться в классах аннотациями или конфигах (xml, yaml). Каждый вариант бывает сильно удобнее в каких-то конкретных кейсах. В конфиге указываются как связи, так и типы данных.
2) Model first — когда модели, их мэппинг и данные описаны… минутку но в рельсах можно описать данные только в миграциях через DSL, который по сути только обёртка над SQL DDL. Негде описать какой тип данных ожидает *модель*. Сгенерить полноценный diff в такой ситуации — просто нереальная задача. Данных недостаточно. Есть средства, которые позволяют как-бы восстановить картину по истории миграций, но они будут бессильными, если какие-то модификации проведены без миграций или описаны через sql. DSL, кстати по умолчанию (по соглашению, ага) не индексирует и не создаёт fk на связочные поля. Ну ладно консистентность (я это правда сказал?!), но это же тормозит!!!
Доктрина ориентируется на текущий мэппинг в коде. Это истина в последней инстанции — всё остальное требуется под неё подогнать. Именно таким образом, при тестировании на копии прода на одном из проектов, мы внезапно обнаруживали изменения в схеме, которые самовольно делали DBA. Более того, имея на руках полную информацию о мэппинге и типах полей, доктрина сама создает связочные таблицы, внешние ключи и индексы. В смысле генерит заполненную миграцию, которую вы потом можете применить as is, дополнить или переписать полностью. И никаких DSL — сразу SQL под конкретную БД.
В рельсах миграции являются важным источником знаний о том, чего хотел разработчик модели. И эти знания могут расходиться с информацией из schema.rb. Поэтому миграции лучше копить и копить.
schema.rb перегенерится после каждой миграциии и это источник постоянных конфликтов мержей. Поэтому в нашем проекте я его вообще пока сунул в gitignore. Пока не придумал, как его правильно готовить, без головняков на ровном месте. Скорее всего будем после релиза его генерить на проде в какой-нибудь schema.rb.prod, а потом при разворачивании девелоперских и тестовых сборках, переименовывать в schema.rb и стартовать с него.
В доктрине миграции — это служебный код, который, после срабатывания миграции, можно безболезненно удалить (и написать delete на табличку schema_migrations, чтобы вычищались неактуальные версии миграций). Был бы дамп с достаточно свежей версией. Нет дампа — тоже не беда. Можно сгенерить нулевую миграцию относительно пустой базы. И начать историю с чистого листа.
Про отличия ActiveRecord от DataMapper я не буду распространяться, кроме того, что для сложных задач, второй безусловно предпочтительнее.
Это, конечно, не всё, что я имею сказать по этому поводу, но на этом уже можно остановиться…
рельсы могут сделать файл schema.rb, которые по сути тот же sql дамп схемы, но на DSL. Делать модели — это уже дополнительные гемы неизвестной кривизны. Ввиду отсутствия явных атрибутов моделей и их типов, сама задача не так актуальна. Нафигачить руками has_one, belongs_to… — это не суперподвиг.
доктрина скафолдить модели умеет искаропки (а симфони на их основе скафолдит весь CRUD). Конфигурация мэппинга может храниться в классах аннотациями или конфигах (xml, yaml). Каждый вариант бывает сильно удобнее в каких-то конкретных кейсах. В конфиге указываются как связи, так и типы данных.
2) Model first — когда модели, их мэппинг и данные описаны… минутку но в рельсах можно описать данные только в миграциях через DSL, который по сути только обёртка над SQL DDL. Негде описать какой тип данных ожидает *модель*. Сгенерить полноценный diff в такой ситуации — просто нереальная задача. Данных недостаточно. Есть средства, которые позволяют как-бы восстановить картину по истории миграций, но они будут бессильными, если какие-то модификации проведены без миграций или описаны через sql. DSL, кстати по умолчанию (по соглашению, ага) не индексирует и не создаёт fk на связочные поля. Ну ладно консистентность (я это правда сказал?!), но это же тормозит!!!
Доктрина ориентируется на текущий мэппинг в коде. Это истина в последней инстанции — всё остальное требуется под неё подогнать. Именно таким образом, при тестировании на копии прода на одном из проектов, мы внезапно обнаруживали изменения в схеме, которые самовольно делали DBA. Более того, имея на руках полную информацию о мэппинге и типах полей, доктрина сама создает связочные таблицы, внешние ключи и индексы. В смысле генерит заполненную миграцию, которую вы потом можете применить as is, дополнить или переписать полностью. И никаких DSL — сразу SQL под конкретную БД.
В рельсах миграции являются важным источником знаний о том, чего хотел разработчик модели. И эти знания могут расходиться с информацией из schema.rb. Поэтому миграции лучше копить и копить.
schema.rb перегенерится после каждой миграциии и это источник постоянных конфликтов мержей. Поэтому в нашем проекте я его вообще пока сунул в gitignore. Пока не придумал, как его правильно готовить, без головняков на ровном месте. Скорее всего будем после релиза его генерить на проде в какой-нибудь schema.rb.prod, а потом при разворачивании девелоперских и тестовых сборках, переименовывать в schema.rb и стартовать с него.
В доктрине миграции — это служебный код, который, после срабатывания миграции, можно безболезненно удалить (и написать delete на табличку schema_migrations, чтобы вычищались неактуальные версии миграций). Был бы дамп с достаточно свежей версией. Нет дампа — тоже не беда. Можно сгенерить нулевую миграцию относительно пустой базы. И начать историю с чистого листа.
Про отличия ActiveRecord от DataMapper я не буду распространяться, кроме того, что для сложных задач, второй безусловно предпочтительнее.
Это, конечно, не всё, что я имею сказать по этому поводу, но на этом уже можно остановиться…
0
Не знаю, на мой взгляд, полный объектный маппинг не такая уж и нужная вещь. Может, вы потратите немножко больше времени при написании миграций вручную, но зато можно делать гораздо более гибкие вещи, чем при их автоматической генерации.
0
Конечно в доктрине также можно писать миграции вручную. Только что созданную автоматически миграцию можно самому подправить. На этапе разработки возможно обходиться вообще без миграции, когда достаточно сделать одну команду для синхронизации таблиц с маппингом. Это экономит время.
0
Да не в миграциях дело. Доктрина позволят с большего наслождаться приниципом persistence ignorance и вообще забыть о том что у вас база данных есть. Вы проектируете только свои бизнес объекты и то как они взаимодействуют друг с другом.
0
По поводу отладки. В rails есть такая вещь как WebConsole. Очень удобно. Отлаживать ошибки прямо в браузере. Сомневаюсь, что на PHP когда-нибудь это будет возможно.
-1
Это удобно только если не рассматривать в качестве альтернативы полноценный debug-режим. Который позволяет не вставлять отладочный код в текст, а пользоваться брек-поинтами в IDE.
Что же касается веб-панелей, то я просто тащусь от симфонийской: symfony.com/blog/new-in-symfony-2-8-redesigned-web-debug-toolbar
Потому что в ней не только информации в разы больше, без всяких вмешательств в код, но есть ещё и профилировщик встроенный (которому ещё можно задавать дополнительные точки фиксации). Причём всё это с историей и независимыми репортами на каждый запрос (включая AJAX), а не так, что эксепшены в соседних окнах чистят сессию друг другу.
Что же касается веб-панелей, то я просто тащусь от симфонийской: symfony.com/blog/new-in-symfony-2-8-redesigned-web-debug-toolbar
Потому что в ней не только информации в разы больше, без всяких вмешательств в код, но есть ещё и профилировщик встроенный (которому ещё можно задавать дополнительные точки фиксации). Причём всё это с историей и независимыми репортами на каждый запрос (включая AJAX), а не так, что эксепшены в соседних окнах чистят сессию друг другу.
0
yii2 тоже утащил себе подобную панель
dab1nmslvvntp.cloudfront.net/wp-content/uploads/2014/08/1408964113Yii2_debugger.png
dab1nmslvvntp.cloudfront.net/wp-content/uploads/2014/08/1408964113Yii2_debugger.png
0
Использую better_errors, на мой взгляд удобнее
https://github.com/charliesome/better_errors
https://github.com/charliesome/better_errors
+1
Также есть вариант в виде использования гема better_errors github.com/charliesome/better_errors
camo.githubusercontent.com/3fa6840d5e20236b4f768d6ed4b42421ba7c2f21/68747470733a2f2f692e696d6775722e636f6d2f367a42474141622e706e67
camo.githubusercontent.com/3fa6840d5e20236b4f768d6ed4b42421ba7c2f21/68747470733a2f2f692e696d6775722e636f6d2f367a42474141622e706e67
+1
а не злиться и не звонить кому-то, чтобы с этим разобралисьОригинал:
instead of bubbling up and forcing the callee to handle itВозможно, речь всё-таки о выбрасывании исключений вверх по стеку?
+1
Не холивара ради, просто факт:
I proudly present: The whole experience of programming in PHP, condensed into just two lines.
Two function definitions from PHP's standard library:
array_filter($input, $callback);
array_map($callback, $input);
Yep.
© Richard Wossal, http://r-wos.org/blog/php-explained
«Никогда мы не будем братьями» (с) ;)
I proudly present: The whole experience of programming in PHP, condensed into just two lines.
Two function definitions from PHP's standard library:
array_filter($input, $callback);
array_map($callback, $input);
Yep.
© Richard Wossal, http://r-wos.org/blog/php-explained
«Никогда мы не будем братьями» (с) ;)
+2
И что? Кто сказал что в этих функциях должны быть одинаковые аргументы? Тем более что в полном виде это выглядит так
array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
array_map ( callable $callback, array $array1 [, array $… ] )
И в array_map можно передавать несколько массивов, а array_filter можно использовать без $callback чтобы удалить все элементы массива у которых false значения.
Да может это и не по фэншую, но уж и к недостаткам не отнес бы, скорее специфические особенности, многие из которых из-за обратной совместимости. А не так как в некоторых других языках…
array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
array_map ( callable $callback, array $array1 [, array $… ] )
И в array_map можно передавать несколько массивов, а array_filter можно использовать без $callback чтобы удалить все элементы массива у которых false значения.
Да может это и не по фэншую, но уж и к недостаткам не отнес бы, скорее специфические особенности, многие из которых из-за обратной совместимости. А не так как в некоторых других языках…
0
Был бы это единичный случай — ещё куда ни шло. Но таких ляпов — море. А всё потому что язык — без дизайна, без соглашения, без единого стиля. В разное время разные люди коммитили в него кто во что горазд, в итоге язык — бардак и бордель, полный. И никто ничего не будет менять.
И да, лучше бы сделали наконец версию без обратной совместимости, но по-человечески, чем тащить надцатилетнее говно сквозь века.
И да, лучше бы сделали наконец версию без обратной совместимости, но по-человечески, чем тащить надцатилетнее говно сквозь века.
+2
Ну так он вообще не как язык начинался, а как набор скриптов, чего тут удивительного?
Тем не менее, где например CMS с популярностью уровня Wordpress на правильных языках? Если в TOP-10 CMS хоть одна не на PHP? Так что PHP при всём своём несовершенстве отлично подходит для своей ниши. При том, что Ruby появился в том же 95 году, что и PHP, а Python вообще в 91-м. Может не в правильности и феншуйности языка дело?
Тем не менее, где например CMS с популярностью уровня Wordpress на правильных языках? Если в TOP-10 CMS хоть одна не на PHP? Так что PHP при всём своём несовершенстве отлично подходит для своей ниши. При том, что Ruby появился в том же 95 году, что и PHP, а Python вообще в 91-м. Может не в правильности и феншуйности языка дело?
0
ну вопервых можно всегда сделать обертку какую хочется.
но прикольнее было бы добавить pipe-оператор или что-то типа bind а так же короткую запись для лямбд:
use function \myLittlePhp\array\{map, reduce, filter};
$sum = reduce(
map(range(1, 42), function ($i) {
return $i * 2;
}), function ($sum, $i) {
return $sum + $i;
}, 0);
но прикольнее было бы добавить pipe-оператор или что-то типа bind а так же короткую запись для лямбд:
use function \myLittlePhp\array\{map, reduce, filter};
$sum = map(range(1, 42), $i ==> $i * 2)
|> filter($i ==> $i % 4 === 0)
|> reduce(($sum, $i) ==> { $sum + $i }, 0);
0
Короткие лямбды (arrow function) рассматриваются:
wiki.php.net/rfc/arrow_functions
К сожалению, синтаксис все еще не такой уж короткий:
$result = array_map(function($x) => $x * 2, $elements);
Для сравнения, в Hack (статически-типизированный диалект php от Facebook):
docs.hhvm.com/hack/lambdas/introduction
return $people->map($name ==> $name. " Banks");
wiki.php.net/rfc/arrow_functions
К сожалению, синтаксис все еще не такой уж короткий:
$result = array_map(function($x) => $x * 2, $elements);
Для сравнения, в Hack (статически-типизированный диалект php от Facebook):
docs.hhvm.com/hack/lambdas/introduction
return $people->map($name ==> $name. " Banks");
0
Если вы не заметили — я как раз таки привел в пример синтаксис Hack.
Мне текущая RFC по лямбдам категорически не нравится ибо оно бесполезно чуть более чем полностью. Я до сих пор не понимаю почему просто не перетащить эту фичу напрямую из Hack. Технических ограничений (если не говорить про автоматический импорт переменных в скоуп функции) как бы нет.
Да даже ситуация с "=>" странная. По сути кейс с двусмысленностью легко обходится скобками:
хотя может я не не учитываю другие сценарии. В любом случае можно попробовать лямбды запилить на yay.
Мне текущая RFC по лямбдам категорически не нравится ибо оно бесполезно чуть более чем полностью. Я до сих пор не понимаю почему просто не перетащить эту фичу напрямую из Hack. Технических ограничений (если не говорить про автоматический импорт переменных в скоуп функции) как бы нет.
Да даже ситуация с "=>" странная. По сути кейс с двусмысленностью легко обходится скобками:
$x = 2;
[
$x => $x ** 2, // просто выражение 2 => 4
($x => $x ** 2) // лямбда в качестве элемента массива
]
хотя может я не не учитываю другие сценарии. В любом случае можно попробовать лямбды запилить на yay.
0
Действительно же hack. Меня смутил приведенный вами пайп-оператор — и я решил, что весь пример чисто синтетический.
Я так понял, что в php проблемы с запиливанием короткого синтаксиса именно с имеющимися парсером, который иначе пришлось бы сильно менять.
В Hack парсер писали с нуля, и у них такой проблемы не возникло.
Согласен, что предложенный вариант лямбд не идеален.
Я так понял, что в php проблемы с запиливанием короткого синтаксиса именно с имеющимися парсером, который иначе пришлось бы сильно менять.
В Hack парсер писали с нуля, и у них такой проблемы не возникло.
Согласен, что предложенный вариант лямбд не идеален.
0
Я так понял, что в php проблемы с запиливанием короткого синтаксиса именно с имеющимися парсером
Нет, в php7 контекстно-зависимый лексер + парсер с использованием AST так что разобрать можно любую синтаксическую конструкцию. Споры разгорелись из-за тайп хинтинга и семантики в случае массивов. Ну и есть определенные нюансы в плане семантики работы автоимпорта переменных. Как такового механизма скоупов в php как бы нет, но это обходится.
Нашлись люди которые начали кричать мол «не красиво не понятно будет смущать умы людей». Потому я все надеюсь на проект yay, препроцессор для php, который позволяет реализовывать такие фичи на уровне препроцессора и давать намного большим массам людей «обкатать» фичу.
0
Лично я когда вижу — слышу про подобные «ужасные изъяны PHP», автоматически делаю для себя отметку — человек PHP явно не знает, а скорее всего вообще не программист, и мило улыбаюсь :)
Не холивара ради, косяки да есть, но вот именно это этот момент — полная фигня, к которой мигом привыкаешь / не замечаешь т.к. юзаешь IDE.
Не холивара ради, косяки да есть, но вот именно это этот момент — полная фигня, к которой мигом привыкаешь / не замечаешь т.к. юзаешь IDE.
0
«а скорее всего вообще не программист», какой милый вывод. Просто умиляюсь. Куда там Шерлоку ;)
На всякий случай — программист с 13-летним стажем, начинал с Perl и PHP, уже лет 8 пишу в основном на ruby и scala и вспоминаю PHP как страшный сон.
На всякий случай — программист с 13-летним стажем, начинал с Perl и PHP, уже лет 8 пишу в основном на ruby и scala и вспоминаю PHP как страшный сон.
0
UFO just landed and posted this here
свистюлек накрутили, а разное говно как было, так и осталось, и тянется уже -надцать лет и будет тянуться ещё -надцать. Потому что за 8 лет никто не набрался смелости вычистить эти Авгиевые конюшни и сделать нормальный обратнонесовместимый релиз.
0
И получить python3? :)
+3
сделать нормальный обратнонесовместимый релиз.
Это самое глупое решение которые может принять разработчик, на продукте которого завязаны миллиарды и миллиарды строк продакшен кода.
Вместо этого достаточно сделать «обертку» над этими функциями (а почему до сих пор никто не сделал интересно?), а opcache бы со временем невилировал бы оверхэд от этого дела.
+1
вспоминаю PHP как страшный сон.
Ну справедливости ради php 8 лет назад и вправду был так себе язык. Он и сейчас местами плох, но уже намного лучше.
+1
Почему все кто переходит на ruby становятся такими снобами? :)
Однако писать можно и 20 лет, это ни о чем не говорит. А вот стенания о какой-то там мелочи в контексте «ну все язык ужасен», это как раз говорит. Как минимум, при должном опыте становятся известны намного более интересные косяки, а в такой момент про какие-то мелочи вспоминать уже язык не повернется. И опять же у слабо знакомого c PHP, но опытного в чем-то другом желания громогласно обсуждать язык по всяким мелочам не появится.
Однако писать можно и 20 лет, это ни о чем не говорит. А вот стенания о какой-то там мелочи в контексте «ну все язык ужасен», это как раз говорит. Как минимум, при должном опыте становятся известны намного более интересные косяки, а в такой момент про какие-то мелочи вспоминать уже язык не повернется. И опять же у слабо знакомого c PHP, но опытного в чем-то другом желания громогласно обсуждать язык по всяким мелочам не появится.
0
«Ужасных изъянов» сейчас уже действительно нет, и это очень хорошо, времена PHP 5.2 вспоминаются с ужасом. Но конкретно этот момент с неконсистентностью параметров все-таки раздражает даже несмотря на то, что IDE подсказывает правильный порядок. В Ruby с этим дела обстоят намного лучше. Пишу и на том, и на другом, больше на PHP (вынужденно), но Ruby доставляет несравнимо больше удовольствия.
0
Так вот в том то и дело, что это решается тупо оберткой, например.
Логичнее начать хотябы с раздражения символом $, тут хоть понять можно, шифт лишний вот, в JavaScript его не ставят, да и не сделать с этим ничего толком.
Логичнее начать хотябы с раздражения символом $, тут хоть понять можно, шифт лишний вот, в JavaScript его не ставят, да и не сделать с этим ничего толком.
0
Логичнее начать хотябы с раздражения символом $
Нынешний лексер между тем позволяет избавиться от этого символа. Но на это не пойдут потому как слишком большой ментальный шифт в языке. Похапэ без доллара — это как бы намекает на возможные негативные эффекты для бизнеса.
0
Пожалуй единственное чего мне не хватает в PHP это синтаксиса анонимных объектов из JavaScript. Ну и чтобы наконец выпилили доллары, а то уже поднадоело их писать) В остальном не вижу никаких особых фич в приведённом списке. «Повторные попытки после исключений» так и вовсе весьма спорное преимущество. Операция не удалась — попробуем ещё раз. А если она опять не удалась? Проще и правильней, сразу написать обработчик, который будет или ожидать успешного завершения в цикле или выпадет с ошибкой. Главными преимуществами PHP на мой взгляд являются его Си подобный синтаксис и широкий выбор CMS/фреймворков, что и определяет его популярность.
+2
Да, с такого расстояния разница может быть заметна только между императивным и функциональным языком, да и то с трудом, ведь, переменные, типы, функции, структуры, да и в целом программный код есть везде.
0
Недавно пришлось написать плагин под вагрант на руби. Немного наговнокодил конечно, но в целом прошло нормально, никакого отторжения. Немного напрягает сокращенная запись if в одной строке с самим действием — возможно дело привычки, но код сложнее читается, приходится вчитываться в каждую строку, чтобы не пропустить очередной if
0
А меня вот давно мучает всего лишь один вопрос… А есть существуют ли вообще люди добровольно переехавшие с ruby на php??
+2
UFO just landed and posted this here
да и среди рубистов никого такого не знаю. С PHP на Ruby — пожалуйста. Обратно — ни одного.
Пожалуй, это кое о чем да говорит. :)
Пожалуй, это кое о чем да говорит. :)
-1
С PHP на Ruby — пожалуйста. Обратно — ни одного.
А на что потом рубисты перебираются интересно? Знаю что python разработчики любят мигрировать на go. А тут куда? Кложа?
+1
>А на что потом рубисты перебираются интересно?
И внезапно никуда не переходят, тупиковый тип получается. Может поэтому они такие злые? Бугога.
И внезапно никуда не переходят, тупиковый тип получается. Может поэтому они такие злые? Бугога.
-1
Из тех что я знаю — scala, haskell, clojure, некоторые node.js увлекаются.
0
Мне кажется куда душа ляжет. Про Python я то же не очень согласен, так как в отличии от ruby/php это не web-only язык (в сравнении конечно). К слову Go уже становится не модно, а Rust немного вырастает как и Elexir.
PS ну и всё же async statefull код (ака websockets) удобнее писать на Python3/Elexi/NodeJS, в PHP/Ruby с этим куда хуже.
PS ну и всё же async statefull код (ака websockets) удобнее писать на Python3/Elexi/NodeJS, в PHP/Ruby с этим куда хуже.
0
async statefull код
Интересно почему в этот список не попал go, у него для этого самая удобная и простая модель выполнения. В целом же я с вами согласен, хотя возможность использовать корутины есть как в ruby так и в php. А стало быть можно достич примерно того же уровня. Проблема у PHP тут скорее в том, что подавляющее большинство существующих решений расчитаны на использование при умирающей модели выполнения. И пройдет еще год-два прежде чем это хоть как-то поменяется. В Ruby с этим намного проще.
0
В Go асинхронность неявная (gorutine). Насколько я понимаю, языки с явной асинхронностью это Python, C#, NodeJS (и возможно будет Rust).
Я не говорю, что это плохо, просто есть разница между написанием по сути multi thread кода (Go) и асинхронного пусть даже с async/yield.
Я не говорю, что это плохо, просто есть разница между написанием по сути multi thread кода (Go) и асинхронного пусть даже с async/yield.
0
Давайте для начала разберемся что есть «асинхронность». По сути в контексте вопроса, это когда у нас поток выполнения идет не в том порядке, в котором у нас все записано в коде. Мол вызвали мы неблокируемую функцию с await, по коду у нас дальше код наш должен идти, а оно что-то другое запустило, и уже потом наш, когда вызов завершится на самом деле. В этом случае «явная» асинхронность достигается только за счет колбэков/сигналов.
Что нам дают корутины (await/yield) — возможность писать код в синхронном стиле, перекидывая обязанности по переключению контекста на рантайм языка, однако все ограничено одним ядром процессора (одним потоком исполнения). Потому допустим надо поднимать несколько инстансов ноды на проект что бы хоть как-то оживить наш web-socket чатик.
Что дают потоки? Потоки дают такую-же изоляцию, возможность выполнять код паралельно и использовать весь CPU, но перелючение контекста уже идет на уровне операционной системы и это сильно дорого в плане потребления ресурсов. Так что 10000 отдельных потоков могут даже медленее одного потока.
А что если объеденить идею потоков и корутин? мы получим горутины. То есть в go это все те же (ну не совсем, я все же утрирую) корутины. которые собраны в пулы и раскиданы между потоками. А за переключение контекста уже отвечает рантайм, который управляет корутинами, и операционная система, которая рулит тем, какой поток сейчас выполняется. В итоге если у нас количество потоков небольшое, то каждый пул корутин выполняется на своем ядре и нет накладных расходов на переключение контекста. А на уровне рантайма языка накладные расходы на корутинки незначительны.
Вывод — горутины это так же неявно как и await/yield но намного удобнее и производительнее.
Что нам дают корутины (await/yield) — возможность писать код в синхронном стиле, перекидывая обязанности по переключению контекста на рантайм языка, однако все ограничено одним ядром процессора (одним потоком исполнения). Потому допустим надо поднимать несколько инстансов ноды на проект что бы хоть как-то оживить наш web-socket чатик.
Что дают потоки? Потоки дают такую-же изоляцию, возможность выполнять код паралельно и использовать весь CPU, но перелючение контекста уже идет на уровне операционной системы и это сильно дорого в плане потребления ресурсов. Так что 10000 отдельных потоков могут даже медленее одного потока.
А что если объеденить идею потоков и корутин? мы получим горутины. То есть в go это все те же (ну не совсем, я все же утрирую) корутины. которые собраны в пулы и раскиданы между потоками. А за переключение контекста уже отвечает рантайм, который управляет корутинами, и операционная система, которая рулит тем, какой поток сейчас выполняется. В итоге если у нас количество потоков небольшое, то каждый пул корутин выполняется на своем ядре и нет накладных расходов на переключение контекста. А на уровне рантайма языка накладные расходы на корутинки незначительны.
Вывод — горутины это так же неявно как и await/yield но намного удобнее и производительнее.
0
Вывод — горутины это так же неявно как и await/yield но намного удобнее и производительнее.
Вот тут я несогласен. async/yield это кок раз явно т.е. вы явно задаёте когда уходите в event loop. Горутины же больше похоже на микро планировщик из ОС. В Go нельзя явно не уходить в «event loop».
Явная асинхронность это когда вы явно в коде задаёте когда уходим в event loop. Это может быть callback или более удобный async/yield.
Неявная это когда вы не имеете полный контроль над этим. Мне ближе явный подход.
А что если объеденить идею потоков и корутин? мы получим горутины. То есть в go это все те же (ну не совсем, я все же утрирую) корутины. которые собраны в пулы и раскиданы между потоками.
Это всё tradeof между удобством и потреблением оперативки. По сути если вы запускаете в несколько потоков Python то получаете аналогичную ситуацию с Go.
0
В Go нельзя явно не уходить в «event loop».
в Go это просто не нужно, а стало быть мы достигаем такого же поведения и нам не нужно учитывать все эти мелочи. По поводу микропланировщика — все именно так. Просто опускаем слово await и все.
По сути если вы запускаете в несколько потоков Python то получаете аналогичную ситуацию с Go.
Мы сейчас про какие потоки? В Python насколько я помню из коробки есть только псевдопотоки, которые являются просто корутинами. А вот если мы раскидаем эти псевдопотоки по настоящим потокам — то тогда да, примерно так же.
И я все еще не понимаю чем вариант go, который самый простой и эффективный в плане работы с I/O, неудобен. Там есть определенные недостатки в экосистеме языка, но это же дело наживное.
0
И я все еще не понимаю чем вариант go, который самый простой и эффективный в плане работы с I/O, неудобен.
Ну разница как между ASM и C++ т.е. в некоторых ситуациях я сам лучше знаю когда и что нужно прервать.
Но тут языки сравнивать мне кажется глупо т.к. Go компилируется хоть и с GC, а Python интерпретируется хоть и байткод.
Кроме того, вы точно знаете где можете наткнутся на проблему гонок т.к. переключение явное. Т.е. это бывает полезно + это ещё один интересный подход которого нету в Go.
Но это не значит, что подход Go плох, но всё же не стоит делать из него silver bullet.
0
на проблему гонок т.к. переключение явное.
Чушь, вы же не контролируете переключение. Вы можете просто дожидаться завершения неблокируемого вызова или не дожидаться. В go точно так же. Можно ждать а можно не ждать.
но всё же не стоит делать из него silver bullet.
А никто и не делает, но я не вижу ровным счетом никаких недостатков в модели выполнения go. Круче только erlang.
0
Чушь, вы же не контролируете переключение.
Ещё как контролирую. Я могу сделать запрос к memcache в блокирующем режиме (в целом как и советую если он по unix-sockets), а уже для тяжёлого SQL запроса сделать yield (и только тогда я верну управление event loop'у).
А никто и не делает,
Противоречит:
я не вижу ровным счетом никаких недостатков в модели выполнения go
И вообще не уверен, что всё это сравнивать корректно в Go это просто легковесные потоки (треды), а в Python это синтаксический сахар к event loop машине. Притом, что Threades в Python это скорее аналог горутин (за счёт GIL), хотя и гораздо более примитивный. К слову появились и пулы процессов/тредов для вот такого:
https://docs.python.org/3.5/library/concurrent.futures.html#concurrent.futures.Executor
ЗЫ полезность event loop машины можно только показать тем, что nginx по сути использует именно её. Т.е. это вполне рабочее решение со своими плюсами.
0
Я могу сделать запрос к memcache в блокирующем режиме
А теперь главный вопрос — зачем? дабы небыло гонок? Это как бы ооочень плохой вариант, так как вы по сути фризите весь поток выполнения. Вам тут барьеры нужны да мьютексы, а не вот этот кастыль.
Все вызовы в кнешним ресурсам должны быть неблокируемыми. Даже по unix-сокету (это не сильно то и быстрее tcp через лупбэк интерфейс).
Притом, что Threades в Python это скорее аналог горутин (за счёт GIL),
Threads в пайтон это неявное использование корутин. А генераторы как раз таки и позволяют организовать корутины на event loop.
ЗЫ полезность event loop машины можно только показать тем, что nginx по сути использует именно её.
go на уровне рантайма так же использует event loop. И так же как и в nginx, где у каждого воркера свой event loop, в go просто создается парочка потоков со своими event loop, а внутренний рантайм уже раскидывает задачи по ним.
0
А теперь главный вопрос — зачем? дабы небыло гонок? Это как бы ооочень плохой вариант, так как вы по сути фризите весь поток выполнения. Вам тут барьеры нужны да мьютексы, а не вот этот кастыль.
Все вызовы в кнешним ресурсам должны быть неблокируемыми. Даже по unix-сокету (это не сильно то и быстрее tcp через лупбэк интерфейс).
Тут всё просто — сходить в memcached за данными быстрее чем отдать это дело в event loop. Питон существо не самое быстрое.
go на уровне рантайма так же использует event loop.
Ну так весь вопрос в том, работаете ли вы с event loop напрямую или же опосредованно в рамках много поточного программирования. Когда вы пишите код в nginx или поверх libevent вы работает с event loop явно из Си.
0
Ну так рубисты это же избранная каста :) После того как познаешь руби, им как-то стыдно уже возвращаться на похапе.
Так что да, это пожалуй говорит, но не всегда о явном превосходстве одного языка над другим.
Так что да, это пожалуй говорит, но не всегда о явном превосходстве одного языка над другим.
0
Ну вот, есть такие, кто сделал несколько проектов на ruby, однако большую часть все равно пишет на php.
На php однако работу найти намного проще, а также и работников.
В целом то это лишь инструменты, причем оба не идеальные.
На php однако работу найти намного проще, а также и работников.
В целом то это лишь инструменты, причем оба не идеальные.
0
Я с Руби не знаком, мне просто интересно, в нем есть удаленная отладка, как это позволяет делать xDebuger? Это реально круто! Не меняя ни строчки кода быстро что-то продебажить даже на удаленном тазике!
0
Что не мало важно — на окружении той машины!
0
Учитывая, что дебагер общается на отдельном порту, должно быть возможно. Другой вопрос, насколько шустро это будет шевелиться.
Я этим не занимался на Symfony2 + PHP5.5, потому что адово тормозило — как я понял, из-за большого количества файлов. Очень хочу как-нибудь попробовать на Symfony3+PHP7.
На текущем Rails-проекте я это тоже пробовал — тоже сильно тормозит. Время от времени можно, но лучше уж <% debugger %> вставлять. Имхо.
Я этим не занимался на Symfony2 + PHP5.5, потому что адово тормозило — как я понял, из-за большого количества файлов. Очень хочу как-нибудь попробовать на Symfony3+PHP7.
На текущем Rails-проекте я это тоже пробовал — тоже сильно тормозит. Время от времени можно, но лучше уж <% debugger %> вставлять. Имхо.
0
А что на счет сравнения производительности? Думаю было бы очень даже не плохо провести исследование.
0
PHP быстрее Ruby, но весь этот профит намертво убивает умирающая модель выполнения и блокировки. Сравнивать имеет смысл ayres vs sinatra например, и то шутки ради, ибо 90% PHP разработчиков настолько разбалованы умирающей моделью выполнения, что скорее всего риски и стоимость разработки взлетят вверх и ruby будет уже выгоднее с экономической точки зрения.
Печально но факт.
Печально но факт.
0
Была пол года-год назад статья с заголовком «PHP рожден чтобы умирать» (или как-то так). Там все расписано на тему «умирающей модели». Это уже устарело, и не актуально с версии 5.3, если не ошибаюсь.
Так что избалованность «кодеров» тем, что «пхп должен умереть» совершенно никак не влияет на «качество» самого языка.
Да, можно на пхп написать сервис, который каждые пол часа нужно перезапускать т.е. он сожрет всю память/заполнит весь диск/упрется в лимиты/просто упадет (нужное подчеркнуть), но ведь и на ruby тоже можно то же самое сделать! Как говорится, с дуру и член можно сломать. Но мы тут рассматриваем именно плюсы/минусы ЯП, а не то, как их используют разработчики/кодеры.
Про блокировки я ничего не могу сказать.
Так что избалованность «кодеров» тем, что «пхп должен умереть» совершенно никак не влияет на «качество» самого языка.
Да, можно на пхп написать сервис, который каждые пол часа нужно перезапускать т.е. он сожрет всю память/заполнит весь диск/упрется в лимиты/просто упадет (нужное подчеркнуть), но ведь и на ruby тоже можно то же самое сделать! Как говорится, с дуру и член можно сломать. Но мы тут рассматриваем именно плюсы/минусы ЯП, а не то, как их используют разработчики/кодеры.
Про блокировки я ничего не могу сказать.
0
Это уже устарело, и не актуально с версии 5.3, если не ошибаюсь.
Техническая возможность писать демоны имеется, и я их активно пишу. И ссылку привел на решение на PHP на базе корутин на котором очень даже приятно писать «не умирающие» штуки (не то что reactphp). Понастоящему «удобно» делать асинхронщину и неумирающий пых можно только с 7-ой версии с добавления return выражений для генераторов. Вот тут уже почти полноценный async/await можно мутить.
Да и сравнивать производительность я предлагал именно ayres (http сервер на php + микрофреймворк) и sinatra (легковесный ruby фреймворк), а точнее написать какой бэкэнд под todomvc на них и попускать нагрузочные тесты полноценные (а не сентетика). И мы с большой долей вероятности получим более высокую производительность на стороне php. Ну или разница будет в пределах погрешности.
Про блокировки я ничего не могу сказать.
У PHP все плохо с поддержкой неблокируемых API. Грубо говоря возьмите любую функцию (PDO, file_get_contents и т.д.) — они блокируют поток исполнения. Есть проекты вроде amphp которые постепенно эту брешь заполняют, но надо еще годик хотя бы что бы 80-90% юзкейсов было закрыто.
0
> Вместо такой строки:
> if! (foo || bar) && baz
> можно написать:
> unless (foo || bar) && baz
/me фейспалмнул и закрыл вкладку школьного портала
> if! (foo || bar) && baz
> можно написать:
> unless (foo || bar) && baz
/me фейспалмнул и закрыл вкладку школьного портала
-1
Не холивара ради, но… Когда в моду входили Ruby и Python думал, какой из них поучить. Какое-то время листал книжки и форумы, но однажды случайно открыл файл Ruby без подсветки синтаксиса. Завис. Открыл файл Python. Понял, что буду учить второй. Вся эта каша из специальных символов в Ruby лично у меня вызывает отторжение. На мой взгляд, нормальный язык программирования должен быть максимально читаем.
+2
Не вижу в таких статьях смысла. Сам рубист но всегда считал PHP хорошим, сильным языком. То что из-за человеческого фактора и в пхп и в руби есть программисты недостаточно продвинутые это нормально.
Никакого холивара по-моему между пхп и руби давно нет. Он остался в умах но не в деле.
Ну и конечно в каментах к таким статьям…
Никакого холивара по-моему между пхп и руби давно нет. Он остался в умах но не в деле.
Ну и конечно в каментах к таким статьям…
0
Sign up to leave a comment.
PHP против Ruby: Давайте жить дружно