Комментарии 11
Городить отдельный тип со своей ошибкой для такого простого поля, как email, кажется оверхедом, ведь это всего лишь строка.
Какая-то тут недосказанность в истории с PersonItem и PersonFullItem. У вас же наверняка есть кейсы, когда у объекта Х полей и лишь несколько из них появляются всегда. Получается, что все же придется идти на оверхед и заменять примитивные типы алгебраическими.
Не очень понял с чего вывод про наверняка) И все таки, что значит "появляются всегда". Если речь о том, что есть место в приложении, где мы показываем маленькую часть объекта - так GraphQL и нужен для этого, клиент просит только эти поля.
В реальности у нас все устроено как я описал тут. Кейс про email я выбрал для наглядности, основная проблема у нас была с вакансиями, которые показываем в откликах кандидата (их могу видеть все, но в саму вакансию перейти не могут). Вероятно нет сложных кейсов потому, что это все таки кабинет в рамках компании, а не сайт hh.ru, где есть поконтактный доступ (часть полей может быть скрыто, но и это не проблема, их то как раз можно целиком выделять в алгебраический тип блоком - например ContactsItem и ContactsError)
У нас же у компании либо куплен доступ ко всему кабинету, либо нет. А для отдельных ролей могут быть просто видны названия чужих вакансий, или наоборот не видны чужие кандидаты (если откроют по прямой ссылке такого)
можно целиком выделять в алгебраический тип блоком - например ContactsItem и ContactsError
Список полей предлагается делать или как? Можно пример?
Может не понял про список полей, но у кандидата будет поле contacts типа Contacts, как-то так:
union Contacts = ContactsItem | ContactsError
type ContactsItem {
items: Contact[]
}
type Contact {
type: ContactType #email,phone,...
value: String
}
type ContactsError {
errorType: ContactsErrorType
# тут тип, например "Неоплачен доступ", "Кандидат скрыл данные" и т.д
}
Да, могут быть разные блоки, еще например ФИО и день рождения, их можно целиком еще в один объект. Если прям хочется динамические блоки в зависимости от ролей, и динамически включать и выключать, то тут конечно придется уже наверное более синтетические списки этих самых полей в дженерном виде.
Пример достаточно топорный, там можно накручивать.. Могут быть полные и не полные контакты (будет три состояния, вообще недоступны, виден только часть, видны все). + со списками еще логика такая - выдаем то, что доступно тебе (когда запрашиваешь "мои вакансии", тут все как в обычном REST API)
Убираем обязательность из полей ответа. Клиент сам может решить, что ему запрашивать.
Пишем ошибку доступа в стандартный блок ошибок.
И не нужно заморачиваться с юнионами PersonItem/PersonError
.
вы путаете обязательность заполнения и ответа)
NonNull (или восклицательный знак) означает не обязательность ответа, а то, Что если вы его запросили, оно точно не null. И избавляться от этих пометок это самое последнее что хочется делать. Клиенту хочется знать что всегда заполнено, а на что ему надо обрабатывать null-ы
GraphQL на то он и нужен, что никакой обязательности ответов нет, запрашивай что хочешь (иначе смысл?)
ну и соответственно тот самый кейс - запросили email, выдали вам null
как вам понять недоступен он или не заполнен? В массив errors писать можно об этом, но это неудобно (нет строгой типизации в ошибках, просто набор полей, перечисление типов ошибок). Получается что контракт по ошибкам хранится где-то в другом месте, а о сущностях - в схеме. Хочется чтобы было единое место знаний - схема.
Не хватает пары примеров, какие конкретно ваши проблемы решил переезд на GraphQL
Хороший вопрос, но о причинах перехода (они же примеры, и они же в итоге и дали профит) описано в другой нашей статье https://habr.com/ru/company/hh/blog/677972/
Хорошая статья! Буду ждать следующий выпуск :half_troll:
GraphQL: доступ запрещен