İçeriğe geç
academia.sh

Ders 10 / 14

Sürüm Yönetimi

Sürüm yönetimi, bir uygulamanın hangi yapısının hangi numarayla yayımlandığını ve istemcinin sunucuyla nasıl konuştuğunu düzenler. Ders, yalnız eski sözleşmeyi sunan sunucuda yeni sözleşmeyi isteyen bir özelliğin ne kadar çalıştığını ölçer.

Yayın Güncelleme

Bu derste

  • Sürüm numarası ile derleme numarasının farkını ve ikisinin kimin tarafından yönetildiğini açıklar
  • Anlamlı sürümlemede düzeltme, özellik ve uyumsuz değişikliğin numarayı nasıl artırdığını gösterir
  • İstemcinin istediği sunucu sözleşmesini yetenek olarak kurup özelliğin işlerliğini ölçer
  • İstemci sürüm numarasının tek başına işlerliği belirlemediğini ölçümle gösterir
İçindekiler

Önceki ders yapıyı tek bir derleme numarasıyla andı ve numaraya anlam yüklemedi. Gerçek bir uygulamada numara iki iş görür: kullanıcıya hangi sürümü kullandığını söyler ve ekibe hangi yapının hangi hatayı taşıdığını. Bu ders numaraların ne olduğunu, kim tarafından artırıldığını ve bir sürüm numarasının sunucuyla ilişkisini ele alır.

Kursun sorusu aynı kalır: bu koşulda bu özellik ne kadar çalışıyor? Bu derste koşulun kaynağı sunucudur. İstemci bir sözleşmeyi ister, sunucu ya o sözleşmeyi sunar ya da sunmaz.

Sürüm Numarası ve Derleme Numarası

Mobil bir uygulamada iki ayrı numara vardır ve ikisi sık karıştırılır.

Sürüm numarası insanın okuduğu numaradır. Mağaza sayfasında görünür, ayarlar ekranında yazar, destek ekibine “hangi sürümdesiniz” diye sorulduğunda söylenir. Sürüm numarasına ekip karar verir, çünkü numara bir anlam taşır: bu yayın önceki yayına göre ne kadar değişti.

Derleme numarası makinenin okuduğu numaradır. Mağaza, aynı sürüm numarasıyla yüklenmiş birden çok yapıyı birbirinden bu numarayla ayırır. Reddedilen bir yapının düzeltmesi aynı sürüm numarasını koruyabilir, ama derleme numarası artmak zorundadır. Bu numarayı önceki derste anlatılan teslimat hattı artırır; elle yönetilen bir derleme numarası, hattın en sık takıldığı yerlerden biridir.

İki platform bu iki numarayı farklı alan adlarıyla tutar. Aşağıdaki iki parça yalnız alanların yerini gösterir; parçalar ölçülmez.

// Platform kodu: Android surum alanlari
android {
    defaultConfig {
        versionCode = 142
        versionName = "4.2.1"
    }
}
# Platform kodu: iOS surum alanlari
CFBundleShortVersionString: "4.2.1"
CFBundleVersion: "142"

Android’de versionName kullanıcıya görünen sürümdür ve versionCode makinenin sıraladığı tam sayıdır. iOS’ta CFBundleShortVersionString kullanıcıya görünen sürümü, CFBundleVersion derleme numarasını taşır. Köprüyle yerel görünümlere bağlanan bir çerçevede de, kendi çizim motoruyla çalışan bir çerçevede de bu iki alan sonunda aynı yere, platformun kendi yapılandırma dosyasına yazılır; çerçeve yalnız bu dosyaları besleyen bir katman ekler.

Anlamlı Sürümleme

Sürüm numarasını üç parçaya bölmek yaygın bir düzendir: ana, ara ve yama. 4.2.1 numarasında ana sürüm dört, ara sürüm iki, yama bir demektir. Her parçanın bir sözü vardır.

  • Yama, mevcut davranışı bozmadan bir hatayı düzeltir. Bir kullanıcı yamayı kurduğunda yeni bir şey öğrenmesi gerekmez.
  • Ara sürüm, mevcut davranışı bozmadan yeni bir yetenek ekler. Yama sıfırlanır.
  • Ana sürüm, mevcut davranışı bozabilecek bir değişiklik getirir. Ara ve yama sıfırlanır.

