Что за мода пошла? REST-like HTML CRUD

Проверенные VDS на SSD в Европе от $4 и России: Датацентр №1 от 199руб

Тема в разделе "Вопросы по теории программирования", создана пользователем Adelf, 5 апр 2016.

  1. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Каждая команда атомарна. Если у тебя в принципе нет никаких событий, привязанных на отдельно взятое действие типа rename, relocate, etc., то можно, в принципе, сделать это одной командой. Как я выше сказал, тут могут быть команды ChangeProfile { userId, name, location, ...} и BanUser { userId }. Ты уверен, что эти действия действительно так обязательно выполнять атомарно, только потому что это одна форма? Ты не встречал, например, форм, которые сразу применяют действие, там даже нет кнопки «Сохранить» (в ВК есть такое, по-моему)? Это чисто вопрос UI. Ну, в конце концов, можно обе команды запустить в одной транзакции БД, это будет специальный хак для UI. Но фактически с этим проблем нет: да, мы может обновить профиль, но зафейлим команду бана юзера. Что тут плохого?

    Можешь привести пример о чём ты говоришь?

    Ещё один момент, заставляющий задуматься: твоя форма отправляет большой скоп данных, вполне вероятно, что юзер изменится, пока ты редактируешь его. Тут мог бы помочь какой-нибудь optimistic lock, но повышается риск того, что даже на неконфликтные с точки зрения бизнес-логики действия форма будет сообщать о конфликтах (ты меняешь юзеру имя, а рядом кто-то его забанил).

    А если ты не используешь optimistic lock, то у тебя вообще будет код, который будет показывать, что ты, например, разбанил юзера (появляется соответствующее событие, сработают методы компенсации за бан и прочее), когда ты ничего такого не делал: просто в момент загрузки формы у тебя была снята галка, а соседний модератор успел забанить этого пользователя.

    Поэтому лучше, когда клиент в явном виде сообщает дифф изменений: набор команд, которые решил предпринять юзер. Явное лучше неявного. Если только мы не занимаемся обфускацией.
     
    Последнее редактирование: 5 апр 2016
    флоппик нравится это.
  2. WMix

    WMix герр M:)ller Партнер клуба

    Сообщения:
    5.847
    Ваш город:
    Berlin
    Address:
    Berlin, Germany
    Country:
    Location on Map:
    У меня crud в голом виде также редко встречается, чаще действие, но если вижу подобные формы, мне в голову сразу приходит голый генератор типа крад, ну и рест как оболочка но это так скушно. Пример денежных операций, из сегоднешнего. Форма типа кнопка на продукте, добавить продукт. Теперь мир вокруг: есть бюргеркинг с главным филиалом в берлине, который в итоге получит счет. Он выделил бюджет филиалу, который на эту кнопку нажмет и получит товар ( получатель). этот филиал прописан к оному из складов (поставщик). Немного запутанней, филлиал накидает много товаров в корзину, а заказ один. Бюджет не превышает по группам, (моющие средства/тряпки, салфетки/трубочки). После отправки заказа шаг назад либо сложный, звонки, откаты, либо даже невозможен. Есть дата заказа, есть туры когда транспорт едет, есть выходные и праздники. Это вероятнее всего только часть перечня, о чем нужно подумать. Но в итоге либо заказ, уменьшить бюджет, записать услугу, отправить заказ... либо извените и причины.
     
  3. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Отправка заказа, списание денег, запись услуги... Я правильно понимаю, что ты эти действия выполняешь в одной транзакции? Это удобно, биллинг лежит в той же БД. Но что если оказание услуги и, например, списание денег будут находиться на разных серверах? Представь, ты оформил заказ, и тут fatal error, не успел списать с удаленного сервера деньги. Что дальше?
     
  4. WMix

    WMix герр M:)ller Партнер клуба

    Сообщения:
    5.847
    Ваш город:
    Berlin
    Address:
    Berlin, Germany
    Country:
    Location on Map:
    Грубо говоря да, есть конечно разделенные запросы, а некоторые могут находится вне. Но основа от начала до коммита. В контроллере простой вызов, отправить. А дальше в зависимости от ситуации. Конечно рест тут как пришей кабыле хвост, но клиент на js и удобнее сказать put, на сервере инзерт, а вот в моделе начинаем по шагам разбираться. Ну получится тоже самое но из модели. Вот с фатал ничего не произойдет, если только базы разделенные, но там и подход иной. Но и это никаким боком к ресту или краду не относится. Это уже модель, не?
     
  5. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Возможно в твоём случае вся форма действительно принадлежит одному бизнес-действию. Моя основная мысль была в том, что формы не должны влиять на модель. Формы — это детали интерфейса. Бан может быть как галочкой в одной большой форме, так и отдельной кнопкой. Интерфейсно выглядит по-разному, но бизнес-действие одно: бан пользователя. Когда ты общаешься с менеджерами, тестерами, ты вряд ли говоришь «я поставил галку в форме редактирования пользователя»; ты обычно говоришь «я забанил пользователя», т.е. ты оперируешь бизнес-действиями и их гораздо больше, чем просто добавить/изменить/удалить.

    Есть ещё такое понятие, как task based UI как противопоставление CRUD-формам. Даже с точки зрения UX мне кажется, что task based обычно лучше, чем одна гигантская форма.
     
  6. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    6.671
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    Все-таки, давайте вернемся к теории. Сначала давайте вспомним, что REST является подмножеством RPC.

    Отделим котлеты от мух, и рассматривать протокол будем отдельно, а API моделей - отдельно. Они не связаны. Хочется их связать, и это представлено аксиомой, но объяснить почему никто не сможет потому что связи нет. Да, сейчас будет флейм на тему моей личности, и я его почищу :)

    Объединение rpc-запросов в bulk и цепочки - это оптимизация, а не суть протокола.
    Атомарность и локи - это свойства логики приложения, не связанные с протоколом. Распределенные транзакции надо рассматривать в контексте 2pc с известным ограничением, и в отдельной теме.

    Аналогично, отделяем котлеты от салата. Если при оформлении заказа появляется fatal error, не происходит ничего. У заказа остается неоплаченный статус, уведомление об ошибке во время оплаты попадает администратору, и вопрос решается в ручном режиме.
    С протоколом это не связано вообще.

    Я много лет использую json-rpc. Одновременно я использую и RESTful.
     
    Redjik нравится это.
  7. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.354
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Так никто же не против использования rest там, где он уместен.
    А вот если rest и activerecord поставить во главу угла и логически развить до полного мяу, получится StrongLoop, хипстерская модная тема, аж IBM купил за охуллиард. Антипаттерн на антипаттерне, просто полная жесть. :)
     
  8. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    6.671
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    Предполагаю, что причина в автогенерации кода. Простой RESTFul API можно нагенерировать, а RPC надо писать руками.
     
  9. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Отталкивайся от того, что нас не интересует анемичная модель. Нам нужна модель, которая реально отражает бизнес-действия.

    Если ты под автогенерацией ты понимаешь «взять сущность, её свойства и добавить к ним глаголы GET/POST/PUT/DELETE», то очевидно, что с rich model такое сделать невозможно. К тому же получается API низкого качества, который тоже по понятным причинам не отражает бизнес-действий. Про проблемы такого API я уже говорил выше.

    REST сам по себе не обозначает, конечно, что запросы применяются напрямую к модели. Существует промежуточный DTO-объект. Но проблема маппинга неявного DTO на явный набор бизнес-действий никуда не исчезает. И я за то, чтобы этим DTO-объектом была команда, а не состояние сущности.

    И эта мысль приходит не мне одному в голову:
    https://twitter.com/nicolopigna/status/708275214111653888
    https://groups.google.com/forum/#!topic/dddinphp/0SIRm90dIFI
    В последнем обсуждении пример Mathias'а на самом деле сводится к вырожденному случаю, когда мы по факту имеем а-ля JSON RPC. Я не против, если тот API, который вы называете REST, будет выглядеть именно так: POST /commands/ {"command": ..., "payload": ...}. Но когда говорят про REST обычно имеют в виду совсем другое.
     
  10. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    6.671
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    Конечно.
    Есть участок задач, которые надо сделать как можно дешевле, и поддерживать их не предполагается. А если и надо будет менять - то через много лет.
    MVP, CRUD SEO-полей сайта, редактирование постов в блоге.
    У денег есть цена - деньги в будущем гораздо дешевле, чем сегодня. Поэтому автогенерация бывает экономически выгодна.
    Это не общее правило, конечно, надо оценивать риски.

    REST for CRUD, RPC for commands, я бы сказал.
    POST /commands/ {"command": ..., "payload": ...} - это обычный RPC
     
  11. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.354
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    А ты уверен, что это самостоятельная сущность, а не коллекция ValueObject-ов, принадлежащая странице?
     
    MegaNuke нравится это.
  12. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    А с этим никто не спорит, просто я завёл речь не про такие задачи.

    Я просто не раз на форуме слышал про REST, как какой-то стандарт де-факто, как нечто по определению «правильное», я просто хочу развеять этот странный миф. Нужно лишний раз подумать, прежде чем в качестве API выбирать именно REST.

    Для появления обсуждения приходится иногда набрасывать, провоцировать, это да.
     
  13. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    6.671
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    Забыл я уже про этот старый тренд, а тут @Вурдалак напомнил.
    Тема эта была в апреле, а летом по стечению обстоятельств я вник в REST достаточно глубоко. Стандарты некоторых корпораций сейчас требуют реализацию API по REST. Все, что я написал в апреле - ламерство.
    Помню, я даже вынес этот вопрос на совещание комитета по архитектуре, и обсудить собралось человек 50.

    Для начала, REST - это нифига не протокол. REST - это
    Все слова важны. Это правила, которые ограничивают. Это гипермедиа.

    Нам надо забанить пользователя. Мы такие телепаты! Откуда ж мы узнали про пользователя, которого уже хотим забанить? Сначала мы получаем данные пользователя. Начинаем с запросов GET. В ответе на этот запрос будут ссылки на все ресурсы, которые нам доступны про этого пользователя.

    Хотим сменить статус. Откуда мы узнали о том, что у пользователя меняется статус? Из документации про API? Нет. В информации о пользователе будет или его статус, или ссылка на другой ресурс, который описывает его статус. Статус может быть отдельной сущностью, и его можно сохранять, если так спроектировать.

    Нифига. REST не ограничен методами HTTP 1.1. Спокойно делаем свой теплый ламповый метод BAN, если так хочется.
    Выделяются "HTTP-based RESTful APIs". В них для изменения состояния части ресурса можно использовать HTTP-метод PATCH.

    Транзакции. Отправка заказа, списание денег, запись услуги. Это все разные, несвязанные действия. В REST состояния нет. Не нравится - обойдитесь без REST, делайте свой 2PC.

    Пример, где REST очень удобен - доступ по API к разным каталогам. В REST API обычно делается постраничная разбивка, и в ответ включают ссылки на другие страницы.
    Клиентские модули есть во многих фреймворках, их можно искаропки использовать со всеми API, остается дописать обработку данных.
     
    Последнее редактирование: 12 окт 2017 в 03:26
  14. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.354
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    @grigori, тут произошла очень частая история, когда изначальный смысл потерялся и все свелось к тупой фигне. Самоадресацию мало кто осилил, да и я бы не сказал, что она часто нужна. Все свелось к примитивной модной штуке с каждому понятным маппингом CRUD на HTTP methods.

    Мне это напоминает историю с hungarian notation, когда из изначально здравой простой идеи помечать префиксом "класс" - чтобы отличать деньги от яблок - стали префиксами помечать тип переменной, то есть сематическую информацию (что сложнее и требует думать головой) заменили на техническую (что просто, но тупо), и, да, это стало корпоративным стандартом.
     
    Последнее редактирование: 12 окт 2017 в 04:42
    grigori нравится это.
  15. antson

    antson на форуме с 2005 года Партнер клуба

    Сообщения:
    1.158
    Ваш город:
    Россия, Липецк
    Address:
    Lipetsk, Russia
    Country:
    Location on Map:
    прочел топик. в голове сумбур.
    а) топик реанимирован из-за переосмысления . сие дошло не сразу.
    б) вся суть как я понял
    - А почему гланды стали удалять через жопу?
    - Проктологам так удобнее !

    Перекурил. Смог сформулировать точнее.
    REST в CRUD - попытка засунуть модную вещь туда , где она по большому счету нафиг
    не нужна.
    Да есть моменты, которые из-за возможности кросс-доменных запросов get'ом,
    лучше решать методами похожими на рест. Но это не сам рест - который задуман для общения автоматизированных подсистем между собой.
     
    Последнее редактирование: 12 окт 2017 в 10:12
  16. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Только причём тут состояние?

    Мне кажется, каталог как-нибудь вывести можно и без HATEOAS. Да и навигация — это предпочтение клиента, разное количество выводимых ссылок, скролл вместо постраничной навигации и т.д.
    На мой взгляд, это выглядит интереснее, когда речь идёт про ограничение списка команд: объявление о продаже можно отредактировать, но только если оно не забанено; опубликовать статью можно, только если она одобрена и т.д. Как в конечном автомате у тебя есть состояние (нет, это не то состояние, о котором написано в Википедии) и список допустимых переходов.
     
  17. WMix

    WMix герр M:)ller Партнер клуба

    Сообщения:
    5.847
    Ваш город:
    Berlin
    Address:
    Berlin, Germany
    Country:
    Location on Map:
    это тоже состояние просто перзистентность меж сессионная и актеров несколько
    crud и rest никаким образом не влияет на домен, и даже в случае обновления полной публичной сущности могут быть правила в приватных полях регулирующие публикование
     
  18. Вурдалак

    Вурдалак Newbie

    Сообщения:
    5.974
    Ваш город:
    Russia, Moscow
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Позовите переводчика.
     
  19. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    6.671
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    я чуть позже напишу
     
  20. WMix

    WMix герр M:)ller Партнер клуба

    Сообщения:
    5.847
    Ваш город:
    Berlin
    Address:
    Berlin, Germany
    Country:
    Location on Map:
    состояние не зависит от сессий, несколько пользователей с различными ролями. (писатель записал, редактор отредактировал, публишер опубликовал -- 3 состояния, 3 актера)
    что еще не понятно, самоучка чтоль?