Pull to refresh
9
0
Send message

Спасибо за статью!

По-моему мнению: Eventual consistency - это когда через день/неделю/месяц/год после сбоев саг или других проблем тех поддержка выравнивает в базе консистентность данны.

Бэкэнд разработчики json-ы перекладывают, а девопсы - ямлы... все справедливо.

ИМО: хельм как раз норм штука для получения законченного кванта поставки продукта, допустим сервиса, решающий вопрос конфигурирования приложения.

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

Конечно это все дико выглядит, но мне показалось достаточно удобно (одни только хуки жизненного цикла установки чего стоят) + подсветка в Idea вполне сносная.

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

В примере с gql я указал дефолт, как вариант, там будет null и не будет филтрации, если оставить без дефолтов, конечно логику бэку нужно будет прописать, но это отдельная история.

В одном моменте это соглашения, в другом контракт, если бэк нарушит контракт, то сам же и пофейлиться

С харп не знаком, возможно кто-то его использует и применимость очень интересная, но на рынке найти готовых спецов будет сложно, с gql не очень, но он хоть маркетингово раскачан и на том им спасибо.

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

Не становится, но кто не хочет gql - можно как рест

Вкурсе, что json, только это типизируется по схеме. Суть, что схема жесткая, в json при ресте - нет

  1. Фильтрация и пагинация в долбанутых кейсах: допустим у нас есть замечательная структура:

{
  "profile": {
    "accounts": [{
      "number": "123",
      "title": "hi"
      }],
    "transactionsHistory": [{
      "description": "open that account",
      "date": ""
    }]
  }
}

Ну не подумали, что не желательно так делать. Какой будет выход, когда нужно будет в accounts и transactionsHistory пагинацию или фильтрацию? Причем не общую, а именно на каждую отдельно? конечно разделим методы, переведем новые клиенты на новые ручки, НО что предлагает gql?

До:

Query {

getProfile: Profile!

}

type Profile {

accounts: [Account!]!

recommendations: [Recommendation!]!

}

После:

type Profile {

accounts(page: Int = 0, size: Int = 10): [Account!]!

recommendations(page: Int = 0, size: Int = 10): [Recommendation!]!

}

Это backward compatible.

Ну на самом деле мы этим и занимаемся на бэке, просто затягивая технологии для повышения своего JSI (шутка, с долей правды).

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

  1. Обязательность полей: застолбив контракт как not null, то вы гарантировано получите из бэка консистентные данные, да, есть конечно в open spec required - но это больше соглашение, чем обязанность, в gql бэк сам обделается и ответит ошибкой.

  2. Строгая типизация: тут немного с другой стороны попробую показать. Вот у нас есть условно банковские счета и метод, который их возвращает. Как нам в rest (при использовании json) подчекрнуть тип? Я пока знаю только 2 способа, но оба упираются в поле. Давайте по-простому сделаем?

    {

    "type": "DEBI",

    "title": "any",

    "number": "1111",

    "balance": 1000.00

    }

    {

    "type": "CREDIT",

    "title": "any",

    "number": "1111",

    "balance": 1000.00,

    "availableCredit": 10000.00

    }

    Тут у нас только соглашение, что у json в котором поле type имеет значение CREDIT должен быть availableCredit, но не у json с type DEBIT.

    Как выглядит в gql?

    interface Account {

    title: String!

    number: Int!

    balance: Float!

    }

    type DebitAccount implements Account {

    title: String!

    number: Int!

    balance: Float!

    }

    type CreditAccount implements Account {

    title: String!

    number: Int!

    balance: Float!

    availableCredit: Float!

    }

    Может быть неочевидным, но второй вариант и может быть расширен еще другими типами и будет нести гарантии в контракте, что удобно и клиентам и бэку.

  3. Ошибки и graceful degradation: допустим бэк написал BFF на ресте и джоинит сам dto от других сервисов (конечно это такой себе вариант и лучше бы тогда CQRS использовать, НО реальность такова, что это достаточно дешевый и быстрый подход), как можно сообщить клиенту, что какую-то часть данных он не получит? Можно допустим кинуть ошибку и отдать, то что есть, можно ничего не отдавать, можно не отдавать данные, которые достать не получилось. В общем, доводить клиентов до истерии.

    Как решено в gql? те данные, при выборке которых произошел фейл - отдается ошибка, оставшиеся приходят клиенту, т.е. клиент осведомлен о том, что чего-то не хватает и принимает решение, как с этим работать, т.е. может отобразить ту часть данных, которую можно -> graceful degradation возможен без приседаний (пользуются ли этим? не всегда, клиенты привыкли получать 4хх или 5хх)

