---
title: 'Çevrimdışı Öncelikli Tasarım'
source: 'https://academia.sh/tr/kurslar/capraz-platform-uretim/cevrimdisi-oncelikli-tasarim'
course: 'Çapraz Platform Üretim Pratiği'
language: tr
updated: '2026-10-21T05:02:50+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Yerel veriyi doğruluk kaynağı yapan tasarımla ağ öncelikli tasarımı karşılaştırır'
    - 'Ağın yalnız tazeleme için kullanıldığı okuma yolunu açıklar'
    - 'Aynı akışın iki tasarımla ağ yokken kapalı ve kısıtlı çıkışını ölçer'
    - 'Yerel modelle tam uyuşan bir ekranın neden yine de kısıtlı olduğunu açıklar'
---

# Çevrimdışı Öncelikli Tasarım

Çevrimdışı öncelikli tasarım, yerel veriyi doğruluk kaynağı yapar ve ağı yalnız tazeleme için kullanır. Ders aynı akışı iki tasarımla kurar ve ağ yokken hangisinin ne kadar çalıştığını ölçer.

Önceki konu, ortak kodun nasıl dilimlendiğini ve her platformun kendi katmanını nasıl taşıdığını ölçtü. Bu konu bir uygulamanın en sık karşılaştığı koşula iner: ağ yok. Metroda, asansörde, uçakta ya da kapsama alanının dışında uygulama yine açılır ve kullanıcı yine bir şey bekler. Bu derste bu beklentiyi karşılamanın iki tasarımı yan yana konur.

Kursun sorusu aynı kalır: bu koşulda bu özellik ne kadar çalışıyor? Açılış dersindeki dokuz kayıt beş tam, bir kısıtlı, iki ertelenen ve bir kapalı çıkmıştı. Bu ders o sayıyı değiştirmez; yalnız kendi kesitini ölçer.

## İki Tasarım

**Ağ öncelikli** bir tasarımda ekran her açılışta veriyi sunucudan ister ve gelen yanıtı gösterir. Doğruluk kaynağı sunucudur; yerel depo en fazla bir önbellektir. Ağ varken bu tasarım basit ve doğrudur. Ağ yokken ekranın gösterecek bir şeyi kalmaz.

**Çevrimdışı öncelikli** bir tasarımda doğruluk kaynağı yereldir. Ekran her zaman yerel depodan okur. Ağ okumanın yolu değildir; yalnız yerel depoyu tazelemenin yoludur. Sunucudan gelen yeni kayıtlar yerel depoya yazılır ve ekran yerel depodaki değişikliği gösterir. Ağ gidince ekranın okuduğu şey değişmez, yalnız tazelenmez.

Bu ayrım bir kuraldır, bir kütüphane seçimi değildir. Aynı gömülü veritabanı iki tasarımda da bulunabilir. Fark, ekranın okuma yolunun nereden geçtiğidir. Aşağıdaki Android parçası çevrimdışı öncelikli okuma yolunu gösterir. Parça ölçülmez.

```kotlin
// Platform kodu: Android yerel okuma
class FeedRepository(private val db: SQLiteDatabase) {
    fun readPosts(): List<Post> {
        val cursor = db.query("posts", null, null, null, null, null, "published DESC")
        return cursor.use { rows ->
            generateSequence { if (rows.moveToNext()) rows.toPost() else null }.toList()
        }
    }
}
```

Ekran depoyu çağırır, ağı çağırmaz. Tazeleme ayrı bir iştir: ağdan gelen kayıtlar `posts` tablosuna yazılır ve okuma yolu bir sonraki okumada onları görür. iOS tarafında aynı sözleşme Swift'te aynı biçimde kurulur; yerel depodan okuyan bir katman ve ağdan tazeleyen ayrı bir katman vardır.

## Özellikleri Kurmak

İki tasarımı ölçmek için kursun çekirdeğine ihtiyaç var. Çekirdek ilk dersten tanıdıktır ve her derste aynı biçimde yeniden verilir; ders ona dokunmaz.

```javascript
// 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. Akış için iki özellik kurulur. `FeedRemote` ağ öncelikli akıştır: yalnız `network` ister ve yedeği yoktur. `FeedLocal` çevrimdışı öncelikli akıştır: `storage` ve `network` ister, ağ eksik olduğunda `kisitli` yedeğine düşer. Üçüncü özellik `Bookmarks` yer imleridir ve yalnız `storage` ister. `stateOf(link)` bir bağlantı durumundan koşul üretir: ağ varsa `network`, depolama alanı varsa `storage` yeteneği koşula girer.

```javascript
// feeds.mjs — iki akis tasarimini ve baglanti durumlarini kurar
import { feature, condition } from "./operability.mjs";

export const remoteFeed = feature("FeedRemote", ["network"]);
export const localFeed = feature("FeedLocal", ["storage", "network"], { network: "kisitli" });
export const bookmarks = feature("Bookmarks", ["storage"]);

