Takip et

GraphQL Tip Sistemini Anlamak

GraphQL Tip Sistemini Anlamak GraphQL, modern API geliştirme dünyasında veri sorgulama ve manipülasyonu için güçlü ve esnek bir yaklaşım sunar.

GraphQL Tip Sistemini Anlamak

GraphQL, modern API geliştirme dünyasında veri sorgulama ve manipülasyonu için güçlü ve esnek bir yaklaşım sunar. REST API’lerinin aksine, GraphQL’de istemciler tam olarak ihtiyaç duydukları veriyi tek bir istekte talep edebilirler. Bu esnekliğin ve gücün temelinde, GraphQL’in en kritik bileşeni olan Tip Sistemi yatar. Tip sistemi, bir GraphQL API’sinin desteklediği tüm verileri ve işlemleri tanımlayan bir sözleşme gibidir. Bu makalede, GraphQL tip sisteminin derinliklerine inecek, temel bileşenlerini, ileri düzey özelliklerini ve geliştiricilere sunduğu avantajları detaylı bir şekilde inceleyeceğiz.

GraphQL Tip Sistemi Nedir?

GraphQL tip sistemi, bir API’nin sunabileceği verinin şeklini, yapısını ve ilişkilerini tanımlayan bir dildir. Tüm GraphQL API’leri, belirli bir tip sistemi tarafından tanımlanan bir şema (schema) üzerinde çalışır. Bu şema, istemci ile sunucu arasında bir köprü görevi görür ve her iki tarafın da hangi verilerin mevcut olduğu, nasıl sorgulanabileceği veya değiştirilebileceği konusunda net bir anlayışa sahip olmasını sağlar.

Tip sistemi, aşağıdaki temel işlevleri yerine getirir:
* Veri Doğrulama: İstemciden gelen sorguların ve mutasyonların şemaya uygun olup olmadığını kontrol eder.
* İç Gözlem (Introspection): İstemcilerin, mevcut tipleri ve alanları dinamik olarak keşfetmesini sağlar. Bu, GraphiQL veya Apollo Studio gibi araçların otomatik tamamlama ve dokümantasyon sağlamasına olanak tanır.
* Geliştirici Deneyimi: Tutarlı bir yapı sunarak geliştiricilerin API’yi daha kolay anlamasına ve kullanmasına yardımcı olur.
* API Evrimi: Şemanın kontrollü bir şekilde geliştirilmesine ve değişmesine olanak tanır, böylece istemciler üzerinde yıkıcı etki yaratmadan yeni özellikler eklenebilir veya eski alanlar kullanımdan kaldırılabilir.

Tüm bu yetenekler, GraphQL’in kendi Şema Tanımlama Dili (Schema Definition Language – SDL) kullanılarak tanımlanır. SDL, insan tarafından okunabilir ve yazılabilir, tip sistemini ifade etmek için özel bir sözdizimine sahiptir.

Temel Kavramlar

GraphQL tip sisteminin temelini oluşturan birkaç ana kavram vardır:

Şema (Schema)

Şema, bir GraphQL API’sinin kalbidir. Bir API’nin tüm veri tiplerini, sorgularını, mutasyonlarını ve aboneliklerini (subscriptions) tanımlayan bir sözleşmedir. Şema, üç özel “kök tip” ile başlar:
* Query (Sorgu): Veri okuma işlemlerini tanımlar. Bir istemci veri almak istediğinde, Query tipinin alanlarını kullanır.
* Mutation (Mutasyon): Veri yazma, değiştirme veya silme işlemlerini tanımlar. Veritabanında bir değişiklik yapmak istendiğinde bu tip kullanılır.
* Subscription (Abonelik): Gerçek zamanlı veri akışlarını tanımlar. Bir olay meydana geldiğinde istemcilere otomatik olarak veri gönderir.

Bir GraphQL şeması genellikle schema { query: Query, mutation: Mutation, subscription: Subscription } şeklinde tanımlanır ve bu kök tiplerin her biri, API’nin sunacağı özel işlemleri temsil eden alanlara sahiptir.

