Pull to refresh

Comments 55

Было бы интересно увидеть цифры про производительность
Если вас беспокоит производительность, но несколько простых советов:
  • Не используйте строковых лямбд, только Closure. Каждая лямбда — это по сути create_function (eval).
  • Если используете строковые «указатели», то выберите библиотеку вообще без поддержки лямбд. Если есть поддержка, то на каждом «указателе» будет вызываться strpos.
  • Не используйте библиотек с ленивыми вычислениями. Кодить нужно будет аккуратнее, у каких-то операций увеличиться цена, но не будет лишних вызовов функций, у которых цена далека от нулевой.
  • Если вам всё ещё не хватает скорости, то LINQ не для вас.
  • Если вам всё ещё мало скорости, то пора смотреть в сторону C#/Java/C++.

В целом, библиотека типа Underscore.php не должна сильно сказываться на скорости. Это по большей части обёртка на стандартными функциями, оверхед небольшой.
Хотелось бы узнать на сколько данные библеотеки лучше/быстрее/функциональнее, чем более известные решения, к примеру, Zend_Db_Select?
Эм. Zend_Db_Select, как я понял из документации, работает с БД. Предложенная реализация LINQ работает с объектами в памяти. Как их можно сравнивать, мне не ясно.
А если указать Zend_Db_Adapter_Array? *мечты… мечты*
не Указать, а Написать :( Пятница-Тринадница
В текущем состоянии для замены существующих DAL и ORM эти библиотеки непригодны, ИМХО. Они представляют интерес только в виде LINQ to objects. Возможно, стоило явно упомянуть это в статье.

В то, что эти библиотеки дорастут до генерации качественного SQL, как оригинальный .NET LINQ, лично мне верится с трудом. Во-первых, PHP не предоставляет синтаксических деревьев, что заставляет парсить PHP вручную, а это уже закат солнца вручную. Что разрабы PHP предоставят синтаксические деревья наружу в PHP — ну не верю, не в этой реальности. Во-вторых, решение задачи генеарации SQL по синтаксическому дереву в лоб приводит к совершенно невменяемым и нечитаемым запросам. Нужно очень много оптимизаций, рассмотрения частных случаев для каждого движка баз — объём практически неподъёмный. Это делается не в одиночку, а серьёзными командами.

Так или иначе, этим никто не занимался. Единственная поделка с доступом к базам — это PHPLinq, от которого LINQ и не пахнет, это просто альтернативная запись SQL запросов, DAL. PHPLinq не пользовался, поэтому сказать об удобстве ничего не могу.
А толку-то. Это LINQ2Objecs. Причём без нормальной поддержки лямбд смотрится убого и чужеродно, даже реализации на C++0x выглядят органичнее. А адекватный LINQ2SQL без поддержки со стороны компилятора/интерпретатора чего-то вроде деревьев выражений всё равно не реализовать.
Мдааа, такой код «синтаксическим сахаром» не назовёшь. В отличие от LINQ
Вот вы минусуете а человек дело говорит. Смысл LINQ именно в синтаксисе, он чужеродный, но прекрасно встраивается в язык, он визуально приятный, в отличии от этого набора методов.
Если для вас LINQ — это исключительно «from a in b where c select d», то у вас очень и очень ограниченные представления о LINQ. Например, я и в C# использую функциональную запись, а не «запросы». LINQ — это НЕ синтаксический сахар.
Да, для меня LINQ именно красивый и функциональный синтаксический сахар, я привык работать с реляционными бд и мне очень понравился он именно с этой стороны. То что он может так же и с обьектами работать и другими наборами данных, это только плюс. А вот о моих представлениях я бы на вашем месте не рассуждал так открыто, можете ошибаться прилюдно.
Смысл LINQ и правда в синтаксисе, ведь вместо него можно использовать обычные foreach...if...else.

Но! LINQ — не «сахар» вокруг for...if...else. Это совершенно самобытная часть языка/фреймворка, которая меняет сам стиль написания кода с императивного на функциональный.
Смысл LINQ именно в синтаксисе

Ну не скажи, я например использую только синтаксис методов. Синтаксис запросов действительно немного чуждо выглядит, плюс в нем доступны не все возможности LINQ.
А зачем? Я как бывший .NET-чик, конечно понимаю что LINQ это круто, модно и бла бла бла. Но вот сомневаюсь, что бы он был действительно нужен в PHP. С моей точки зрения LINQ в PHP это избыточная функциональность, которая привносит дополнительную вычислительную нагрузку в PHP скрипты. И опять таки вопрос зачем? Для того что бы было удобно программисту и все? Я например люблю что бы быстрее работало и при этом потребляло меньше ресурсов. По этому считаю что лучше уж пусть будет на несколько строчек длиннее код, зато работать будет лучше :)
Язык LINQ мне кажется очень выразительным. По-моему, «where()->select()» не идёт ни в какое сравнение с «foreach — if — a[]». Первое анализируется человеком за секунду, во второе надо вчитываться.