export function stateOf(link) {
  const has = [];
  if (link.network) has.push("network");
  if (link.storage !== false) has.push("storage");
  return condition(link.name, has);
}
```

## Ağ Yokken İki Tasarım

İlk ölçüm iki akışı iki bağlantı durumunda koşar. `online` durumunda ağ ve depolama alanı vardır. `offline` durumunda yalnız depolama alanı vardır.

```javascript
// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { remoteFeed, localFeed, stateOf } from "./feeds.mjs";

const links = [
  { name: "online", network: true },
  { name: "offline", network: false },
];
printLevels(assess([remoteFeed, localFeed], links.map(stateOf)));
```

```text
tam: FeedRemote @ online eksik=-
tam: FeedLocal @ online eksik=-
kapali: FeedRemote @ offline eksik=network
kisitli: FeedLocal @ offline eksik=network
```

Ağ varken iki tasarım da tamdır; fark ağ gidince açılır. `FeedRemote @ offline` kapalıdır, çünkü eksik `network` yeteneğinin yedeği yoktur. `FeedLocal @ offline` kısıtlıdır, çünkü aynı eksik için özellik bir yedek tanımlamıştır: yerel veriyle çalışmaya devam eder. İki özellik aynı eksiği taşır ve yedek yüzünden farklı düzeye düşer.

**CE1.** Model, ağı tek bir yetenek olarak kurar: ya vardır ya yoktur. Gerçek bir bağlantı kesintili, yavaş ya da yarı açık olabilir; bu durumlar dördüncü derste ayrıca ele alınır. Kural yeteneği ve yedeği görür; yerel depoda kaç kayıt bulunduğunu, kayıtların ne kadar eski olduğunu ve kullanıcının ne beklediğini görmez. Model, bu işlerliğin kuralını kurar; model çerçevenin kendisi değildir.

## Okuma Yolu ve Tazeleme

İşlerlik kaydı ekranın ne gösterdiğini söylemez. Bunu görmek için iki akışın okuma yolu ayrıca modellenir. Depoda üç yerel kayıt vardır; sunucuda dört kayıt vardır ve ikisi yerel kayıtlarla ortaktır. Ağ öncelikli akış yalnız sunucudan okur. Çevrimdışı öncelikli akış yerelden okur ve ağ varsa sunucudaki yeni kayıtları ekler.

```javascript
// reader.mjs — iki tasarimin gonderi okuma yolunu kurar
export function readFeed(design, store, link) {
  if (design === "remote") {
    return link.network ? { shown: store.remote.length, fresh: true } : { shown: 0, fresh: false };
  }
  const merged = link.network ? [...new Set([...store.local, ...store.remote])] : store.local;
  return { shown: merged.length, fresh: link.network };
}

export function printReads(label, design, store, links) {
  for (const link of links) {
    const read = readFeed(design, store, link);
    console.log(`${label} @ ${link.name}: ${read.shown} gonderi, taze=${read.fresh ? "evet" : "hayir"}`);
  }
}
```

Ölçüm iki okumayı ve `offline` koşulunun işlerlik kayıtlarını birlikte basar.

```javascript
// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { remoteFeed, localFeed, stateOf } from "./feeds.mjs";
import { printReads } from "./reader.mjs";

const store = { local: ["p1", "p2", "p3"], remote: ["p2", "p3", "p4", "p5"] };
const links = [
  { name: "online", network: true },
  { name: "offline", network: false },
];
printReads("FeedRemote", "remote", store, links);
printReads("FeedLocal", "local", store, links);
const records = assess([remoteFeed, localFeed], links.map(stateOf));
printLevels(records.filter((r) => r.condition === "offline"));
```

```text
FeedRemote @ online: 4 gonderi, taze=evet
FeedRemote @ offline: 0 gonderi, taze=hayir
FeedLocal @ online: 5 gonderi, taze=evet
FeedLocal @ offline: 3 gonderi, taze=hayir
kapali: FeedRemote @ offline eksik=network
kisitli: FeedLocal @ offline eksik=network
```

Ağ varken çevrimdışı öncelikli akış beş gönderi gösterir: üç yerel ve sunucudan gelen iki yeni kayıt. Ağ yokken üç yerel gönderiyi göstermeye devam eder ve tazelik düşer. Ağ öncelikli akış ağ yokken sıfır gönderi gösterir. İki tasarımın işlerlik kayıtları, okuma yolunun bu farkını sınıfa çevirir: sıfır gönderi kapalı, üç gönderi kısıtlı.

## Depolama Alanı Doğruluk Kaynağıdır

Yerel veriyi doğruluk kaynağı yapan tasarım ağa olan bağımlılığı azaltır ve depolama alanına olan bağımlılığı artırır. Depolama alanı dolduğunda yerel okuma da yazma da çalışmaz. Üçüncü ölçüm bunu `storage-full` koşuluyla gösterir: ağ vardır, depolama alanı yoktur.

```javascript
// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { localFeed, bookmarks, stateOf } from "./feeds.mjs";