Şema Tanımlama Dili (Schema Definition Language – SDL)

SDL, GraphQL şemasını yazmak için kullanılan dildir. SQL veya JSON gibi diğer veri tanımlama dillerine benzer ancak GraphQL için özel olarak tasarlanmıştır. SDL, tipleri, alanları, argümanları ve yönergeleri (directives) tanımlamak için basit ve sezgisel bir sözdizimi sunar.

Örnek bir SDL tanımı:

type User {
  id: ID!
  name: String!
  email: String
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String
  author: User!
}

type Query {
  user(id: ID!): User
  users: [User!]!
  post(id: ID!): Post
  posts: [Post!]!
}

type Mutation {
  createUser(name: String!, email: String): User!
  createPost(title: String!, content: String, authorId: ID!): Post!
}

Bu örnek, User ve Post adında iki nesne tipi, bunların alanları ve bu tipleri döndüren veya argüman olarak alan Query ve Mutation tiplerini göstermektedir.

Temel Tip Türleri

GraphQL tip sistemi, verileri yapılandırmak için çeşitli temel tip türleri sunar:

Skaler Tipler (Scalar Types)

Skaler tipler, bir GraphQL sorgusunun en küçük, atomik veri birimleridir. Bunlar, daha fazla parçaya ayrılamayan temel değerlerdir. GraphQL, varsayılan olarak birkaç yerleşik skaler tip sağlar:
* String: UTF-8 karakter dizisi.
* Int: İşaretli 32-bit tam sayı.
* Float: Çift duyarlıklı kayan nokta sayısı.
* Boolean: true veya false.
* ID: Benzersiz bir tanımlayıcı (genellikle bir String olarak serileştirilir, ancak semantik olarak bir kimlik belirtir).

Özel Skalerler (Custom Scalars): Geliştiriciler, Date, URL, JSON veya EmailAddress gibi kendi özel skaler tiplerini de tanımlayabilirler. Bu, veri tipini daha spesifik hale getirmeye ve istemci ile sunucu arasında daha güçlü bir sözleşme oluşturmaya yardımcı olur. Özel skalerler, sunucu tarafında nasıl serileştirilecekleri, seri durumdan çıkarılacakları ve doğrulanacakları konusunda özel mantık gerektirir.

Örnek özel skaler tanımı:

scalar Date
scalar URL

Nesne Tipleri (Object Types)

Nesne tipleri, bir GraphQL şemasının temel yapı taşlarıdır. Uygulamanızdaki bir “şey”i veya bir “varlığı” temsil ederler ve bir dizi alana (fields) sahiptirler. Her alanın bir adı ve bir tipi vardır.

Örnek:

type User {
  id: ID!
  name: String!
  email: String
  posts: [Post!]! # Bir kullanıcının birden fazla gönderisi olabilir
}

* User: Bir nesne tipinin adıdır.
* id, name, email, posts: Bu tipin alanlarıdır.
* ID!, String!, String, [Post!]!: Bu alanların tipleridir. ! işareti, alanın her zaman bir değer döndürmesi gerektiğini (non-nullable) belirtir. [] köşeli parantezler, alanın bir liste (array) olduğunu gösterir. [Post!]! ise, bu alanın Post nesnelerinin bir listesi olduğunu ve listenin kendisinin null olamayacağını, ayrıca listedeki her bir Post öğesinin de null olamayacağını ifade eder.

Enum Tipleri (Enum Types)

Enum tipleri, belirli bir alan için izin verilen değerlerin sınırlı bir kümesini tanımlar. Bu, kodda sabit değerleri kullanmak yerine daha anlamlı ve hata olasılığı düşük bir yol sunar.

Örnek:

enum UserRole {
  ADMIN
  EDITOR
  VIEWER
}

type User {
  id: ID!
  name: String!
  role: UserRole! # Kullanıcının rolü bu enum değerlerinden biri olmalıdır
}