Я, как дотнетчик и похапэшник, не понимаю обсуждения скорости работы скриптов PHP. PHP с точки зрения скорости работы — это курам на смех. Точка. Если нужна скорость разработки — используется PHP, Ruby и т.п. Нагрузку побеждаем железом. Если нужна скорость работы приложения — используется C#, Java, в особо тяжёлых случаях C++. Нагрузку побеждаем и железом, и силой мыли.

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

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

Прошу уточнить
PHP, Ruby и т.п. — низкая скорость выполнения кода, высокая скорость разработки
C#, Java и т.п. — высокая скорость выполнения кода, средняя скорость разработки
C++, C и т.п. — максимальная скорость выполнения кода, низкая скорость разработки

Все отношения — средние по больнице. Зависит от того, что разрабатывается, кем разрабатывается и т.п.
Да ладно Вам.
Если поставить кэшер опкода, то PHP тоже быстро выполняется.
А если еще все лежит на SSD, код написан грамотно, то единственное место, в которое можно упереться — работа с базой данных. Да, тут PHP не так уж и быстр, соглашусь.
Даже со всеми кэшерами PHP в разы медленнее компилируемых языков. Или я отстал от жизни, и появился компилятор? (Не, ну есть фейсбуковый ХипХоп, но он накладывает ограничения на немало вкусностей PHP.)

Да и даже с компиляцией… Динамическая типизация весьма нехило сказывается на скорости относительно строгой типизации. И когда единственная коллекция для всех случаев жизни — это array.

В общем, PHP медленный, что называется, by design. Можно сколько угодно ускорять, но C#, Java, C++ он не догонит никогда.
Не спорю на счет компилируемых языков, но на счет коллекций вот есть SPL. Да и чем array так плох?
Есть на свете типизированные массивы, битовые поля, односвязные списки, двусвязные списки, хэш-таблицы… Как вы думаете, насколько эффективен один тип коллекции, который используется для всех остальных, оптимизированных для разных случаев?

SPL — это, конечно, прогресс, но пока небольшой.
Минус SPL в том, что его очень редко используют почему-то. Хотя буду честен, я его тоже недавно открыл :)
А так все перечисленное уже есть.
Минус SPL в том, что его видимо писали те же люди, что и саму корку PHP, из того, что навсегда запомнил при работе с ним — не доверяй документации, я очень злился когда узнал что RecursiveDirectoryIterator так и не умеет обходить директории рекурсивно.
Документация там вообще-то какая-то… никакая. Если древние функции ещё кое-как документированы, а самое важное можно найти в комментариях, то в SPL на каждый метод в лучшем случае жалкий однострочный комментарий.
Вы куда смотрите?!
Кэшер опкода, если Вы не в курсе, это что-то вроде .pyc для php -_- (т.е. компилируются один раз, а потом просто выполняется байткод).

Динамическая типизация?
При грамотном использовании isset, empty и === вместо ==, то все шикарно…

P.S. шарп, джава, плюсы немного из другой серии. Хотя шарп еще ладно, но последние два, имхо, не для вебдева, а чего-то более серьезного.
На данный момент весь почти весь ентерпрайз — ява и веб. Сейчас уже мало кто пишет громозские монолитные приложения, куда ни глянь — несколько вебсервисов свзяанных друг с другом. Глянье хотя бы на Spring и посмотрите чем в будующем станет symfony.
В .NET добавили тип dynamic (по названию ясно, что это такое). И вот почему-то код с этим dynamic работает ну очень ощутимо медленнее, чем с обычными типами. Наверное, у программистов в Microsoft руки кривые, сравнивать переменные не умеют…