Подходить к любой технологии с энтузиазмом, потом разочаровываться и не находить до конца путей решения проблем - очень не конструктивный подход. Потом и рождаются статьи такого типа, по прочтению которой приходишь к выводу, что gql прям не очень.

Вопрос ведь в другом, оверхед есть, вопрос тех проблем, что решает gql. Любая технология решает одни проблемы добавляя другие.

Лучше брать то, что подходит.

Если мучаемся от просьб добавлять, изменять атрибутный состав, то с рестом точно жить несколько не удобно. Тут даже не стоит вопрос об экономии сетевого трафика, тут вопрос про удобство предоставления апи и да, клиенты, кто не любит gql, могут смотреть на него как на простые рест запросы (чем оно и является).

Во всей этой истории есть главный момент: брать нужно то, с чем может команда совладать, будет готова к минусам подхода, ну и закроет свои проблемы.

В небольших проектах и небольших командах принесет скорее боль из-за сложности входа и решения проблем. В. Больших (особенно с развесистыми струткрами) скорее даст гибкость и независимость команд разработки (кстати всякие там api first ложиься достаточно не плохо в gql). Опять же большой и нагруженный проект, ну тут что, много денег, много команд, хоть рест, хоть json-rpc (я думал он rip), хоть grpc.

Видимо оригинальный автор 3 года как-то странно работал с GraphQL, проблем есть, но они решаются достаточно не сложно.

Про N+1 уже в 20-ом году были пути решения, а точнее тот же appollo gateway умеет в него, hasura (для прототипирования), тоже не болеет этим. Есть несколько другая проблема, которую решить сложнее (выборка из базы именно тех, полей, которые запросили), но и ее можно решить.

Про коды ответов - вообще не понял, 401 - ок тут нужно отдавать и да, это вполне себе возможно, 404 - отдавать в текущих реалиях уже не комильфо, 400 - зачастую связано с косяками передачи данных для запроса, но тут строгая типизация помогает.

Инструментарий и консоль разработчика - еще в 2019-ом был плагин для chrome, где видны все запросы.

Кастомные типы - в json та же трабла, только в gql хотя бы можно подчеркнуть на уровне схемы, что тут нужно что-то делать с этим типом, в json вообще может прийти что угодно.

Решение проблем деприкейтед полей через версионирование апи - можно, но спорно, 2 апи поддерживать сложнее, которые живут в конечном итоге годами и нужно вносить правки уже в 2-х источниках.

Злая проблема gql, на мой взгляд - отсутствие int64, только int32.... конечно можно заменить на float или кастомный тип, но иногда просто больно без него.

Пагинация наоборот в gql проще и лучше организовать в тех кейсах, когда есть вложенная структура с несколькими списками, а клиенту вот нужна пагинация (да еще и с фильтрацией) на каждой из этих коллекций (а кому-то и не нужна).

Конечно gql вообще не серебряная пуля и не лишен недостатков, но это как и любой другой инструмент - решает одни проблемы, добавляет другие.

Реально брать не стоит для небольших приложений с одним клиентом (веб) да монолитом, но точно стоит брать, когда система это несколько команд разработки, MSA, да еще и клиентов несколько видов (2 МП, веб, десктоп, да еще и сторонние подключаются).

Имхо: иногда оправдание следует за невозможностью наступить себе на горло и признать, что чего-то не знаешь. К сожалению эти переходы от "бог программирования" до "я ничего не знаю" даются болезненно, если даются вообще.

Спасибо за статью. С точки зрения рассмотрения нюансов решения проблем в конкурентной обработки и использования транзакций - отлично, но с точки зрения проблемы вопрос: почему не рассматривали что-то а-ля CQRS или labmda подхода?

В котром обычно 2 сообщения:

Мы к Вам вернёмся когда-нибудь...

Подскажите пожалуйста, почему отклонили?

За статью в таком же духе, но про мак меня попёрли из хабра))))

По-моему очень спорное решение. С одной стороны да, у нас в таком кейсе имеется возможность управлять жизненным циклом токена (точнее прерывать его заблаговременно), можем достаточно гибко реагировать на изменения прав пользователей, чуть меньше заморачиваться насчет авторизации.

C другой мы имеем 2 точки отказа + оверхед на походы в auth сревис (можно обмазать кэшeм, но тогда нужно решать 2-ую самую сложную проблему программирования), gateway имеет несколько отвественностей.

ИМХО: такой подход несомненно имеет место быть, только у меня пока к нему всё же больше вопросов.

Согласен. Тут я хотел накатать статью про это, но боюсь будет холиварной.

Суть моих заметок помимо того, чтобы дать какие-то достаточно простые вещи, но и триггернуть людей.

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

Information

Rating
Does not participate
Registered
Activity