Pull to refresh

Comments 85

Очередная попытка из букв P, H и P собрать слово Java?

В этот раз хотя бы грамотная, поэтому +.
минусуйте, но мне показалось это чистым костылем превращения php в java
я считаю не корректным призывать минусовать/плюсовать.
если есть что сказать — надо говорить или голосовать молча.
Причем тут java или другие языки? Нужен функционал, он делается, независимо от того какой язык. Или если язык называется php, то в него нельзя добавить нужного функционала? Или может если в php добавить коллекцию, то он автоматически станет java? Не нужно говорить глупостей.
Если какое-то направление программирование развилось в среде разработчиков, использующих определенный язык, это не значит, что оно должно там и остаться навеки и умереть. Точно также многие MVC-фреймворки (именно веб-MVC-фреймворки) вдохновлены Рельсами, но никто же не говорит, что Yii или ASP.Net — это попытка превращения PHP или C# в Ruby. Это переносится на другие языки потому что это красиво, удобно и в этом есть определенная выгода.
немного уточню, что ASP.Net имел в виду ASP.Net MVC…
я с вами бесспорно согласен. мое сообщение относилось конкретно к этой реализации… в данном случае упрощения чего либо я не знаметил
На протяжении последних 5 лет я работаю с PHP. У него есть достаточно разных проблем, но это никогда не мешало создавать отлично работающие продукты.

Может ваш комментарий не уместен? Это занудство, какой PHP плохо, уже достало, ну не нравиться PHP, даже не открывай заметки с тегом PHP, не пиши, не читай, вообще забудь про существование.

У каждого языка есть свое предназначение, и у PHP есть своя ниша, то что люди его хотят сделать лучше, не есть плохо. Сравнение PHP и Java это как выбор между T-34 и ферари, и присутствием двух задач — уличные гонки и перепахать поле 40га, думаю вы долго не будете думать какой инструмент для какой задачи выбрать!?
UFO just landed and posted this here
Расскажите эти сказки Цукербергу.
Если у меня есть Т-34 и есть поле, которое надо перепахать прямо сейчас, лучше продать танк, купить трактор и перепахать поле через несколько месяцев?
Если продолжать вашу аналогию, вы собираетесь поставить на T-34 колеса и двигатель от феррари.

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

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

Что то не вижу прикрученной JVM :)
Хм… Сделать JVM, портировать все библиотеки Java…

Вон, на JS библиотеки аналогичным способом уже портируют, чем PHP хуже.
Каково же было мое удивление, когда в процессе чтения статьи я подумал ровно то, что Вы материализовали в первый коммент.
В java или C#, коллекции были заложены в язык изначально, и основной профит от их использования это то, что некоторые коллекции дают упорядоченность при помещении в них элементов, какие-то оптимальны для случайного доступа, какие-то для последовательного…

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

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

На практике важным моментом оказалась терминология. Больше не нужно говорить «сделай вот как вчера или как в том самом месте...».
Так вам же и плюсуют в общем-то за грамотность реализации. Код на гитхабе выглядит красиво и осмысленно, мне придраться не к чему.
Просто ошибка похоже была в базовом планировании — вовсе не обязательно было делать такую сложную обвязку из кучи файлов для относительно простого функционала.
Достаточно было одного простого инклуда с более простой обвязкой вокруг обычного массива, и использованием хешей(тех же дополнительных ассоциативных массивов) для производительности.
Ну еще малость убивает использование array_search() внутри. Это медленная функция, ибо даже не смотря на ее нативность и Си-шную реализацию, она ищет тупым перебором, без использования хеширования.

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

То есть в данном случае претензии в комментах — это вовсе не минусы. Это просто здравая критика. Воспринимайте правильно )
Как-то так.
Согласен с вами, что сделано грамотно, сразу видно что человек понимает как коллекции работают изнутри
Я подобное для себя решил проще. Добавить в движок объект который реализует Iterator, Countable и ArrayAccess интерфейсы. Получаем обычный с виду массив (разработчикам удобно), но вот просто так в него левых данных не вставить (забывчивый джуниор не пройдет). Имхо, так рано или поздно приходится делать в любой проекте с долгим периодом жизни.
Не в язык заложены, а в стандартлиб. Это в Groovy, например, коллекции заложены в язык.
А чем ваша реализация отличается от SplObjectStorage?
Какая именно реализация?

