Kavramlar, Fikirler, Stratejiler
Kavramlar, Fikirler, StratejilerAlan ve direktif sürümü belirleme stratejileri

Alan ve direktif sürümü belirleme stratejileri

Lütfen önce Şemayı alan sürümlemesi aracılığıyla geliştirme kılavuzunu okuyun; bu kılavuz Gato GraphQL'deki "field versioning" özelliğini açıklamaktadır.

Gato GraphQL, alanların ve direktiflerin versionConstraint argümanını almasına izin vererek kullanılacak alan/direktifin belirli sürümünü (yani uygulamasını) seçmeyi sağlar:

query GetPosts {
  posts(versionConstraint: "^1.0") {
    id
    title(versionConstraint: ">=2.1")
    excerpt @strUpperCase(versionConstraint: "~1.5.3")
  }
}

versionConstraint argümanını belirtmediğimizde ne olmalıdır? Örneğin, aşağıdaki queries içindeki surname alanı hangi sürüme çözümlenmeli?

query GetSurname {
  account(id: 1) {
    # Hangi sürüm kullanılmalı? 1.0.0? 2.0.0?
    surname
  }
}

Burada iki endişemiz var:

  1. Hiçbiri sağlanmadığında kullanılacak varsayılan sürümü belirlemek
  2. İstemciyi aralarından seçim yapabileceği birden fazla sürüm olduğu konusunda bilgilendirmek

Bu endişeleri ele almadan önce, GraphQL'in queries çalıştırırken bağlamsal geri bildirim sağlama konusunda ne kadar iyi performans gösterdiğini öğrenmemiz gerekir.

Queries çalıştırırken bağlamsal geri bildirim sağlamak

GraphQL ile ilgili şu anda pek ideal olmayan bir durumu belirtmemiz gerekiyor: queries çalıştırırken iyi bağlamsal bilgi sunmuyor. Bu, deprecation'lar konusunda açıkça görülmektedir; deprecation verileri yalnızca Field ve Enum türleri üzerindeki isDeprecated ve deprecationReason alanları sorgulanarak introspection aracılığıyla gösterilmektedir:

{
  __type(name: "Account") {
    name
    fields {
      name
      isDeprecated
      deprecationReason
    }
  }
}

Yanıt şöyle olacaktır:

{
  "data": {
    "__type": {
      "name": "Account",
      "fields": [
        {
          "name": "id",
          "isDeprecated": false,
          "deprecationReason": null
        },
        {
          "name": "name",
          "isDeprecated": false,
          "deprecationReason": null
        },
        {
          "name": "surname",
          "isDeprecated": true,
          "deprecationReason": "Use `personSurname`"
        },
        {
          "name": "personSurname",
          "isDeprecated": false,
          "deprecationReason": null
        }
      ]
    }
  }
}

Ancak deprecated bir alanı içeren bir queries çalıştırıldığında…

query GetSurname {
  account(id: 1) {
    surname
  }
}

...deprecation bilgisi yanıtta görünmeyecektir:

{
  "data": {
    "account": {
      "surname": "Owens"
    }
  }
}

Bu, queries çalıştıran geliştiricinin şemanın güncellenip güncellenmediğini ve herhangi bir alanın deprecated olup olmadığını öğrenmek için aktif olarak introspection queries çalıştırması gerektiği anlamına gelir. Bu durum… ara sıra yaşanabilir mi? Büyük olasılıkla hiç yaşanmaz mı?