Bu düzen mobilde bir web servisine göre daha önemlidir, çünkü eski sürüm kullanıcının aygıtında yaşamaya devam eder. Sunucu güncellenir ve herkese birden ulaşır; istemci güncellenmez, kullanıcı karar verene kadar eski kalır. Ana sürüm numarası bu yüzden yalnız bir etiket değil, sunucunun hangi istemcilerle hâlâ konuşması gerektiğini planlayan ekibe bir işarettir.

Numara üretimi mekaniktir ve elle yapıldığında hata verir; bu yüzden küçük bir işleve bırakılması iyi olur. Dersin yardımcı dosyasındaki nextVersion işlevi bu kuralı yazar.

Sürüm Notu

Her yayın bir sürüm notuyla çıkar. Not iki okuyucuya hitap eder: mağaza sayfasını okuyan kullanıcıya ve yayını izleyen ekibe. Kullanıcıya dönük not kısa ve davranış odaklıdır; “ödeme ekranı yenilendi” gibi. Ekibe dönük not hangi değişikliklerin yayına girdiğini, hangilerinin bayrağın arkasında kapalı gittiğini ve hangi sunucu sürümünü gerektirdiğini söyler.

Son madde ihmal edilir ve sonradan pahalıya mal olur. Bir yayın yeni bir sunucu sözleşmesini gerektiriyorsa not bunu açıkça yazmalıdır; çünkü sunucu o sözleşmeyi sunmadan istemciyi yayımlamak, özelliği sessizce eksik çalıştırır. Aşağıdaki bölüm bu eksikliği ölçer.

İstemci ile Sunucu Arasındaki Sözleşme

İstemci ve sunucu bir sözleşmeyle konuşur: hangi alanlar var, hangi biçimde, hangi adlarla. Sözleşmenin de bir sürümü vardır ve sunucu birden çok sürümü aynı anda sunabilir. Eski bir istemci eski sözleşmeyi, yeni bir istemci yeni sözleşmeyi ister.

Uyumsuz bir değişiklikte sunucu eski sözleşmeyi bir süre daha sunar, çünkü eski istemciler hâlâ kullanımdadır. Bunun tersi de vardır: yeni istemci yayımlanmış, ama sunucu henüz yeni sözleşmeye geçmemiş olabilir. Mağazaya giren istemci ile canlıya alınan sunucu aynı anda güncellenmez; ikisinin arasındaki aralıkta yeni istemci eski sözleşmeyle karşılaşır.

İşlerlik açısından sorunun şekli yeniden bellidir. Sözleşmenin sürümü bir yetenektir: api:v2 ya da api:v3. İstemcideki bir özellik yeni sözleşmeyi istiyorsa ve sunucu onu sunmuyorsa özellik eksik bir yetenekle çalışır. Bu eksiklik bazen özelliği tamamen engeller, bazen özellik eski alanlarla daha az bilgi gösterir. İkincisi yedeği olan bir eksikliktir.

Sözleşmenin Koşulunu Ölçmek

Ölçüm için sipariş geçmişini ele alalım. OrderHistory yeni sözleşmeyi, yani api:v3 yeteneğini ister; bu sözleşme her siparişin kalem ayrıntısını da getirir. Yalnız api:v2 sunan sunucuda ekran açılır, ama siparişleri eski alanlarla, kalem ayrıntısı olmadan gösterir. Bu bir yedektir ve kisitli düzeyindedir. Çekirdek ilk dersten tanıdıktır ve her derste aynı biçimde yeniden verilir; ders ona dokunmaz.

// operability.mjs — bir ozelligin bir kosulda ne kadar calistigini siniflandirir
export const LEVELS = ["tam", "kisitli", "ertelenen", "kapali"];
const FALLBACKS = ["kisitli", "ertelenen"];