Если речь идет о интерфейсе Set и его реализации UniqueStore, то у SplObjectStorage нет встроенного контроля типов объектов.
Можно, но картина все равно не станет целостной.

Расширение SplObjectStorage позволит нам реализовать набор объектов, но никак не повлияет на реализацию карт и последовательных списков.
Но, к сожалению, не содержит карт.
Было бы удобнее работать с коллекциями нативным способом. Т.е. заменить
$list->each(function(){...});

на
foreach ($list as $k=>$v) {...}


Иначе не понятно, как в итерабельную функцию передать внешнюю переменную? Неужели через $GLOBALS?
Забыл про это.
Но всё равно, зачем так сложно?
1. Я не смогу это объяснить своим верстальщикам, которые прикручивают вёрстку и знают php на уровне if/else/foreach.
2. Вопрос в полиморфизме: где-то надо использовать foreach, а где-то $list->each(). Почему бы везде не использовать одну и ту же конструкцию?
Прошу прощения, не прочел комментарий автора ниже, где он говорит, что foreach некорректно работает с ключами-объектами. Просто никогда не экспериментировал :)
А где про это можно почитать? Что-то в мануале никак это не отрою…
волшебное слово «use»
Если использовать стандартный интерфейс Itertator, то и в foreach можно будет обходить такие объекты.
Практически каждый писал что-то подобное ведь. А тут все получилось собрано и аккуратно. Уж что что, а написано действительно хорошо. Однако, мне кажется, вы правы в том, что не нужно плодить сущностей:
// Iterable.php
interface Iterable {
  // ...
}

В PHP уже имеются необходимые интерфейсы. И еще свои пять копеек вставить на счет следующего замечания:
$objectMap = new HashMap('stdClass', 'stdClass');

try {
    $objectArray = $objectMap->toArray();
} catch (UnexpectedValueException $exc) {
    echo 'Объекты не могут являться ключами массива.';
}

Добавить сюда «внутреннее» расширение такого плана. Если объект реализует интерфейс, к примеру, IForMapHash — то пожалуйста, пусть будут ключами.
Отличный вопрос.

На первый взгляд для реализации итерации путем использования foreach() достаточно реализовать интерфейс Iterator или его производные (любой наследник Traversable).

foreach ($list as $k=>$v) {...}


Так и планировалось сделать. Но на этапе анализа вылез подводный камень — foreach() неадекватно реагирует на ключ в виде объекта.

Исходя из этого я сделал единый вариант для всех коллекций, оставляя возможность реализовывать интерфейсы итераторов на более низких уровнях.
Я даже не представляю, кому и зачем может потребоваться использовать объекты в качестве ключей. Быть может, имеет смысл оставить обе возможности и в 99% случаев использовать нативный foreach?
Ну вполне просто. Допустим, у нас есть карта 100*100, на ней 200 юнитов.
$map->setUnit( $unit, new Point(43, 12) );


Нам надо сделать очень быстрое получение координат юнита:
$map->getUnitCoord( $unit );


Можно, конечно, реализовать как-то так:
function setUnit (Unit $unit, Point $coord) {
  $this->units[$unit->id] = $coord;
}


А можно сделать так:
function setUnit (Unit $unit, Point $coord) {
  $this->units->set( $unit, $coord );
}


Пример, конечно, притянуто за уши, но идея может иметь смысл.

Именно из этого и расчет.

Данная ситуация может осложниться, если Unit не имеет уникально идентифицирующего его строкового или числового свойства.

function setUnit (Unit $unit, Point $coord) {
  $this->units[$unit->id] = $coord;
}
А если юнит перемещается по карте, то его придётся постоянно в перемещать в коллекции? Т.е. перестраивать массив.

По моему, это не правильно. Должна быть коллекция юнитов и у каждого юнита должно быть свойство $coords. Если надо найти всех юнитов в клетке, то придётся пробежаться по всей коллекции точно так же как SQL БД пробегаются по таблицам.

Кстати, поиск юнитов в конкретной координате, наверное, не самая частая задача. Подозреваю, что более распространённая задача это поиск всех юнитов в регионе (от 23х23 до 48х56). Ключи не решат эту проблему и придётся пробегать по всей коллекции.

