Основные принципы GraphQL в качестве руководства (часть 1)

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

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

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

и) Иерархический

Первый принцип Principled GraphQL заключается в том, что API должен быть иерархическим. API должен иметь четко определенную схему, описывающую модель данных и ее отношения. Определив схему, клиенты могут перемещаться по графу данных структурированным образом, снижая риск избыточной или недостаточной выборки данных.

В нашем кодовом решении мы можем определить схему, включающую типы «Продукт» и «Пользователь», где продукт связан с создавшим его пользователем. Мы также можем определить запрос, который позволяет клиентам получать все продукты, связанные с конкретным пользователем, например:

type User {
  id: ID!
  name: String!
  products: [Product!]!
}

type Product {
  id: ID!
  name: String!
  description: String!
  price: Float!
  seller: User!
}

type Query {
  user(id: ID!): User
}

ii) Ориентированность на продукт

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

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

type Mutation {
  createProduct(name: String!, description: String!, price: Float!): Product!
}

iii) Строго типизированный

Третий принцип Principled GraphQL заключается в том, что API должен быть строго типизирован. Это означает, что API должен иметь четко определенную схему, определяющую модель данных и ее отношения. Используя строго типизированную схему, клиенты могут быть уверены, что запрашиваемые ими данные достоверны и непротиворечивы.

г) декларативный

Четвертый принцип Principled GraphQL заключается в том, что API должен быть декларативным. Это означает, что клиенты должны иметь возможность точно указывать, какие данные им нужны, и получать в ответ только эти данные. Делая API декларативным, клиенты могут снизить риск избыточной или недостаточной выборки данных.

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

query GetUserProducts($userId: ID!) {
  user(id: $userId) {
    products {
      id
      name
      price
    }
  }
}

в) Безопасный

Пятый принцип Principled GraphQL заключается в том, что API должен быть безопасным. Это означает, что API должен предоставлять надежные и детализированные механизмы аутентификации и авторизации, чтобы гарантировать, что только авторизованные клиенты могут получить доступ к данным. API также должен быть разработан с учетом требований безопасности, чтобы предотвратить такие атаки, как внедрение SQL и межсайтовые сценарии.

Таким образом, в этом случае мы можем определить механизм аутентификации, который требует от клиентов предоставления действительного токена доступа для доступа к API, например:

type Query {
  me: User!
}

type Mutation {
  createProduct(name: String!, description: String!, price: Float!): Product!
}

type User {
  id: ID!
  name: String!
  email: String!
}

type Product {
  id: ID!
  name: String!
  description: String!
  price: Float!
  seller: User!
}

input CreateProductInput {
  name: String!
  description: String!
  price: Float!
}

type AuthPayload {
  token: String!
  user: User!
}

type Mutation {
  login(email: String!, password: String!): AuthPayload!
  signup(name: String!, email: String!, password: String!): AuthPayload!
}

Конец части 1 😃

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

Следите за обновлениями!