GraphQL API'sinin deprecated alanları içeren queries çalıştırırken deprecation bilgisi sağlaması, eski queries'lerin revize edilmesine yönelik büyük bir iyileştirme olurdu. Bu bilgi ideal olarak errors'dan sonra ve data'dan önce görünen yeni bir üst düzey deprecations girdisi altında verilebilir (spec'in yanıt formatı için önerisi izlenerek).

Bir deprecations üst düzey girdisi spec'in parçası olmadığından, Gato GraphQL'in "Proactive Feedback" özelliği, protokolü gerektiği gibi genişletmeye olanak tanıyan joker üst düzey extensions girdisini kullanarak queries yanıtında daha iyi geri bildirim desteği ekler:

Queries yanıtındaki deprecation bilgisi

Sürümleri uyarılar aracılığıyla duyurmak

GraphQL sunucusunun deprecation'ları sağlamak için extensions üst düzey girdisini kullanabildini az önce öğrendik. Bu aynı metodolojiden, geliştiriciye bir alanın sürümlendirildiğini bildirdiğimiz bir warnings girdisi eklemek için yararlanabiliriz. Bu bilgiyi her zaman sağlamıyoruz; yalnızca queries'in sürümlendirilmiş bir alanı içerdiği ve versionConstraint argümanının eksik olduğu durumlarda.

Bir alan için varsayılan sürümü tanımlamak

Uygulayabileceğimiz çeşitli yaklaşımlar vardır; bunlar arasında şunlar sayılabilir:

  1. versionConstraint'i zorunlu kılmak
  2. Belirli bir tarihe kadar varsayılan olarak eski sürümü kullanmak; o tarihte yeni sürüm varsayılan hale gelir
  3. Varsayılan olarak en son sürümü kullanmak ve queries geliştiricilerini hangi sürümü kullanacaklarını açıkça belirtmeye teşvik etmek

Bu stratejilerin her birini inceleyelim ve bu queries çalıştırıldığındaki yanıtlarına bakalım:

query GetSurname {
  account(id: 1) {
    surname
  }
}

1. versionConstraint'i zorunlu kılmak

Bu en açık olanıdır: alan argümanını zorunlu hale getirerek istemcinin sürüm kısıtlamasını belirtmemesini engellemek. Böylece sağlanmadığı her durumda queries bir hata döndürecektir.

Queries çalıştırıldığında şu yanıt alınır:

{
  "errors": [
    {
      "message": "Argument 'versionConstraint' in field 'surname' cannot be empty"
    }
  ],
  "data": {
    "account": {
      "surname": null
    }
  }
}

2. Yeni sürümün varsayılan hale geldiği belirli bir tarihe kadar eski sürümü varsayılan olarak kullanmak

Yeni sürümün varsayılan olacağı belirli bir tarihe kadar eski sürümü kullanmaya devam etmek. Bu geçiş süresinde, queries geliştiricilerinden o tarihten önce queries'deki yeni extensions.warnings girdisi aracılığıyla eski sürüme açıkça bir sürüm kısıtlaması eklemelerini istemek.

Queries çalıştırıldığında şu yanıt alınabilir:

{
  "extensions": {
    "warnings": [
      {
        "message": "Field 'surname' has a new version: '2.0.0'. This version will become the default one on January 1st. We advise you to use this new version already and test that it works fine; if you find any problem, please report the issue in https://github.com/mycompany/myproject/issues. To do the switch, please add the 'versionConstraint' field argument to your query (using Composer's semver constraint rules; see https://getcomposer.org/doc/articles/versions.md#writing-version-constraints): surname(versionConstraint:\"^2.0\"). If you are unable to switch to the new version, please make sure to explicitly point to the current version '1.0.0' before January 1st: surname(versionConstraint:\"^1.0\"). In case of doubt, please contact us at name@company.com.",
    ]
  },
  "data": {
    "account": {
      "surname": "Owens"
    }
  }
}

3. En son sürümü kullanmak ve kullanıcıları hangi sürümü kullanacaklarını açıkça belirtmeye teşvik etmek

versionConstraint ayarlanmadığında alanın en son sürümünü kullanmak ve queries geliştiricilerini hangi sürümün kullanılması gerektiğini açıkça tanımlamaya teşvik etmek; yeni bir extensions.warnings girdisi aracılığıyla o alan için mevcut tüm sürümlerin listesini göstermek:

Queries çalıştırıldığında şu yanıt alınabilir:

{
  "extensions": {
    "warnings": [
      {
        "message": "Field 'surname' has more than 1 version. Please add the 'versionConstraint' field argument to your query to indicate which version to use (using Composer's semver constraint rules; see https://getcomposer.org/doc/articles/versions.md#writing-version-constraints). To use the latest version, use: surname(versionConstraint:\"^2.0\"). Available versions: '2.0.0', '1.0.0'.",
    ]
  },
  "data": {
    "account": {
      "surname": "Owens"
    }
  }
}

Direktiflerin sürümlenmesi

Direktifleri sürümlemek için aynı stratejileri kullanabiliriz. Örneğin, sürüm kısıtlaması sağlanmadan queries çalıştırıldığında:

query {
  post(by: { id: 1 }) {
    title @strTitleCase
  }
}

Kullanılacak varsayılan bir sürüm varsayılabilir ve geliştiricinin queries'i revize etmesi için bir uyarı mesajı üretilebilir:

Sürüm kısıtlamaları olmadan sürümlendirilmiş bir direktif sorgulamak