«Строгого типизированного» сравнения больше-меньше в PHP, к слову, не существует. А при повсеместном использовании === ваш код обрастёт кастованием переменных. Это уже не похапэ получается…

Джава не для вебдева? Гхм. Вы только в людных местах такое не говорите, камнями забросают. :)
но последние два, имхо, не для вебдева, а чего-то более серьезного

Гхм. Вебдев — это несерьёзно? Такое точно на людях говорить не надо. :)
Да, и я бы не сказал, что вебдев на C# — средняя скорость разработки, в то время как PHP — высокая. Есть MVC, который позволяет разрабатывать с потрясной скоростью.

А вот рельсам и правда не помешало бы скорости выполнения (особенно ощутимо после ASP.NET MVC). Но с точки зрения разработки — самая приятная штука.
hint:… скорости работы… !=… скорость разработки…
UFO just landed and posted this here
Я правильно понимаю, что собственно выражений-то нигде нет, так что прощай все применение LINQ к БД?
Есть попытки парсить строчки PHP вручную: в ныне покойном Phinq 2.0 и в ныне криво написанном PHPLinq. Со вторым можно поиграться, но он не LINQ, а DAL скорее. Для продакшена ни один из них не пригоден. Про перспективы этой затеи я отписался выше: habrahabr.ru/post/147612/#comment_4977062

Вкратце: индейская народная изба в силу неповоротливости и узкого взгляда на мир у разрабов PHP.
echo Phinq::create($people)
  ->groupBy(function($person) { return $person->residence->region; })
  ->select(function($grouping) {
    $obj = new stdClass();
    $obj->people = $grouping;
    $obj->region = $grouping->getKey();
    return $obj;
  })->orderBy(function($obj) { return $obj->people->count(); }, true)
  ->aggregate(function($current, $next) {
    $count = $next->people->count();
    return $current . sprintf(
      "%d %s (%s) live in the %s region\n",
      $count,
      $count === 1 ? 'person' : 'people',
      $next->people->aggregate(function($current, $next) {
        if ($current !== null) {
          $current .= ', ';
        }
        return $current . sprintf('%s [%s]', $next->name, $next->residence->code);
      }),
      $next->region
    );
  });

Язык LINQ мне кажется очень выразительным.

Я бы не хотел бы поддерживать такой код, уже лучше чистый SQL + PDO драйвер, а ещё лучше noSQL решение поддерживать.
Не надо выдирать из контекста. :) Это пример с использованием замыканий, синтаксис которых в PHP ужасен. «Лямбдовые» запросы, которые поддерживаются многими библиотеками, позволяют писать запросы примерно так:

from($categories)
    ->orderBy('$v["name"]')
    ->groupJoin(
        from($products)
            ->where('$v["quantity"] > 0')
            ->orderByDescending('$v["quantity"]')
            ->thenBy('$v["name"]'),
        '$v["id"]', '$v["catId"]', 'array("name" => $v["name"], "products" => $e)'
    );

К сожалению, цена такой красоты — семь вызовов create_function. Но если библиотеки LINQ получат достаточное распространение, то есть надежда, что разрабы PHP в конце концов добавят краткий синтаксис замыканий.
Ну, вообще-то, автор этот код привел как пример, при котором любой, кто знаком с LINQ «закатит глаза».
А про выразительность — вообще из другого контекста, это про LINQ сам по себе (из C#).

Зачем вы смешали эти две вещи в кучу?
1. Выразительность кода

2. Неестественная тяга к функциональщине
1. Но в итоге получаем еще большую невыразительность, разве нет?
Мне кажется, что чтобы такие вещи принести в PHP, нужно это все писать расширением, а не пытаться эффективно реализовать на самом языке.
Где невыразительность в этом коде?

from($categories)
    ->orderBy('$v["name"]')
    ->groupJoin(
        from($products)
            ->where('$v["quantity"] > 0')
            ->orderByDescending('$v["quantity"]')
            ->thenBy('$v["name"]'),
        '$v["id"]', '$v["catId"]', 'array("name" => $v["name"], "products" => $e)'
    );

Читаемость у него точно такая же, как у дотнетового LINQ (если использовать функциональную запись, а не запросовую). Ну да, строчки. Но здесь среды разработки могут подтянуться. В PHPStorm для этого надо сделать всего ничего — сделать PHP «внедряемым» в строчки, как и все остальные языки (не знаю, что им помешало сделать так сразу). В конце статьи ссылки на фичи.

Если реализовать расширением, то только скорость будет чуть выше, а возможности те же самые. С помощью расширения не добавить в язык поддержку синтаксических деревьев, это можно сделать только на ядрёном уровне. Да и если сделать расширение, то количество программистов, которые смогут применить библиотеку у себя в проекте, сократится раз эдак в 50.
Про невыразительность — да, строчки. Или многословность замыканий как на КДПВ.
А так, даже не знаю. Возможно я уже очень привык к обычной записи через foreach и прочие array_filter и новый подход тяжелее воспринимается, просто потому что не видно старых конструкций. А может я просто слишком консервативный в этом смысле.

В обычном php мне было бы видно сразу что происходит с данными, с какими именно частями и как они там оказались. И я даже могу это построчно отдебажить и проверить на каждом уровне. А тут, во-первых это новый синтаксис в котором прям вот сходу не поймешь что происходит и зачем. Лезем в доку, видим 50 методов… ух. Да, оно конечно выглядит прикольно, вроде так классно, но в вашем примере откуда-то взялась $v в строчках, непонятно как дебажить это дело. И вообще меня это пугает :)