Мне кажется, что вы путаете ключи массива с индексами из БД. Если Вам надо по какому-то полю быстро находить записи, значит Вам стоит создать отдельный индекс, что бы быстро его перебирать. Вы можете сделать его в формате b-tree или ещё как-то оптимизировать под свои нужны. Но не надо использовать для этого ключи массива так как круг решаемых задач очень не велик, зато коллекцию придётся постоянно перестраивать во время перемещения юнитов.
А если юнит перемещается по карте, то его придётся постоянно в перемещать в коллекции? Т.е. перестраивать массив.

Зачем?
$collection->rm($unit);
$collection->set($unit, new Point(2,3));

По моему, это не правильно. Должна быть коллекция юнитов и у каждого юнита должно быть свойство $coords. Если надо найти всех юнитов в клетке, то придётся пробежаться по всей коллекции точно так же как SQL БД пробегаются по таблицам.

Я обычно так и делаю, но это нарушает принцип единственной отвественности. Не юнит должен контролировать своё положение.
$collection->rm($unit);
$collection->set($unit, new Point(2,3));

Это и есть перестроение коллекции: сначала удаляете элемент, а потом создаёте новый. По моему, это сложнее, чем:
$collection->move($unitKey, new Point(2,3));
// или
$unit->move(new Point(2,3));


Ну, ок. Там может быть так:

$collection->get($unit)->moveTo(4, 1)


У точки ведь может быть метод «moveTo»
Действительно притянуто, потому что в качестве ключа логичнее использовать не весь объект, а его ID.
Но на этапе анализа вылез подводный камень — foreach() неадекватно реагирует на ключ в виде объекта.

Что происходит? Ошибка вылетает?
E_WARNING, который невозможно подавить.
Если реализация Iterator::key() возвращает объект, то вылетает такой warning:
PHP Warning: Illegal type returned from A::key() in /home/sam/sims/q.php on line 44
PHP Stack trace:
PHP 1. {main}() /home/sam/sims/q.php:0
Отсутствие возможности построить ассоциативный массив, где ключами будут объекты.
странное желание. Мне всегда казалось что у массива/«хеш массива» должна быть одна функция: быстрое извлечение данных по ключу.
Всякие накрутки типа: ключами могут быть объекты — это удар ниже живота по производительности.

Если есть такое, ну очень большое желание, то за 5 мин можно написать простую обертку, которая сериализует объект(часть объекта) и использует результат в качестве ключа.
Сериализация объекта тоже не самая быстрая операция. Вместо нее использую spl_object_hash().

Как показала практика — быстрое извлечение по ключу не говорит о том, что ключ не должен быть объектом.
да, я в курсе, я упомянул про суть, так сказать идею, а конкретное воплощение может быть любым
и все же спасибо за комментарий.
Зачем использовать в качестве ключа сериализованный объект, если можно использовать его уникальный идентификатор (id)?
Зачем так

use \UnexpectedValueException as UnexpectedValueException;

если можно просто так

use UnexpectedValueException;
Потому что выше используется пространство имен Rmk\Collection, и use UnexpectedValueException будет искать этот класс в этом пространстве имен. use \UnexpectedValueException; сработает.
Я думаю, что

use UnexpectedValueException

можно вообще не использовать и писать в коде сразу

try {
    $objectArray = $objectMap->toArray();
} catch (\UnexpectedValueException $exc) {
    echo 'Объекты не могут являться ключами массива.';
}

И так далее, для всех стандартных исключений из глобального namespace.
Самостоятельный контроль типов объектов в массиве.

а не лучше ли использовать для этой цели собственный враппер, тоже пишется за 5 мин :).
Мне, например, часто требуется использовать массив, как универсальный стораж, в котором могут буть разные типы. Не забываем, что РНР идеалогически разрабатывался как язык с НЕ СТРОГОЙ типизацией!
Да, в этом есть плюсы и минусы. Не нравится не срогая типизация — перелезайте на рельсы!
Самостоятельный контроль последовательности индексов в списке.

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