Bu örnekte, UserRole enum tipi, bir kullanıcının rolünün yalnızca ADMIN, EDITOR veya VIEWER olabileceğini belirtir.

Girdi Nesne Tipleri (Input Object Types)

Girdi nesne tipleri, mutasyonlara veya sorgulara karmaşık nesneleri argüman olarak iletmek için kullanılır. Normal nesne tiplerinden farklı olarak, girdi tiplerinin alanları argüman alamaz ve sadece skaler, enum veya diğer girdi tipleri olabilir.

Örnek:

input CreateUserInput {
  name: String!
  email: String
  role: UserRole = VIEWER # Varsayılan değer atanabilir
}

type Mutation {
  createUser(input: CreateUserInput!): User!
}

Burada CreateUserInput bir girdi nesne tipidir ve createUser mutasyonuna tek bir argüman olarak iletilir. Bu, birden fazla argümanı tek bir yapı altında gruplayarak mutasyon imzalarını daha düzenli hale getirir.

İleri Tip Türleri ve İlişkiler

GraphQL tip sistemi, daha karmaşık veri yapılarını ve ilişkileri modellemek için gelişmiş özellikler sunar.

Arayüzler (Interfaces)

Arayüzler, birden fazla nesne tipinin paylaşabileceği bir dizi alanı tanımlar. Bir nesne tipi bir arayüzü uyguladığında, o arayüzde tanımlanan tüm alanlara sahip olmak zorundadır. Bu, polimorfik sorgular yazmaya olanak tanır.

Örnek:

interface Node {
  id: ID!
}

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

type Product implements Node {
  id: ID!
  name: String!
  price: Float!
}

type Query {
  node(id: ID!): Node
}

Bu örnekte, User ve Product tipleri Node arayüzünü uygular ve her ikisi de id alanına sahiptir. node sorgusu, Node tipinde bir değer döndürebilir; bu, aslında bir User veya Product olabilir. İstemciler, bu tür polimorfik tipleri sorgularken “inline fragments” (... on) kullanarak belirli tiplere özgü alanları talep edebilirler:

query GetNode($id: ID!) {
  node(id: $id) {
    id
    ... on User {
      name
      email
    }
    ... on Product {
      price
    }
  }
}

Birlikler/Birleşimler (Unions)

Birlikler, bir alanın farklı nesne tiplerinden herhangi birini döndürebileceğini belirtir, ancak arayüzlerin aksine, bu tiplerin ortak alanlara sahip olması gerekmez. Birlikler, genellikle bir arama sonucunun farklı türde öğeler içerebileceği veya bir hata tipinin farklı hata nesneleri olabileceği senaryolarda kullanılır.

Örnek:

type Book {
  title: String!
  author: String!
}

type Movie {
  title: String!
  director: String!
}

union SearchResult = Book | Movie

type Query {
  search(text: String!): [SearchResult!]!
}

Burada SearchResult bir birleşim tipidir ve ya bir Book ya da bir Movie döndürebilir. Sorgular yine “inline fragments” kullanır:

query SearchItems($text: String!) {
  search(text: $text) {
    ... on Book {
      title
      author
    }
    ... on Movie {
      title
      director
    }
  }
}

Şema İlişkileri ve Yönlendiriciler (Directives)

GraphQL tip sistemi, alanlar ve argümanlar aracılığıyla karmaşık ilişkileri tanımlamanın yanı sıra, şemaya meta veri eklemek ve çalışma zamanı davranışını etkilemek için yönergeler kullanır.

Alanlar ve Argümanlar (Fields and Arguments)

Her nesne tipinin, kendi tipine ve isteğe bağlı olarak argümanlara sahip alanları vardır. Argümanlar, istemcilerin bir alanın döndürdüğü veriyi filtrelemesine veya şekillendirmesine olanak tanır.

Örnek:

type User {
  id: ID!
  name: String!
  posts(limit: Int, offset: Int): [Post!]! # posts alanı limit ve offset argümanlarını alıyor
}