export function feature(name, needs, fallback = {}) {
  return { name, needs, fallback };
}

export function condition(name, has) {
  return { name, has };
}

function judge(item, cond) {
  const missing = item.needs.filter((need) => !cond.has.includes(need)).sort();
  let level = "tam";
  for (const need of missing) {
    const given = FALLBACKS.includes(item.fallback[need]) ? item.fallback[need] : "kapali";
    if (LEVELS.indexOf(given) > LEVELS.indexOf(level)) level = given;
  }
  return { level, feature: item.name, condition: cond.name, missing };
}

export function assess(features, conditions) {
  const records = [];
  for (const cond of conditions) {
    for (const item of features) records.push(judge(item, cond));
  }
  return records;
}

export function printLevels(records) {
  for (const r of records) {
    const missing = r.missing.length === 0 ? "-" : r.missing.join(",");
    console.log(`${r.level}: ${r.feature} @ ${r.condition} eksik=${missing}`);
  }
}

export function countLevels(records) {
  for (const name of LEVELS) {
    console.log(`${name}: ${records.filter((r) => r.level === name).length}`);
  }
  console.log(`etkilenen: ${records.filter((r) => r.level !== "tam").length}`);
}

Çekirdeğin ardından dersin yardımcı dosyası gelir. conditionsFor(servers) her sunucu tanımından bir koşul üretir: ağ her sunucuda vardır, sözleşme yeteneği ise sunucunun sunduğu sürümden gelir ve api: önekiyle yazılır. nextVersion(version, change) üç parçalı bir numarayı değişikliğin türüne göre artırır. Özellikler üçtür. OrderHistory ağı ve api:v3 yeteneğini ister; api:v3 eksikse kısıtlı çalışır. Catalog ürün listesidir ve Profile kullanıcı profilidir; ikisi de yalnız ağı ister.

// versions.mjs — sunucunun sundugu sozlesmeden kosul uretir, surumu artirir
import { feature, condition } from "./operability.mjs";

export function conditionsFor(servers) {
  return servers.map((server) => condition(server.name, ["network", `api:${server.api}`]));
}

export function nextVersion(version, change) {
  const [major, minor, patch] = version.split(".").map(Number);
  if (change === "major") return `${major + 1}.0.0`;
  if (change === "minor") return `${major}.${minor + 1}.0`;
  return `${major}.${minor}.${patch + 1}`;
}

export const historyFeatures = [
  feature("OrderHistory", ["network", "api:v3"], { "api:v3": "kisitli" }),
  feature("Catalog", ["network"]),
  feature("Profile", ["network"]),
];

YI3. Model, sunucunun sunduğu sözleşmeyi tek bir yetenek olarak kurar: bir sunucu v2 ya da v3 sunar. Gerçek bir sunucu birden çok sürümü birlikte sunabilir ve istemci hangisini kullanacağını pazarlıkla belirleyebilir; kural bu pazarlığı görmez, yalnız koşulun has listesine bakar. Model, bu işlerliğin kuralını kurar; model çerçevenin kendisi değildir.

İlk ölçüm iki sunucuyu aynı istemci için yan yana koyar. Önce üç numara artışı basılır; bunlar dersin yerel çıktısıdır. Sonra altı kayıt gelir.

// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { conditionsFor, nextVersion, historyFeatures } from "./versions.mjs";

let version = "4.2.0";
for (const change of ["patch", "minor", "major"]) {
  const next = nextVersion(version, change);
  console.log(`surum: ${version} + ${change} = ${next}`);
  version = next;
}
const servers = [
  { name: "api-v2", api: "v2" },
  { name: "api-v3", api: "v3" },
];
printLevels(assess(historyFeatures, conditionsFor(servers)));
surum: 4.2.0 + patch = 4.2.1
surum: 4.2.1 + minor = 4.3.0
surum: 4.3.0 + major = 5.0.0
kisitli: OrderHistory @ api-v2 eksik=api:v3
tam: Catalog @ api-v2 eksik=-
tam: Profile @ api-v2 eksik=-
tam: OrderHistory @ api-v3 eksik=-
tam: Catalog @ api-v3 eksik=-
tam: Profile @ api-v3 eksik=-