Возможно разработчикам РНР и нужно было сделать две отдельных сущности: массивы и хештайблы? Но, разработчики пошли по пути универсализации. Все довольны, все в шоколаде!
в целом проект грамотный и интересный
Дал плюс за креативность и грамотную реализацию, но тем не менее пользу вижу только в возможности работы по объекту как по ключу. Однако учитывая реализацию строго на PHP, эта польза нивелируется — можно было ограничиться реализацией лишь пары вспомогательных функций к стандартному массиву.
Итого(уж извините за критику, но взгляд со стороны часто находит простое в сложном): вы сделали, как справедливо заметил выше hom, бесполезное усложнение архитектуры.
Обычно, если нужно работать с объектами столь гибко, делается так: пишется класс обвязки к стандартному массиву, оперирующий самогенерирующимися ключами, строковыми или числовыми, и внутренним объектом, который является обычным массивом.
То есть когда вы потом напишете например $col->remove($obj), у вас $obj будет(и должен быть) не самим объектом, а его ключем в коллекции $col. Фактически это разновидность псевдопоинтера.
Соответственно работать с такими объектами вы будете не как $obj->method(), а как $col->get($obj)->method() или подобным образом. Компилятор сам вам подскажет, если вы забудетесь и попытаетесь вызвать $obj->method().
Контролировать типы объектов можно либо самому, либо включая в каждый объект метод либо свойство, отвечающее за тип. Таким образом при желании вообще можно в коллекцию помещать как ООП-объекты, так и обычные структуры, и работать с ними, не путая типы. Кстати работать можно будет как полностью с процедурным подходом, так и с объектным.

Плюс такого подхода в том, что аналоги перлового хеша в стандартный PHP-массив уже встроены — это ассоциативный массив. А следовательно, поиск значений по простому ключу будет гораздо быстрее любой другой реализации, написанной на самом PHP, иными словами: быстрее любого нативного перебора. То есть суть класса обвязки сводится лишь к группировке функций обслуживания такой «коллекции»(большинство из которых в языке уже есть нативно, а соответственно, работают быстрее) и скрытие внутри вспомогательных массивов-хешей.
>>Исторически сложившиеся имена функций и отсутствие ОО интерфейса
Это бесит только первые пять лет :)

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

Use SplObjectStorage, Luke.
и еще капля дегтя…
Очереди и списки интересны, если они производительны. Может я однобоко гляжу в сторону разработки, просто я последние пять лет сильно упираюсь в производительность.
При необходимости использования этих структур, я бы реализовал их в в виде РНР-расширения. Кажется я даже встречал такую реализацию. Можно покапаться в просторах инета…
У меня самого пару лет назад была такая идея, но не нашлось проекта для применения. И я бы туда еще добавил деревья. Как смотришь на это?

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

Другими словами, буду этим заниматься, но быстрых результатов дать не получится.

Если бы кто-то реализовал эти интерфейсы в качестве PECL модулей, я уверен, что работали бы они гораздо быстрее и доверия к ним было бы больше. Собственно, писал об этом в конце статьи.
1) надо поискать на предмет реализации, кажется я это где-то уже встречал
2) деревья не на много сложнее списков, можно найти уже готовые библиотеки, над которые просто написать РНР-враппер. Если такие найдешь, стукнись в приват.
Хорошая штука когда должно работать быстро и кушать мало памяти и мгновенно печалит, когда такой массив невозможно ни куда сериализовать.
на мой взгляд
1) сериализацию можно реализовать, это совсем не трудно, но надо понимать, что всякая сериализация/десерриализация — это время… как минимум O(n)
2) если хранилище сделать персистентным, то смысла в сериализации я не вижу, так как в основном сериализация используется, как передача данных между циклами обработки как правило одного приложения. Как раз тема персистентного хранилища. Если приложений несколько, и на разных языках (не удивительно и такое встречается), то использование данного вида сериализации вообще не имеет смысла, так как эта хреновина будет либо PHP-only. Либо если делать в виде отдельного демона — то это уже велосипед аналогов Тарантула или Токио. А оно надо? Лучше все равно не сделаешь. Хотя у меня были попытки www.slideshare.net/akalend/treedb-keyvalue-nosql-database
и даже не плохие: см. слайд 17 (производительность). Но уперся в ряд прочих проблем…