Bu örnekte, posts alanı, bir kullanıcının tüm gönderilerini döndürmek yerine, limit ve offset argümanları aracılığıyla sayfalandırılmış bir alt kümesini döndürebilir. Argümanlar varsayılan değerlere de sahip olabilir: posts(limit: Int = 10): [Post!]!.

Yönlendiriciler (Directives)

Yönlendiriciler, GraphQL şemasına veya sorgularına meta veri eklemek için kullanılan özel işaretlerdir. @ sembolü ile başlarlar. GraphQL, birkaç yerleşik yönergeye sahiptir:
* @include(if: Boolean): Belirli bir alanın veya parçanın yalnızca if argümanı true ise sorguya dahil edilmesini sağlar.
* @skip(if: Boolean): Belirli bir alanın veya parçanın if argümanı true ise sorgudan atlanmasını sağlar.
* @deprecated(reason: String): Bir alanın veya enum değerinin kullanımdan kaldırıldığını belirtir ve genellikle bir gerekçe sağlar. Bu, API evrimi için çok önemlidir.

Örnek:

type Post {
  id: ID!
  title: String!
  content: String @deprecated(reason: "Use the 'body' field instead.")
  body: String
}

Geliştiriciler ayrıca kendi özel yönergelerini de tanımlayabilirler. Özel yönergeler, şema dönüşümleri, yetkilendirme kontrolleri veya çalışma zamanı davranışlarını değiştirmek gibi güçlü senaryolar için kullanılabilir.

Tip Sisteminin Avantajları

GraphQL tip sistemi, geliştiricilere ve API tüketicilerine bir dizi önemli avantaj sunar:

Veri Doğrulama (Data Validation)

Tip sistemi, hem istemci tarafında (sorgular oluşturulurken) hem de sunucu tarafında (sorgular yürütülürken) otomatik veri doğrulaması sağlar. Bu, yanlış tiplerde veri gönderilmesini veya alınmasını engeller, böylece hata oranını azaltır ve daha sağlam uygulamalar oluşturulmasına yardımcı olur.

İç Gözlem (Introspection)

GraphQL’in en güçlü özelliklerinden biri iç gözlemdir. Şema, kendisi hakkında bilgi edinmek için sorgulanabilir. Bu, GraphiQL gibi araçların otomatik olarak API dokümantasyonu oluşturmasına, sorgu alanlarını otomatik tamamlamasına ve potansiyel hataları vurgulamasına olanak tanır. Geliştiricilerin API’yi öğrenme ve kullanma süresini önemli ölçüde kısaltır.

Geliştirici Deneyimi (Developer Experience)

Tutarlı ve iyi tanımlanmış bir tip sistemi, geliştiricilerin API ile etkileşimini basitleştirir. İstemci tarafında, tip bilgisi sayesinde kod üretimi (code generation) yapılabilir, bu da sorguların ve mutasyonların güvenli bir şekilde oluşturulmasını sağlar. Sunucu tarafında, tip sistemi, resolver’ların doğru veri tiplerini döndürmesini garanti eder.

API Evrimi (API Evolution)

GraphQL, REST’in aksine, API versiyonlama ihtiyacını önemli ölçüde azaltır. @deprecated yönergesi gibi özellikler, eski alanları kullanımdan kaldırırken yeni alanlar eklemeye olanak tanır. İstemciler, ihtiyaç duydukları eski alanları kullanmaya devam edebilirken, yeni istemciler güncellenmiş şemadan yararlanabilir. Bu, API’nin sürekli olarak gelişmesini ve genişlemesini sağlar.

Güvenlik (Security)

Tip sistemi, istemcilerin yalnızca şemada tanımlanan verilere erişebilmesini sağlar. Bu, kötü niyetli veya yanlış biçimlendirilmiş sorguların sunucuya ulaşmasını ve beklenmeyen davranışlara yol açmasını engeller. Ayrıca, tip sistemi, yetkilendirme mantığının belirli alanlara veya tiplere uygulanmasını kolaylaştırır.