Про расширение я не имел ввиду скорость, хотя это тоже плюс. А разве для ядерного уровня нельзя написать расширение? Тот же xdebug (zend_extension же) или опкод кешеры они не там работают? Вроде есть еще runkit, который позволяет заменять встроенные функции на что хочется. Так что я тут не уверен, что с помощью расширения нельзя привнести короткий синтаксис или синтаксические деревья. Ну и количество программистов — спорно. memcache/memcached расширение же ставят и ничего, не умирают. Не говоря уже о банальных php_mysql и прочем.

Я смотрю со своей колокольни, функциональщиной не интересовался, так что могу чего-то недопонимать в этой магии.
Если вы никогда не имели ничего общего с около-функциональным программированием, то выглядить код странновато будет, полагаю. Но это дело привычки.

Дебажить… Дебажить это весьма нетривиально. Там по сути eval'ы — как их дебажить? :) Внутри библиотеки код не сказать, что очевидный (впрочем, во внутренности .NET LINQ тоже лазать не принято, хотя благодаря поддержке yield код там в разы более читаемый).

Если уж совсем никак не разобраться, что происходит, то можно переписать запрос с помощью замыканий и подебажить их. И/или можно разбить запрос на части. Дебаг .NET LINQ так и происходит по сути.
UFO just landed and posted this here
Не могу предложить ничего лучше, чем справка по LINQ в MSDN. Правда там другие языки. И другой синтаксис запросов («запросовый», а не функциональный; первый в PHP невозможен без ядрёной поддержки). Надо бы написать хорошую вступительную статью по LINQ для тех, кто не пользовался .NET LINQ, но на это нужно дофига времени, которое никто не оплачивает.

Вкратце: работа с данными. Всякий раз, когда вы пишете

$array = array();
for ($elements as $element) {
  if ($element['foo'] == 'bar') {
    $array[] = $element['baz'];
  }
}
return $array;

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

return from($elements)->where('$v["foo"] == "bar"')->select('$v["baz"]')->toArray();

В LINQ очень много методов, которые заменяют вложенные друг в друга десять раз for-if-for-if.
UFO just landed and posted this here
> «И другой синтаксис запросов»

Ну почему же другой. LINQ — это и то, и другое. Чем больше нравится пользоваться — дело личных предпочтений. Мне, например, куда больше нравится запись в виде extension-методов к IEnumerable/IQueryable через точку.

И никогда не нравилось «from c in collection» — неинтуитивно, сбивает с толку. Читабельно было бы «for c from collection ...» или что-то в этом духе.
Я о том, что в справке в первую очередь рассказывается о запросовой записи.

В шарпе «неестественный» порядок сделан в угоду IntelliSense — так редактор может выводить максимум подсказок в процессе ввода запроса.
Я, разумеется, понимаю, что такая запись не просто так, но выглядит странно, на мой взгляд. Ну я и не переживаю — все равно никогда ей не пользуюсь.

Окей, про справку понял :)
Sign up to leave a comment.

Articles