так что из всего вышеизложенного словоблудия я вижу следующий смысл:
— если реализовывать, то только как персистентное хранилище shmap
— реализовать как класс (несколько классов: map, hash, queue, list,? )
— Implements Irerator или ArrayIterator, чтоб можно было использовать в конструкции foreach
— Serialize/Unserialize ????? или hash2array/array2hash, map2array/array2map etc…

Я на досуге проанализирую все комментарии и составлю план будущего рефакторинга.
Легкая реализация judy массивов? У каждого конечно свой опыт, но мне оно видится не таким простым. В PHP сериализаторах judy ни в одном нет.

Я себе запиливал key-value хранилище на shm (по принципу slab-ов) в ipc на PHP и оно пахало раза в 4 быстрее, чем mamcached по unix socket. На сях как расширение нужно думать получилось бы выжать больше. В итоге все забросилось в довольно черновом варианте. На этой стадии вылезла только одна проблема. При записи лочить весь сегмент совершенно не хотелось, хочется лочить только конкретный key и связанные с ним куски памяти. Но если использовать семафоры, то их просто не хватает под мою задачу. А лок сервер который мог бы жить в однопоточном режиме внутри php-fpm мастер процессе я найти не смог.
да с локами еще тот геморой, я бы лочил весь слаб. А слабы делал небольшими, элементов на 64 -128 не больше. А в принципе ты прав — от задачи зависит.
Не всегда можно юзат слабы небольшого размера. Проблему лока решал через финт ушами. Что нужно для быстро лока? Имхо — атомарность, гарантирующая консистентность данных (актуально когда у нас размер данных хранящихся по key изменился и его нужно перетаскивать в другой slab) и отсутствие блокирования в коде приложение на вызове. Единственный адекватный вариант к которому удалось прийти, это shmop_open с флагом n (получение лока — создание сегмента, снятие лока — удаление сегмента). Если создаваемый сегмент уже есть, то управление в PHP код возвращается тут же. И можно либо сгенерировать ошибку, либо немного обождать и повторить попытку залочится. После n попыток генерим ошибку и завершаемся. А когда лочимся, то в созданный сегмент пишу unix timestamp. Нужно для автоматического снятия лока (сравнивая текущее время с записанным в сегменте) если процесс его создавший сдох и не удалил сегмент.

Минус тут в жесткой схеме. С каждым значимым куском памяти в shm я ассоциирую определенный shm_id и при локе использую именно его. А это int, т.е. диапазон не очень на самом деле большой. Другой минус — приложение по сути эксплуатирует shm единолично, но в системе ipc нужен и другим сервисам, postgresql к примеру. Но более адекватной схемы из самого PHP найти не удалось. Поэтому как ни крути нужно выходит на уровень си и лок сервер в мастер процессе.

А какие проблемы получились по материалам изложенным в презентации?
конкретно по сторажу проблем не было, так как использоват реализацию tree из Tokyo
если не считать проверки на балансировку дерева по истечения интервала или выполнение DELETE > 10%

заморочки получились в правильной обязке libevent работающей на n потоков. в общем до ума на 100% не довел, а познакомился с Тарантулом, понял что он именно то что мне нужно и эффективнее моего сторожа и забил. В итоге приобрел хороший опыт.

Что касается блокировок, то в случае INSERT/DELETE просто делал блокировку через mutex.
на очень больших нагрузках не тестировал, но синтетические тесты показали не плохую производительность. Возможно и стоило довести до ума…

Ваши коллекции — вещи сами по себе. Создать, заполнить последовательно по одному ключику, вынуть по ключику. И всё.

Как предлагается обрабатывать коллекции как единое целое: сортировать, преобразовывать, конвертировать, фильтровать? Стандартные функции массивов принимать ваши коллкции не будут. Конвертировать туда-сюда? Не выйдет из-за объектов-ключей, да и окончательно убьёт производительность. Или предлагаете ради каждой новой функции лезть в сорцы коллекции и реализовывать всё вручную? Так теряется весь профит от использования «библиотеки»: сам дописывай, сам тестируй, сам исправляй баги.

По вашим коллекциям даже нельзя пройтись с помощью foreach — нужно использовать изобретённые вами же методы. Отдать в какой-то код «снаружи» коллекции нельзя, они из станданртных интерфейсов только Countable поддерживают (коллекция, у которой можно вычислить размер, но нельзя получить элементы — лолшто?).