const links = [
  { name: "online", network: true },
  { name: "offline", network: false },
  { name: "storage-full", network: true, storage: false },
];
printLevels(assess([localFeed, bookmarks], links.map(stateOf)));
```

```text
tam: FeedLocal @ online eksik=-
tam: Bookmarks @ online eksik=-
kisitli: FeedLocal @ offline eksik=network
tam: Bookmarks @ offline eksik=-
kapali: FeedLocal @ storage-full eksik=storage
kapali: Bookmarks @ storage-full eksik=storage
```

`Bookmarks` yalnız yerel depoya dayanır, bu yüzden ağ gidince etkilenmez ve `storage-full` koşulunda kapanır. `FeedLocal` ağ eksikliğine yedekle dayanır ama depolama eksikliğine dayanamaz: `storage` için bir yedek tanımlanmamıştır, bu yüzden aynı özellik `storage-full` koşulunda kapalıdır. Çevrimdışı öncelikli tasarım ağ bağımlılığını yedekle karşılar; bağımlılığı ortadan kaldırmaz, yerel depoya taşır.

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

Bu dersin odak kaydı `FeedLocal @ offline`'dır. Son ölçüm üç özelliği iki durumda koşar, `offline` koşulunun kayıtlarını ve sayımı basar, ardından ekranın yerel modelle uyuşup uyuşmadığını sorar.

```javascript
// main.mjs
import { assess, printLevels, countLevels } from "./operability.mjs";
import { remoteFeed, localFeed, bookmarks, stateOf } from "./feeds.mjs";
import { readFeed } from "./reader.mjs";

const store = { local: ["p1", "p2", "p3"], remote: ["p2", "p3", "p4", "p5"] };
const offline = { name: "offline", network: false };
const links = [{ name: "online", network: true }, offline];
const records = assess([remoteFeed, localFeed, bookmarks], links.map(stateOf));
printLevels(records.filter((r) => r.condition === "offline"));
countLevels(records);
const shown = readFeed("local", store, offline).shown;
console.log(`ekran yerel modelle uyusur: ${shown === store.local.length ? "evet" : "hayir"}`);
```

```text
kapali: FeedRemote @ offline eksik=network
kisitli: FeedLocal @ offline eksik=network
tam: Bookmarks @ offline eksik=-
tam: 4
kisitli: 1
ertelenen: 0
kapali: 1
etkilenen: 2
ekran yerel modelle uyusur: evet
```

İlk iki satır dersin işlerliğini taşır: aynı akış ağ öncelikli kurulduğunda kapalı, çevrimdışı öncelikli kurulduğunda kısıtlı çıktı. Altı kaydın dördü tam, biri kısıtlı, biri kapalıdır; etkilenen iki.

Son satır işlerliğin neyi sınıflamadığını gösterir. M30/K04'te bir ekranın modelle uyuşup uyuşmadığı soruldu. Burada ekran yerel modelle tam uyuşur: gösterdiği üç gönderi yerel depodaki üç gönderidir ve ekran ile model arasında bir ayrılık yoktur. Yine de `FeedLocal @ offline` tam değil, kısıtlıdır. Uyum ile işlerlik ayrı eksenlerdir. Uyum ekranın modelin söylediğini gösterip göstermediğini sorar; işlerlik özelliğin o koşulda vaat ettiğinin ne kadarını yaptığını sınıflar. Yeni içerik gelmeyen bir akış, modeliyle tam uyuşsa da, ağ varken olduğundan daha azını yapar.

Bu fark tasarım kararını da etkiler. Çevrimdışı öncelikli bir ekran için "çevrimdışı çalışıyor" demek yetmez; hangi işlerin yedekle sürdüğünü ve hangilerinin durduğunu özellik özellik söylemek gerekir.

## Özet

- Bu dersin işlerliği: kısıtlı. `FeedLocal @ offline`, `network` eksik olduğu ve `kisitli` yedeği tanımlandığı için kısıtlı çıktı; ağ öncelikli `FeedRemote` aynı koşulda yedeksiz olduğundan kapalı kaldı.
- Çevrimdışı öncelikli tasarımda doğruluk kaynağı yerel depodur; ağ okumanın yolu değil, yerel depoyu tazelemenin yoludur.
- Ağ varken iki tasarım da tamdı. Ağ yokken okuma yolu farkı gösterdi: ağ öncelikli akış sıfır gönderi, çevrimdışı öncelikli akış üç gönderi gösterdi.
- Yerel veri ağ bağımlılığını yedekle karşılar ama depolama bağımlılığını kaldırmaz: `storage-full` koşulunda `FeedLocal` kapalıdır.
- Ekran yerel modelle tam uyuşsa da özellik kısıtlı kalır; uyum ve işlerlik ayrı eksenlerdir.

## Sonraki Adım

Bu derste ağ yokken yalnız okuma ele alındı: yerel veri gösterildi, kullanıcının yaptığı değişiklik ise hiç konuşulmadı. Sıradaki ders, `Eşitleme Stratejileri`, çevrimdışıyken yapılan bir yazmanın kuyruğa alınmasını, ağ dönünce sunucuya gönderilmesini ve iki tarafın aynı kaydı değiştirdiği çakışmanın nasıl çözüldüğünü ele alır. Sonra çevrimdışı not düzenlemesinin ne kadar çalıştığını ölçer.