Numara artışları sürüm kuralını gösterir: yama yalnız son parçayı artırır, ara sürüm yamayı sıfırlar, ana sürüm ikisini birden. Kayıtlarda ise OrderHistory yalnız api-v2 sunucusunda kısıtlıdır; eksik olan api:v3 yeteneğidir ve yedeği kısıtlı olarak tanımlanmıştır. Aynı sunucuda Catalog ve Profile tamdır, çünkü ikisi sözleşme sürümünü istemez. api-v3 sunucusunda üç özellik de tamdır.

Kısıtlı sözcüğü burada somut bir şey söyler: sipariş geçmişi açılır, siparişler listelenir, ama kalem ayrıntısı yoktur. Kapalı olsaydı ekran hiç açılmayacaktı. Yedeğin tanımlı olması, özelliğin eksik yetenekle de bir şey sunabilmesi demektir.

Yama Yükseltmesi Yeteneği Değiştirmez

Kullanıcı bir yama kurduğunda sürüm numarası değişir. Numaranın değişmesi, özelliğin ihtiyaç duyduğu yeteneklerden birini getirmiş ya da götürmüş olmak anlamına gelmez. Yama hatayı düzeltir, sözleşmeyi değiştirmez.

İkinci ölçüm aynı sunucuda iki istemci sürümünü karşılaştırır. Koşul adları sürümü içerir, çünkü iki koşulun adı aynı olamaz; sunulan sözleşme ikisinde de aynıdır.

// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { conditionsFor, historyFeatures } from "./versions.mjs";

const installs = [
  { name: "4.2.0-api-v2", api: "v2" },
  { name: "4.2.1-api-v2", api: "v2" },
];
const records = assess(historyFeatures, conditionsFor(installs));
printLevels(records);

const key = (list) => list.map((r) => `${r.level}:${r.feature}:${r.missing.join(",")}`).join("|");
const before = key(records.filter((r) => r.condition === "4.2.0-api-v2"));
const after = key(records.filter((r) => r.condition === "4.2.1-api-v2"));
console.log(`yama kaydi degistirir mi: ${before === after ? "hayir" : "evet"}`);
kisitli: OrderHistory @ 4.2.0-api-v2 eksik=api:v3
tam: Catalog @ 4.2.0-api-v2 eksik=-
tam: Profile @ 4.2.0-api-v2 eksik=-
kisitli: OrderHistory @ 4.2.1-api-v2 eksik=api:v3
tam: Catalog @ 4.2.1-api-v2 eksik=-
tam: Profile @ 4.2.1-api-v2 eksik=-
yama kaydi degistirir mi: hayir

İki istemci sürümü altı kayıtta aynı üç sonucu verir ve son satır bunu söyler. Karşılaştırma koşul adını dışarıda bırakır, çünkü ad zaten farklıdır; karşılaştırılan şey düzeyler, özellikler ve eksik yeteneklerdir.

YI4. Model, yamanın yetenek değiştirmediğini varsayar ve bu varsayım bir sözleşmeye dayanır: yama davranışı bozmaz. Gerçekte bir yama, yedek bir yolu devre dışı bırakabilir ya da bir yeteneği yanlışlıkla kaldırabilir. Bu durumda yama bir hatayı düzeltirken yenisini getirmiştir ve sürüm numarası bunu söylemez. Kural bu durumu yakalamaz; yakalayan, yamadan sonra koşulun yeniden kurulup ölçülmesidir.

Sınırlayıcı Ölçüm

Bu dersin odak kaydı OrderHistory @ api-v2’dir. Sınırlayıcı ölçüm iki şeyi birlikte gösterir. Birincisi, odak kayıt api-v2 sunucusunda kısıtlı, api-v3 sunucusunda tamdır ve altı kaydın yalnız biri etkilenir. İkincisi, istemcinin sürüm numarası kayda girmez: ana sürümü yükseltilmiş bir istemci, aynı eski sunucuda aynı kaydı verir.