Похапэ и так производительностью не отличается, так вы ещё реализуете немало методов с помощью полного прохода, весь код array_search утыкан.

После просмотра функции getHash сразу возникают вопросы.

    public function getHash($value)
    {
        if (is_object($value)) {
            return spl_object_hash($value);
        }

        if (is_string($value)) {
            return md5($value);
        }

        if (is_array($value)) {
            $value = serialize($value);
        }

        return md5($value);
    }

Почему для объектов всегда используется spl_object_hash? А если у меня два объекта считаются равными, если их id совпадает?

Зачем для строк вычислять md5? Похапэшные массивы — и так хэштаблицы, не нужно вычислять хэши на двух уровнях. Только память и вычислительные ресурсы впустую расходуются.

Вызов serialize забавен. Понимаю, «нужно» все типы поддерживать, но не такой же ценой.

Насчёт осмысленности вызова md5 при целочисленных ключах вообще без комментариев. Это всё ради сохранения ручного порядка элементов что ли?

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

Ах да, и тестов нет. Для такого рода библиотек это критично.
>> Почему для объектов всегда используется spl_object_hash? А если у меня два объекта считаются равными, если их id совпадает?

— Это прикладная логика. Наследуйте карту и реализуйте getHash().

>> Зачем для строк вычислять md5? Похапэшные массивы — и так хэштаблицы, не нужно вычислять хэши на двух уровнях. Только память и вычислительные ресурсы впустую расходуются.

— Действительно как-то не подумал. Есть только небольшой вопрос: что будет, если не преобразовывать в md5 достаточно длинную строку? Например, в несколько десятков килобайт? Если это не страшно, то действительно есть смысл переделать.

>> Вызов serialize забавен. Понимаю, «нужно» все типы поддерживать, но не такой же ценой.

— В точку, «нужно». Более элегантного способа не нашел. Предложите что-нибудь?

>> Ах да, и тестов нет. Для такого рода библиотек это критично.
— Тесты действительно нужно разработать. Займусь этим.

Теперь о вопросах работы с фильтрацией, сортировкой и т. д.
Я считаю, что отсутствие данных функций есть моя вина. Я должен был их включить в пакет, но не включил на текущий момент. Думаю, что их наличие существенно увеличит полезность и привлекательность пакета. Я займусь этим в будущем. На текущий момент был собран минимальный функционал, который позволяет работать.
Наследуйте карту и реализуйте getHash()

По коллекции на каждый тип объекта? Шутить изволите? :) Почему в конструктор не передать ссылку на функцию или ещё как?

Есть только небольшой вопрос: что будет, если не преобразовывать в md5 достаточно длинную строку? Например, в несколько десятков килобайт? Если это не страшно, то действительно есть смысл переделать.

Не знаю, что будет, но явно будет не хуже, чем сейчас, когда каждый раз пересчитывается md5. :) Это уже оптимизировано до нас (надеюсь, по крайней мере).

Более элегантного способа не нашел. Предложите что-нибудь?

Если для поддержки массивов это единственный способ, то лучше их не поддерживать вообще. Тот, кто пользуется библиотекой, должен выбирать подходящие инструменты для задачи, и ваша коллекция в таких условиях — очевидно, не вариант. Ну или сделать для массивов передачу своей функции получения хэша обязательной — чтобы человек осознанно шёл на кривое решение с serialize.
>> По коллекции на каждый тип объекта? Шутить изволите? :) Почему в конструктор не передать ссылку на функцию или ещё как?

— Шутить, нет :) Я бы, пожалуй, все таки делал специализации, само собой, в умеренных количествах.

На счет предложения с конструктором — тоже неплохая идея. На сколько я понимаю, то в общем виде предложение выглядит как:
«Сделать IoC для функции getHash()»?
На счет строк — нужно будет попробовать. Я тоже надеюсь…
Извините за оффтоп, но подскажите, пожалуйста, в какие тэги брать текст комментариев?
О-о-о… Комментарии на хабре под весьма изощрённым тегом: <blockquote>цитата</blockquote>. Почему нет кнопки для цитирования — одному НЛО известно.

Да, при написании комментария есть ссылка «html-теги» — там всё перечислено.
Sign up to leave a comment.

Articles