Tip Sistemini Tasarlarken En İyi Uygulamalar

Etkili bir GraphQL API’si oluşturmak için tip sistemini doğru bir şekilde tasarlamak kritik öneme sahiptir. İşte bazı en iyi uygulamalar:

Anlamlı Adlandırma (Meaningful Naming)

Tipler, alanlar ve argümanlar için açık, açıklayıcı ve tutarlı adlar kullanın. Bu, şemanın okunabilirliğini ve anlaşılırlığını artırır. PascalCase tipler için, camelCase alanlar ve argümanlar için yaygın olarak kabul görmüş adlandırma kurallarıdır.

Granüler Tipler (Granular Types)

Büyük, monolitik tipler yerine daha küçük, odaklanmış tipler oluşturun. Bu, şemanın daha modüler olmasını sağlar ve gelecekteki değişiklikleri kolaylaştırır. Örneğin, bir User tipinin tüm olası alanları içermesi yerine, UserProfile veya UserAddress gibi ayrı tipler oluşturarak daha iyi bir yapı elde edilebilir.

Gerekli Alanlar (Required Fields)

! (non-nullable) işaretini dikkatli kullanın. Bir alanın her zaman bir değere sahip olacağını garanti ediyorsanız ! kullanın. Ancak, bir alanın null olabileceği durumlar varsa, bunu belirtmek daha esnek bir API sağlar. Aşırı ! kullanımı, istemci tarafında gereksiz hata yönetimine yol açabilir.

Genişletilebilirlik (Extensibility)

Şemanızı gelecekteki büyüme ve değişiklikleri göz önünde bulundurarak tasarlayın. Yeni alanlar eklemeyi veya mevcut alanları kullanımdan kaldırmayı kolaylaştıracak bir yapı kurun. Arayüzler ve birlikler, gelecekte yeni tipler eklemeyi kolaylaştıran güçlü genişletilebilirlik mekanizmalarıdır.

Hata Yönetimi (Error Handling)

GraphQL’de hata yönetimi, genellikle sorgu sonucunun errors dizisinde döndürülür. Ancak, daha spesifik hata durumlarını modellemek için özel hata tipleri veya birleşim tipleri kullanmak, istemcilerin hataları daha iyi anlamasına ve işlemesine yardımcı olabilir. Örneğin, bir mutasyonun başarılı bir sonuç veya belirli bir hata tipi döndürebileceği bir birleşim tanımlanabilir.

Versiyonlama Yerine Evrim (Evolution over Versioning)

GraphQL’in @deprecated yönergesini kullanarak API’nizi versiyonlamak yerine evrimleştirin. Bu, istemcilerin eski API’yi kullanmaya devam etmelerini sağlarken, yeni özelliklerin sorunsuz bir şekilde tanıtılmasına olanak tanır.

Sonuç

GraphQL tip sistemi, modern API geliştirmenin temel taşıdır. Veri tanımlama, doğrulama, iç gözlem ve API evrimi gibi kritik işlevleri yerine getirerek, hem sunucu hem de istemci tarafında geliştiriciler için eşsiz bir deneyim sunar. Skalerlerden nesne tiplerine, arayüzlerden birliklere kadar çeşitli tip türleri sayesinde, karmaşık veri modelleri basit ve sezgisel bir şekilde ifade edilebilir.

İyi tasarlanmış bir GraphQL şeması, güçlü, esnek ve sürdürülebilir bir API’nin temelini oluşturur. Geliştiricilerin tip sisteminin gücünü anlaması ve en iyi uygulamaları benimsemesi, GraphQL’in potansiyelinden tam olarak yararlanmalarını sağlayacaktır. GraphQL’in tip sistemi, sadece bir veri tanımlama aracı olmanın ötesinde, istemci ile sunucu arasında güvenilir bir sözleşme ve işbirliği platformu olarak hizmet vermektedir. Bu sayede, uygulamalar daha hızlı geliştirilebilir, daha az hata içerir ve zamanla daha kolay evrimleşebilir.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.