- Şema neden bir sözleşmedir?
- Nesne tipleri ve alanlar: SDL ile yazım
- Null olmayan alanlar ve listeler: en çok yanlış anlaşılan kısım
- Enum, input ve kök tipler
- Interface ve union: ne zaman hangisi?
- Sürdürülebilir şema için tasarım ilkeleri
- Sık yapılan şema tasarımı hataları
- Bu beceriyi Mindset programlarında nerede çalışırsınız?
- Sık sorulan sorular
GraphQL şeması tasarlamak: tipler, null kuralları ve evrilebilir bir sözleşme
GraphQL şeması nasıl tasarlanır: SDL ile nesne tipleri, null olmayan alanlar, enum, input, interface ve union kullanımı ile sürdürülebilir şema ilkeleri.
Şema neden bir sözleşmedir?
GraphQL şeması, bir hizmetin sorgulanabilen bütün veri tiplerini tanımlar. İstekler bu şemaya göre doğrulanır ve çalıştırılır; istemci hangi alanı isteyebileceğini ve ne tür bir yanıt alacağını önceden bilir. Şema, ön yüz ve arka yüz ekipleri arasında yazılı bir sözleşme gibi çalışır: arka yüz henüz hazır değilken bile ön yüz şemaya bakarak geliştirme yapabilir.
Bu nedenle şema bir veritabanı çıktısı değil, bir ürün arayüzüdür. İyi tasarlanmış şema, istemcinin ihtiyaç duyduğu soruları kolay yanıtlar; kötü tasarlanmış şema sonradan yapılan her değişikliği kırıcı hale getirir.
Nesne tipleri ve alanlar: SDL ile yazım
Şema, şema tanımlama dili (SDL) ile yazılır. Şemadaki çoğu tip nesne tipidir ve alanlardan oluşur:
type Customer { id: ID! name: String! orders: [Order!]! }
type Order { id: ID! status: OrderStatus! customer: Customer! }
Alanlar argüman alabilir; argümanlar her zaman isimle verilir, zorunlu ya da isteğe bağlı olabilir ve varsayılan değer taşıyabilir. Örneğin bir alan, sayfalama için bir limit argümanı alabilir.
Dahili skaler tipler Int, Float, String, Boolean ve ID'dir. Skalerler yaprak değerlerdir, alt alanı yoktur. Tarih gibi ihtiyaçlar için özel skaler tanımlanabilir (scalar Date); bu durumda değerin nasıl serileştirileceğini ve doğrulanacağını uygulama belirler.
Null olmayan alanlar ve listeler: en çok yanlış anlaşılan kısım
GraphQL'de tipler varsayılan olarak boş (null) olabilir. Ünlem işareti (!) alanı null olmayan yapar: sunucu her zaman bir değer döndürmeyi taahhüt eder; çözümleyici null üretirse bir yürütme hatası oluşur. Liste için köşeli parantez kullanılır ve modifikatörler birleştirilebilir: • [String!]: liste null olabilir, ama içindeki öğeler null olamaz. • [String]!: liste null olamaz, ama öğeler null olabilir. • [String!]!: ne liste ne öğe null olabilir.
Boş bir liste, null olmayan liste için geçerli bir değerdir; yani GraphQL "en az bir öğe" şartı getiremez. Tasarım kararı şudur: alanı null olmayan yapmak istemciyi kolaylaştırır, ancak o alanı doldurması beklenen bir servis arızalandığında bütün üst nesneyi null'a çevirebilir. Dış servislerden ya da başarısız olabilecek kaynaklardan gelen alanları null olabilir bırakmak daha dayanıklıdır.
Enum, input ve kök tipler
Enum, bir alanı sabit bir değer kümesiyle sınırlar ve doğrulama ile belgelemeyi tip sistemine taşır:
enum OrderStatus { PENDING SHIPPED DELIVERED }
Serbest metin yerine enum kullanmak, istemcinin geçersiz durum göndermesini baştan engeller.
Yazma işlemleri için input nesne tipi kullanılır. Input tipleri yalnızca girdidir; çıktı tipleriyle karıştırılmaz ve alanları argüman alamaz:
input CreateOrderInput { customerId: ID! note: String }
type Mutation { createOrder(input: CreateOrderInput!): Order }
Her şema en az bir Query kök tipi sunmalıdır; Mutation ve Subscription isteğe bağlıdır. Bunlar sıradan nesne tipleridir, yalnızca giriş noktası rolü taşırlar. Mutation'ın bir çıktı tipi döndürmesi, istemcinin değişen nesneyi aynı istekte geri almasını sağlar.
Interface ve union: ne zaman hangisi?
Interface, uygulayan tiplerin içermesi gereken ortak alanları tanımlar. Birden fazla tip aynı alanları paylaşıyor ve istemci bunları ortak biçimde sorgulamak istiyorsa uygundur. Tipe özgü alanlar ise satır içi fragment ile istenir.
Union ise ortak alan tanımlamaz; yalnızca bir alanın hangi somut tiplerden biri olabileceğini söyler. Örneğin bir arama sonucu müşteri, sipariş ya da ürün olabilir: union SearchResult = Customer | Order | Product. Union'ın üyeleri somut nesne tipleri olmalıdır; sorgularda satır içi fragment gerekir ve __typename alanıyla somut tip öğrenilir.
Karar basittir: ortak alanlar varsa interface, yoksa ve sonuç farklı tiplerden oluşuyorsa union. Çok fazla soyutlama şemayı okunmaz hale getirir; yalnızca gerçek bir çok biçimlilik ihtiyacı olduğunda kullanın.
Sürdürülebilir şema için tasarım ilkeleri
- İstemci ihtiyacından başlayın. Ekranın ya da akışın hangi soruları sorduğunu yazın, şemayı bu sorulara göre biçimlendirin; veritabanı tablolarını birebir yansıtmayın.
- Adlandırmada tutarlı olun: tip adları tekil ve büyük harfle, alan adları küçük harfle başlayan camelCase, enum değerleri büyük harfle.
- Mutation girdilerini tek bir input nesnesinde toplayın; yeni alan eklemek mevcut istemcileri kırmaz.
- Şemayı eklemeli geliştirin: alan eklemek güvenlidir, alan silmek ya da tipini daraltmak kırıcıdır. Kaldırılacak alanı önce kullanımdan kaldırılmış (deprecated) olarak işaretleyin ve kullanım izlendikten sonra silin.
- Hata durumlarını tasarlayın: yetki yok, kayıt bulunamadı ve doğrulama hatası gibi beklenen sonuçları şemada ifade etmeyi değerlendirin.
- Büyük listeler için baştan sayfalama tasarlayın; sınırsız liste alanı, istemcinin tüm kayıtları çekmesine yol açar.
Sık yapılan şema tasarımı hataları
- Her alanı null olmayan yapmak; tek bir hata bütün yanıtı düşürür.
- Şemayı REST uç noktalarının kopyası gibi kurmak ve istemciyi çok sayıda küçük sorguya zorlamak.
- İç işleyişi (veritabanı kolon adları, tablo ilişkileri) şemada ifşa etmek; sonradan değiştirmek kırıcı olur.
- Serbest metin alanlarla durum tutmak, enum yerine string kullanmak.
- Belgelendirme eklememek: SDL'de tip ve alanlara açıklama yazmak, araçlarda otomatik tamamlamada görünür ve ekip içi anlaşmazlığı azaltır.
- Şemayı tek kişinin kafasında tutmak; değişiklik sürecini (inceleme, sürüm denetimi) tanımlamamak.
Bu beceriyi Mindset programlarında nerede çalışırsınız?
GraphQL ile API Geliştirme eğitimi, REST deneyimi olan arka yüz geliştiricilerine ve ön yüz ile arka yüz arasındaki sözleşmeyi yöneten teknik liderlere uygundur; Şema Tasarımı modülü bu sayfadaki tip sistemini uygulamalı olarak ele alır. Apollo GraphQL ile İstemci ve Sunucu Geliştirme eğitimi ise aynı konuyu Apollo ekosistemiyle, hem sunucu hem istemci tarafında çalışacak ekipler için kapsar; ilk modülü GraphQL temelleri ve şema tasarımına ayrılmıştır.
Kurumsal ekiplerde şema tasarım ilkelerinin ortak yazılı hale gelmesi, farklı ekiplerin eklediği alanların tutarlı kalmasını sağlar.
İlgili Mindset programı
GraphQL ile API Geliştirme
Sık sorulan sorular
GraphQL şeması hangi dille yazılır?
Şema, GraphQL şema tanımlama dili (SDL) ile yazılır. SDL'de type, enum, input, interface, union ve scalar anahtar kelimeleriyle tipler tanımlanır. Sunucu kütüphaneleri bu tanımı okuyup çözümleyicilerle eşleştirir. Şema önce SDL dosyası olarak yazılabilir (şema öncelikli) ya da kodla üretilebilir; her iki yaklaşımda da istemcinin gördüğü sözleşme SDL'dir.
Alanları null olmayan mı yoksa null olabilir mi yapmalıyım?
Sunucunun her zaman değer döndürebileceğinden emin olduğunuz alanları null olmayan yapın. Başarısız olabilecek dış servislerden ya da isteğe bağlı verilerden gelen alanları null olabilir bırakın. Çünkü null olmayan bir alan null üretirse hata üst nesneye kadar yayılır.
Input tipi ile nesne tipi neden ayrıdır?
Nesne tipleri çıktı içindir ve alanları argüman alabilir; input tipleri ise yalnızca girdi içindir ve alanları argüman alamaz. Girdi ve çıktı tipleri karıştırılamaz. Bu ayrım, yazma işlemlerinin girdisini açıkça tanımlamayı sağlar.
Şemada bir alanı silmek yerine ne yapmalıyım?
Alanı önce kullanımdan kaldırılmış olarak işaretleyin ve istemcilerin kullanımını izleyin. Kullanım kalmadığında silmek güvenlidir. Doğrudan silmek, o alanı sorgulayan istemcileri kırar. Eklemek ise genellikle kırıcı değildir. SDL'de bunun için deprecated yönergesi kullanılır ve yanına yerine geçen alanı belirten kısa bir neden yazılır.
İlgili rehberler
İlgili eğitimler
Kategori: Yazılım Geliştirme