Быстрый фильтр каталога для интернет-магазинов на основе битмапов Redis



    Не секрет, что каждый интернет-магазин должен помогать пользователям найти то, что им нужно. Особенно, если товаров у вас много (> 10). На помощь приходит каталогизация товаров, но разбить товары по категориям — полдела. Товары внутри категории нужно уметь фильтровать по их свойствам. Особенно, если товары у вас разношёрстные, например, одежда, электроника, ювелирные изделия и т.д. И тут любой разработчик, пишущий свой e-commerce продукт, сталкивается с неприятными реалиями жизни: у товаров могут быть совершенно разные свойства, у некоторых товаров они могут отсутствовать, некоторые товары по одному свойству могут попадать под разные значения (цвет платья то ли синий, то ли голубой, соответственно, неплохо бы его показать и по синему и по голубому цвету). Проще говоря, у вас EAV. Бывает ещё, что EAV вам диагностирует заказчик ближе к концу разработки, а то и просит добавить фильтр по динамическим свойствам уже после релиза.

    Вы начинаете почёсывать за ухом, понимая, что в реляционную модель у вас ничего не укладывается, вы же уже выбрали MySQL в качестве СУБД, если вы хороший веб-разработчик, или, может, PostgreSQL, если вы про него читали, а адепты разных корпораций могут вообще выбрать их продукты, никто не запрещает. Чаще всего, тем не менее, это всё RDBMS, и динамические свойства туда вкручиваются не очень просто (читай: сложно), не каждому это под силу.
    Вот, для примера, маленький кусочек диаграммы БД у популярной e-commerce платформы Magento:

    (по клику в полный размер)

    Вот и перед нами была поставлена задача сделать такой фильтр каталога для ювелирного магазина. А свойства у товаров у нас тогда вообще лежали в json-е в MySQL, т.к. нужны были только на странице самого товара и нигде более. Немного улучшало наше положение то, что это был ювелирный интернет-магазин, и свойства в нём можно было установить изначально, такие как размер кольца, тип металла, цвет металла, вставка. Тем не менее, полученное решение универсально, доработать код можно легко под полностью динамические наборы свойств у товаров.
    Решено было, что менять половину БД и больше половины кода для добавления фильтра не есть хорошо, поэтому на помощь мы позвали in-memory key-value storage called Redis, в частности, его крутую возможность работать побитово со строками, операции: SETBIT, GETBIT, BITOP, BITCOUNT. О значении команд легко догадаться не заглядывая в документацию.

    Схема хранения фильтров в Redis была следующей:
    1. Один ключ — это одно значение свойства товара, например, size-18: или color-red:
    2. Данными в каждом ключе являлся битмап длиной N бит, где N — количество товаров всего в магазине. Соответственно, позиция бита в битмапе — это ID товара, а сам бит показывает, принадлежит ли данный ID фильтру с таким значением.

    Пример, для лучшего понимания:
    ID товаров (позиция бита) ID: 1 ID: 2 ID: 3 ID: 4 ID: 5
    redis-key redis-value
    size-17: 0 0 1 0 1
    size-18: 1 1 0 0 0
    size-19: 0 0 0 1 0
    color-red: 1 1 1 0 1
    color-green: 0 0 1 1 1

    Таким образом, в редисе у нас 5 пар ключ-значение, т.к. имеем два фильтра — по цвету (2 варианта) и по размеру (3 варианта). В магазине всего 5 товаров, поэтому битмап состоит из 5 бит. Из таблицы видно, что товар с ID 2 — красного цвета, размера 18, а товар с ID 3 — размера 17, но имеет в себе как красный, так и зелёный цвет.
    Для применения фильтра к каталогу товаров, достаточно произвести операцию побитового AND для выбранных пользователем значений фильтров. Например, человек хочет товар зелёного цвета размера 18, тыкает в фильтре две галки, а мы делаем:
    BITOP AND result-key size-18 color-green

    после чего в result-key у нас будет лежать битмап, представлющий собой побитовое умножение этих двух битмапов. Нам остаётся только посчитать места, в которых у нас стоят единички, позиции единичек и будут ID товаров с заданными фильтрами:
    $bytes = str_split($result_key);
    $ids = []; // resulting product IDs
    for ($i = 0; $i < count($bytes); $i++) // iterate in bytes (8 products at once)
    	for ($j = 7; $j >= 0; $j--) // iterate over bits in current 8-products chunk
    		if ($bytes[$i] & (1 << $j)) // >0 if bit was 1, otherwise 0
    			$ids[] = 8*$i + (8-$j); // calculate product ID and append it


    Генерация битмапов происходит на моменте добавления / изменения товара в админке, в зависимости от имеющихся свойств товара мы делаем BITSET в нужный фильтр, и всё.

    плюсы такого решения:
    1) Жрёт мало памяти. У нас > 50000 товаров, около 100 значений фильтров, то есть 50000 * 100 = 5 000 000 бит = всего 625 килобайт памяти.
    2) Очень быстро. Сложность побитовой операции O(N), тем не менее, строки у нас не миллионами байт измеряются, а перемножить пару-тройку битмапов ио 50000 бит — задача пары микросекунд для процессора. Overall, в худшем случае (перемножение всех фильтров), замеряя разницу времени в PHP до отправки команды в REDIS и после получения результата — 40мс (это с доп. функцией из п.3, далее). Вполне реалтаймовая генерация страницы, для веба пойдёт. Если кажется много — просьба кешируйте результат, но нас это удовлетворило вполне.
    3) Возможность подсчёта кол-ва товаров в каждом фильтре и категории. Это стало полезным side-эффектом. Мы теперь можем посчитать количество товаров для каждого значения фильтра, доступное в данный момент. Да, это требует побитовое умножение текущего result-key (текущей выборки товаров) на каждое значение фильтра, а затем выполнение BITCOUNT. Мы это реализовали, теперь можем динамически скрывать фильтры с пустым множеством товаров (человек, выбрав платиновые кольца с бриллиантами, не видит фильтра по цене «до 3 000 рублей»).

    минусы такого решения:
    1) Невозможность закодировать фильтры типа range, например, где цену пользователь может фильтровать вручную влоть до рубля. Ну такие, с ползунками ОТ и ДО, знаете. Которые ещё на мобилах никогда не работают. В нашем магазине фильтр по ценам представлял из себя просто пять вариантов (до 3000, 3000-10000 и т.д.), соответственно, закодировали их как 5 битмапов price-0-3000:, price-3000-10000: и т.д.
    2) Необходимость передачи списка выбранных ID в MySQL для выборки их данных. Это, конечно, нехорошо, что мы из редиса кидаем список ID для выборки
    SELECT * FROM products WHERE id IN (....)
    

    Но, как оказалось, работает крайне быстро. В худшем случае вся страница каталога со всеми выбранными фильтрами для всех категорий генерировалась за 600мс, если не ошибаюсь. Пруф для нескольких фильтров:


    Итогом, прикрутить это дело оказалось очень быстро, биндинги Redis для PHP имеются, сам Redis очень примитивен и лёгок для освоения за один день.
    Поделиться публикацией
    Комментарии 75
      –3
      за постгрес минус
        +2
        Особенно в контексте того, что он умеет индексировать JSON.

        P.S. Тем неменее минусовать не стал, имхо, больше статей по Redis хороших и полезных.
          +3
          Я разве что-то плохое сказал про Postgres? По-моему вполне оригинально использовать постгресовский jsonb заместо Mongo или MySQL, и я бы даже так и сделал, тем более, что оно быстрее монги. Статья о другом, о том, как можно добавить поверх существующего кода Redis и получить быстрый результат.
            0
            я думаю дело в фразе «вы же уже выбрали MySQL в качестве СУБД, если вы хороший веб-разработчик, или, может, PostgreSQL, если вы про него читали»
              +1
              Ну юмор же, всем приятно знать, что он хороший веб-разработчик, даже если он кроме MySQL ничего и не пробовал :)
                +2
                ну тут дело не в том что вы использующих MySQL возвысили, а в том что адептов PostgreSQL принизили
                +3
                А вдруг подразумевалось, что хороший разработчик использует MySQL, а отличный разработчик хотя бы читал про PostgreSQL?
          +1
          Мы в своем магазине (сейчас около 8000 товаров) для хранения товаро перешли на MongoDB

          Это дало нам много преимуществ:

          1) отсутствие схемы позволяет добавлять поля товара на лету (например одни имеют вес, а другие количество таблеток в упаковке
          2) возможность хранить массивы — используем в случае когда товар может быть сразу в 2-3 и более категориях
          3) эти же массивы используем для фильтров

          Скорость поразительна, разумеется важно проиндексировать важные поля

            0
            Постгресовская скорость работы с jsonb ещё поразительнее: obartunov.livejournal.com/175235.html
              0
              Не буду спорить, просто с MongoDB был опыт работы в другом проекте, к Postres присматриваюсь, изучаю.
                0
                Это первый бенчмарк который обходит монгу из тех что я видел. Их столько много, всяких разных…
                0
                Но при этом это не снимает проблему именования атрибутов? На вскидку: менеджер для одного товара создал поле «цена» в том время как у всех товаров используется «розничная цена». Получаем два разных поля, так ведь?
                  0
                  Несмотря на многообразие полей у товаров, они все-таки жестко прописаны в административной панели. Я лишь описал наш кейс, пока что MongoDB нас полностью устраивает.

                  И цены у нас вручную нельзя прописать, они пересчитываются автоматически на основе прайсов поставщиков, равно как и скидки :)
                • НЛО прилетело и опубликовало эту надпись здесь
                  +3
                  Делал сложные фильтры на много тысяч товаров с помощью Elasticsearch, заодно получил возможность полнотекстового поиска по названию, описанию и составу, учитывая опечатки.

                  Ну а Postgres — это стандарт, зря вы так.
                    +1
                    Видимо мой юмор не очень понятен, но я всего-лишь сделал акцент на том, что MySQL в вебе используется чаще, чем Postgres, добавив чувства гордости большинству :) На то есть как исторические причины (уверен, вы знаете это и без меня), так и объективные. Так и быть, заменил предложение.
                      0
                      Веб — он бывает разным — если это домашний вордпрессик установленный за 5 минут на самом дешевом тарифе, то на хостингах постгрес если и есть то по запросу или «покупайте наш крутой VPS/VDS» и ставьте что хотите.

                      А на серьезных проектах — за последние лет 5 моих собеседований — про MySQL я не услышал ни одного вопроса. ни бекапы, ни репликации, вообще ни одного. PG, Oracle, MSSQL спрашивают много и активно, MySQL — остался только у хостеров или у тех, у кого задача с него смигрировать.
                        +1
                        Не думаю, что стоит снова начинать этот спор.
                          +1
                          Это не спор, а факты моего личного опыта на собеседованиях на хайлоадные проекты, куда мне было интересно попасть.
                          А спорить таки да, толку нету.
                          0
                          Begun (если не путаю), Mamba, Badoo используют mysql. Mysql как и Postgre – это инструменты, а эффективно их использует программист.
                            0
                            — богомерзские автоинкременты в mysql (до insert не выйдет получить id записи что в некоторых случаях делает жизнь болью и вынуждает использовать UUID)
                            — отсутствие возможности делать вложенные транзакции
                            — alter запросы не покрываются транзакциями (не шибко удобно для миграций).

                            Это тот минимум почему в некоторых задачах mysql в принципе не выйдет эффективно использовать и вам придется подстраиваться под инструмент и городить костыли.

                            А так… компаний много разных всяких, кто использует mysql или postgres (допустим skype на нем работал, а может и до сих пор).
                              –1
                              Я с mysql работаю 15 лет (а так же работал с MSSQL, Oracle), ни чего из перечисленного не создавало мне проблемы.

                              И ещё раз, это инструменты, не нравится эта лопата, возьмите другую, которая вам нравится. Бессмысленно ругаться на совковую лопату, что ей трудно копать огород, а на штыковую, что ею долго перекидывать кучу земли. А если вам нужно перекидать кучу гравия, то возьмите шахтёрскую…
                                0
                                Так я ж не спорю, у меня тоже с этим проблем не было пока не перешел на инструмент, где с этим все хорошо (хотя у оракла тоже с этим все хорошо). Как бы мелочь но приятно. По поводу выбора инструментов — это так, согласен. Просто что бы знать из чего выбирать люди должны лучше представлять что зачем.
                            –1
                            2.5 млн уникальных посетителей в сутки.
                            Без всякого постргесса

                            Устроит в качестве примера домашнего вордпрессика?
                              +1
                              В зависимости от характера взаимодействия с данными можно хоть на файлах такую нагрузку держать. Вы же понимаете, что все зависит от задачи.
                                –1
                                Почему вы от меня требуете понимания того, чего сами с оппонентами не понимаете. Если бы понимали, то высказываний ваших не было бы. А с дуру можно любую БД положить вы же понимаете это?

                                Что касается упомянутого случая, то это была БД примерно на 150 млн записей в основной таблице.
                          0
                          Как впечатления? Опечатки может строить из коробки или нужна настройка?
                            0
                            В простом случае достаточно поиграться с магическими константами :) Elastic из коробки много чего умеет и неплохо справляется.

                                'query': {
                                    'fuzzy_like_this': {
                                        'fields': ["name", "brand"],
                                        'like_text': query,
                                        'fuzziness': '0.5',
                                        'prefix_length': '1'
                                    }
                                }
                            
                              0
                              Кстати, да! Elastic одна из замечательных вещей, которая активно используется во всех наших проектах. Фильтрацию товаров с ее помощью делать просто сказка
                                0
                                А на сколько быстро работает? Сколько под себя ресурсов при этом хочет (Java же)? Фасетчатый поиск?
                                  +1
                                  Elastic я использую в двух разных проектах.

                                  Первый — крупный интернет-проект с >10млн пользователей, используется следовательно для поиска и фильтрации людей по куче полей (город, пол, возраст и т д). Нода работает на одном сервере с 32GB оперативной памяти, больше не требуется, интенсивность поиска доходит до 200 запросов в секунду, ответ в среднем менее 0.05ms. Обновление индекса выставлено каждые 30сек.

                                  В свое время стоял выбор между Sphinx и Elastic — выбор пал в пользу последнего. Поскольку метод обновления индекса в Sphinx не очень эффективен при таком большом количестве записей. Плюс удобный REST API, хорошая документация, сообщество, результаты тестирования, в общем, мы довольны. Руская морфология добавляется плагином, работает хорошо.

                                  Второй — небольшой интернет магазин с 7000 товарами, использую исключительно для поиска товаров. Здесь он работает также хорошо. Обновление индекса здесь, разумеется, моментальное. Единственное, потребление памяти конечно, не самое лучшее (после многих дней аптайма оно составляет 1.0-1.5GiB). Однако для нас всегда был приоритет в скорости, да и недорогого сервера с 8GB оперативки хватает за глаза.

                                  Насчет фасетчатого поиска — у Elastic с этим все отлично, вы можете комбинировать любые сложные вариации фильтров, как простых соответствий, так и range (для цен например). В общем, присмотритесь к Elastic и не жалейте память, вряд ли его использование будет экономически невыгодным, учитывая удобство, которое он предоставляет.
                          +3
                          А вы не думали над тем, чтобы просто вынести поиск в Elastic? Такие задачи туда как-раз очень хорошо подходят
                            0
                            Не просто думал, а даже смотрел в эту сторону. Но внедрить и настроить эластик — мне показалось задачей посложнее, чем разобраться с редис и добавить десяток строк кода.
                              0
                              Эластик очень хорош, вернее, даже не эластик, а solr, он очень хорошо умеет искать, группировать, выводить количество найденных совпадений.
                              Даже сам на интервалы разбивать и считать попадания в интервалы) Сам использую на около 30К товаров, летает.
                                +1
                                Извиняюсь, но мне казалось, что ElasticSearch основан на lucene, а не на громоздком Solr :) Разве это не так?
                                  –1
                                  Разве lucene и solr не одно и то же нынче?
                                    +2
                                    В моем пониманию ES выстроен на lucene. Solr в свою очередь так же построен на базе lucene.
                                    Т.е lucene это такая core сущность, на основе которой уже сделаны полноценные решения для поиска — Solr/ES. И как мне кажется ES появился, потому что Solr многим не нравился. Согласны?)
                                    PS: Я бы с радостью почитал где нибудь о истории развитии ES и Solr, так как сам не имею четкого представления об этом :(
                            0
                            С диапазонами — мое решение было таким habrahabr.ru/post/114113
                              0
                              Я кстати вашу статью читал когда думал, с диапазонами у меня проблемы не было, кому-то может и пригодится
                              0
                              Респект! Но почему бы не искать прямо по EAV-модели в SQL? Это же очень легко делается, даже по произвольному количеству атрибутов. Взяли первый атрибут, по таблице связей entity_id — value_id получили множество товаров (entity_ids), далее взяли второй атрибут и сократили это множество, далее взяли следующий атрибут… и так далее.

                              По каким причинам этот подход был отвергнут?
                                –1
                                EAV не жизнеспособна на сколько-нибуть значимых объемах товарной базы
                                  +1
                                  Ну как бы 400 000 товаров легко крутились. Так что я бы не делал таких громких заявлений.
                                  Конкретно — ulmart.ru его предыдущий дизайн сайта.
                                    0
                                    А причем тут дизайн и структура БД? Вы точно уверены что ulmart применяет EAV? Да и по скорости работы ulmart не показатель (по крайней мере в старой версии), я бы даже сказал наоборот.
                                      0
                                      Я точно уверен :)
                                      А у вас опять много громких заявлений.
                                        0
                                        Ну ок, но я как пользователь могу однозначно сказать, что ulmart очень медленно работает
                                          0
                                          текущую версию делали не мы. И даже при этом, я могу сказать что тормозит скорее клиентская часть.
                                          На нашем движке страницы отдавались не более чем за 0.5с

                                            0
                                            0.5 c это адски медленно, ну видимо у каждого свой порог медленно-быстро. У нас критическая планка для бекенда 100 мс.
                                      0
                                      Тут еще важно сколько у товаров свойств по которым возможны фильтры. Я не поверю, что выборка по 3-4 условиям из EAV таблицы в десятки миллионов записей с нагрузкой в 30-40 запросов в секунду будет отрабатывать за приемлемое время без танцев с бубнами.
                                        0
                                        Вера важна в определении технологии, безусловно. Однако Смекалка творит чудеса.
                                          0
                                          Зачастую смекалки уже недостаточно и нужно принципиально новое решение, с EAV вы как раз примерно очертили границы его возможностей, это 0.5 с. Запаса прочности у такого решения практически нет, да и масштабировать его трудно и затратно.
                                            0
                                            А что за проект? Где посмотреть?
                                              0
                                                0
                                                ну справедливости ради у вас там больше 100мс (по крайней мере сейчас)
                                                кстати то что выбранные значения исчезают немного расстраивает, посмотришь цвет, а твои фильтры уже сбросились наполовину
                                                  0
                                                  Вы смотрите ответа на http запрос, а я упоминал про бекэнд. Фильтр сбрасывается только если вы перешли в другой раздел.
                                                  0
                                                  По моим измерениям те же 0.5с на отдачу страницы.
                                                  Предлагаю закончить фехтование линейками и писюнами. Модель EAV достаточна для 99% интернет-магазинов рунета, удобна в поддержка и обладает многими преимуществами структурированности данных. Никто не спорит, что есть случаи, когда EAV не позволит выполнить требования. Ни EAV, ни другие решения не являются догмами, и ВСЕ имеют свои плюсы и минусы и области применения.
                                                    0
                                                    Согласен, но я в первом же комменте сказал про серьезные нагрузки.

                                                    Модель EAV достаточна для 99% интернет-магазинов рунета, удобна в поддержка и обладает многими преимуществами структурированности данных


                                                    Это можно отнести тогда ко всей статье в целом.
                                                    0
                                                    а какую схему использовали Вы, если не секрет?
                                          0
                                          с EAV как раз можно делать очень быстрые индексные ranged запросы.
                                            0
                                            Конкретику в студию. Сколько точно в граммах? И каков негативный, видимо, личный опыт использования данной модели?
                                          0
                                          Чтобы не делать SELECT * FROM IN () по БД, достаточно хранить минимальный набор инфы о товаре в том же редисе. Будет ещё быстрее выбирать, а минимум данных не сожрёт память.
                                          Особенно оно понадобится, когда будет миллион товаров и они будут шардиться по разным БД. Тогда с разных серверов MySQL страница будет собираться значительно дольше, чем из редиса.
                                            0
                                            Интересно, не пытался ли кто то сделать следующий шаг — сделать Redis единственной БД?
                                              0
                                              Сделать то можно, но профита особо не будет + можно огрести сильное усложнение бизнес-логики.
                                                +1
                                                Усложнение бизнес-логики? Ничуть. Просто не нужно делать декомпозицию данных в sql парадигме. Ну и по хорошему именно бизнес-логика со способом хранения данных напрямую не должна быть связана вообще ни как.
                                                  0
                                                  Не, я имел в виду вещи вроде foreign keys и транзакций (грубый пример в контексте сабжа — размещение заказа с последующим обновлением состояния продуктов на складе и прочее). Не спорю, все это можно сделать на уровне непосредственно кода (как и аналоги прочих join'ов и union'ов). Но вот именно про это я и говорил — будет очевидное усложнение логики, и тут уже фиг его знает, перекроет ли профит (в смысле времени выполнения) от простого in memory хранилища это дополнительное усложнение кода.
                                                  Возможно, тут эффективнее будет оставить хоть тот же mysql/postgresql но держать всю базу в памяти.
                                                    0
                                                    Разделите все на write model/read model и тогда все будет намного проще.
                                                      +2
                                                      я имел в виду вещи вроде foreign keys и транзакций

                                                      Еще раз повторюсь: "Просто не нужно делать декомпозицию данных в sql парадигме". Декомпозиция бизнес зачади в код и структуру данных должны при использовании noSQL решений проводиться вне парадигмы sql. Код приложения при этом будет другой, структура данных тоже будет другая. И делается это на фазе проектирования, т.е. еще до написания приложения. Если это выполняется после, то нужно очччень серьезное обоснование почему переезда приложения с sql -> nosql оправдан.
                                                  0
                                                    0
                                                    В статье рассказано о том как решить проблему масштабирования — вкраце, разбивать данные на блоки.
                                                    Интереснее почитать про разработку схему данных. У меня есть ощущение, что 95% всех проектов никогда не упруться в ограничение памяти для Redis, а вот модель данных станет проблемой с первой секунды проектирования.
                                                      0
                                                      Не станет проблемой, если думать в парадигме noSQL. Ясное дело, не все данные можно эффективно впихнуть в набор типов redis-а. Выбор в пользу редиса должен в том числе приниматься в контексте "могу ли я/команда думать в категориях nosql, а не РСУБД".
                                                        0
                                                        могу ли я/команда думать в категориях nosql, а не РСУБД


                                                        То есть вы предлагаете все держать в nosql? а зачем? Опять же такая же проблема будет как и со всякими mongodb — появляются связи между объектами (а они появятся) и уже начинаем кастыли ваять.

                                                        Могу ли я/команда построить систему без привязки к конкретной СУБД, лучше так. Тогда в РСУБД мы будем хранить все и в nosql агрегации данных для масшабирования.
                                                          0
                                                          То есть вы предлагаете все держать в nosql?

                                                          Нет, я этого не предлагаю. Я просто упираю на то, что не нужно пытаться на Х делать Y (например, писать на PHP как на Java). И тогда волосы будут относительно гладкими и шелковистыми.

                                                          построить систему без привязки к конкретной СУБД

                                                          Построить можно что угодно и на чем угодно. Вопрос, какими силами/матами/костылями. Я к тому, что если в проекте выбор пал на nosql, то нужно быть уверенным, что команда умеет его готовить. Потому что в противном случае может в итоге оказаться, что поверх nosql написали свою, кровью и соплями, простенькую РСУБД.
                                                          Всегда в подобных обсуждениях мне вспоминается Erlang. Требует разворота мозга для переходящих с С-подобных языков. Так и тут, nosql требует все же некоторого разворота мозга для эффективной работы. Но если такой разворот выполнить, то проблем с бизнес-логикой не будет.
                                                            0
                                                            писать на PHP как на Java

                                                            Вы о чем вообще? А как еще на PHP писать кроме как «как на Java»? Или вы имеете в виду что «не писать полноценный сервер на PHP»?

                                                            все же некоторого разворота мозга для эффективной работы

                                                            Да не требует он «разворота мозга», просто надо мыслить агрегациями данных. И для 90% проектов nosql может использоваться только как кеширующий слой, но не основная база данных (я не говорю о случаях когда мы храним независимые документы, логи и прочее, это я отношу к 10% задач).
                                                              0
                                                              полноценный сервер на PHP

                                                              Нет, я о другом. О том, что человек может PHP код, но делает это в парадигме Java. Так, как если бы он кодил на Java. Ну банально на вскидку — все гоняется через XML (конфиги, обмен данными), явное приведение типов, создание объектов на все-все-все.

                                                              просто надо мыслить агрегациями данных

                                                              И я о том же. Это и есть «разворот мозга».

                                                                0
                                                                Ну банально на вскидку — все гоняется через XML (конфиги, обмен данными), явное приведение типов, создание объектов на все-все-все.


                                                                Увы если делать по другому начинается адЪ. Не нужно конечно каждый инт или строку в объект заворачивать, но это нормально делать все объектами инкапсулируя поведение если мы практикуем ООП.

                                                                По поводу явного приведения типов — в php7 есть тайпхинтинг для скаляров, который в строгом режиме требует этого. И да это удобно для библиотек например). По умолчанию каст типов будет происходить автоматически, бросая иключения в случае потери данных.

                                                                Ну а конфиги в xml это рак, в основном юзают аннотации или yml.

                                                                PHP очень похож по семантике на Java/C#, он конечно не дотягивает до них (куда ему), и там есть странности, но писать на нем как на java это более чем нормально. Вопрос в том насколько надо упарываться и насколько люди придерживаются своему здравому смыслу.
                                                                  +1
                                                                  да ладно вам уже хватит тут разводить, уведомления на почту идут и идут)

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

                                              Самое читаемое