// main.mjs
import { assess, printLevels, countLevels } from "./operability.mjs";
import { conditionsFor, historyFeatures } from "./versions.mjs";

const servers = [
  { name: "api-v2", api: "v2" },
  { name: "api-v3", api: "v3" },
];
const records = assess(historyFeatures, conditionsFor(servers));
printLevels(records.filter((r) => r.feature === "OrderHistory"));
countLevels(records);

const key = (list) => list.map((r) => `${r.level}:${r.feature}:${r.missing.join(",")}`).join("|");
const oldClient = assess(historyFeatures, conditionsFor([{ name: "4.2.0-api-v2", api: "v2" }]));
const newClient = assess(historyFeatures, conditionsFor([{ name: "5.0.0-api-v2", api: "v2" }]));
console.log(`istemci surumu kayda girmez: ${key(oldClient) === key(newClient) ? "evet" : "hayir"}`);
kisitli: OrderHistory @ api-v2 eksik=api:v3
tam: OrderHistory @ api-v3 eksik=-
tam: 5
kisitli: 1
ertelenen: 0
kapali: 0
etkilenen: 1
istemci surumu kayda girmez: evet

İlk iki satır dersin işlerliğini taşır: aynı özellik, aynı kod; yalnız sunucunun sunduğu sözleşme değişti ve kayıt tamdan kısıtlıya geçti. Sayım satırları altı kayıttan beşinin tam, birinin kısıtlı olduğunu söyler; etkilenen birdir.

Son satır modelin sınırını gösterir. Sürüm numarası bir etikettir; özelliğin ihtiyaç duyduğu şey sürüm numarası değil, sunucunun sunduğu sözleşmedir. 5.0.0 numaralı bir istemci, api:v3 sunmayan bir sunucuda 4.2.0 numaralı istemci kadar kısıtlıdır. Numara bu yüzden bir ipucudur ama kanıt değildir: ekip hangi istemcinin hangi sözleşmeyi istediğini sürüm notuna yazar, işlerliği ise sunucunun gerçekten sunduğu sözleşme belirler.

Bu ayrım yayın sırasını da belirler. Yeni sözleşmeyi isteyen bir istemci, sunucu o sözleşmeye geçmeden yayımlanırsa kullanıcıların bir kısmı özelliği kısıtlı görür. Sunucunun önce, istemcinin sonra yayımlanması bu aralığı kapatır.

Özet

  • Bu dersin işlerliği: kısıtlı. OrderHistory @ api-v2, sunucu yalnız eski sözleşmeyi sunduğu ve api:v3 yeteneğinin yedeği kısıtlı olduğu için kısıtlı çıktı; aynı sunucuda Catalog ve Profile tam kaldı.
  • Sürüm numarasına ekip karar verir ve kullanıcıya görünür; derleme numarasını hat artırır ve her yüklemede yeni olmak zorundadır.
  • Anlamlı sürümlemede yama hatayı düzeltir, ara sürüm yetenek ekler ve yamayı sıfırlar, ana sürüm uyumsuz değişiklik getirir ve ikisini de sıfırlar.
  • Altı kayıttan beşi tam, biri kısıtlıydı; etkilenen bir. Yama yükseltmesi aynı sunucuda kaydı değiştirmedi.
  • Ana sürümü yükseltilmiş istemci eski sunucuda aynı kaydı verdi; işlerliği sürüm numarası değil, sunucunun sunduğu sözleşme belirler.

Sonraki Adım

Bu derste sunucu sabit bir koşuldu ve istemci tek bir yapıydı. Sıradaki ders, Aşamalı Yayın ve Geri Alma, yeni bir sürümün kullanıcıların yalnız bir kısmına ulaştığı durumu ele alır. Yayını durdurmayı, geri almayı ve ileri doğru düzeltmeyi karşılaştırır, ve her kovanın koşulunu ayrı ayrı ölçer.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat