---
title: 'Modüler Kod Paylaşımı'
source: 'https://academia.sh/tr/kurslar/capraz-platform-uretim/moduler-kod-paylasimi'
course: 'Çapraz Platform Üretim Pratiği'
language: tr
updated: '2026-10-21T05:02:51+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Paylaşılan modül ile platforma özgü katman arasındaki katman sınırını açıklar'
    - 'Bir özelliğin işlerliğini tam, kısıtlı, ertelenen ve kapalı olarak sınıflar'
    - 'Dokuz kayıtlık açılış ölçümünü okur ve etkilenen kayıtları ayırır'
    - 'Tamamen paylaşılan bir modülün bir platformda neden kapalı kaldığını ölçer'
---

# Modüler Kod Paylaşımı

Modüler kod paylaşımı, ortak kodu paylaşılan modüle ve platforma özgü katmana ayırır. Ders kursun işlerlik ölçüsünü kurar ve tamamen paylaşılan bir modülün bir platformda kapalı kalabildiğini ölçer.

Önceki kurslar bir çapraz platform uygulamasının nasıl kurulduğunu sordu: kod platformlar arasında nasıl paylaşılıyor, görünüm ağacı nasıl güncelleniyor, bir bileşenin genişliğini kim belirliyor. Üretimdeki bir uygulama için asıl soru başkadır. Aynı ekran bir aygıtta çevrimiçi, ötekinde çevrimdışı açılır; bir üçüncüsünde arka plan işi kısılmıştır; bir dördüncüsü eski bir istemci sürümünü çalıştırır. Tek bir uygulama tek bir koşulda çalışmaz.

Bu kurs her özelliği tek bir soruyla sınıflar: bu koşulda bu özellik ne kadar çalışıyor? İlk ders soruyu kurar ve ilk konunun konusuna, ortak kodun nasıl dilimlendiğine bağlar. Bu kursta "özellik" bir uygulama özelliği, yani feature demektir: kullanıcının yaptığı bir iş, örneğin katalog gezmek ya da ödeme yapmak. Bir bileşenin dışarıdan aldığı değer anlamına gelmez.

## Dört İşlerlik

Sorunun yanıtına işlerlik denir ve dört değeri vardır. Kurs boyunca bu dört ad değişmez.

- **tam:** özelliğin ihtiyaç duyduğu her yetenek bu koşulda vardır; özellik tasarlandığı gibi çalışır.
- **kısıtlı:** bir yetenek eksiktir; özellik eksik yeteneğin yerine daha az şey yaparak hemen çalışır, örneğin önbellekteki içeriği gösterir.
- **ertelenen:** bir yetenek eksiktir; özelliğin işi kaybolmaz, sonraya bırakılır ve yetenek dönünce yapılır.
- **kapalı:** eksik yeteneklerden en az birinin yedeği yoktur; özellik bu koşulda çalışmaz.

Çıktıda bu adlar ASCII yazılır: `tam`, `kisitli`, `ertelenen`, `kapali`. Kapalı ile ertelenen aynı şey değildir. Kapalı bir özelliğin işi o koşulda yapılmaz ve sonraya da kalmaz; ertelenen bir özelliğin işi ise yerinde durur.

İşlerliği bir etiket değil, bir kural verir. Özellik ihtiyaç duyduğu yetenekleri sayar, koşul o anda var olan yetenekleri sayar, aradaki fark eksikleri verir. Her eksik için özellik bir yedek tanımlamış olabilir. Kural sırayla üç soru sorar:

1. Eksik yetenek yoksa özellik tamdır.
2. Eksik yeteneklerden birinin yedeği yoksa özellik kapalıdır.
3. Aksi hâlde eksik yeteneklerin yedeklerinden en ağırı seçilir; ertelenen, kısıtlıdan ağırdır.

Bu üç soru çekirdeğin içinde kod olarak durur. Çekirdek bu kursun her dersinde aynı biçimde yeniden verilir; ilk kez burada okunur.

```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}`);
}
```

`feature(name, needs, fallback)` bir özellik kurar: `needs` ihtiyaç duyduğu yetenekleri, `fallback` bir yetenek eksik olduğunda neye düşeceğini söyler. `fallback` verilmezse boştur; o özelliğin hiçbir yeteneğinin yedeği yoktur ve her eksik onu kapalıya düşürür. `condition(name, has)` bir koşul kurar; `has` o koşulda var olan yeteneklerdir. Yetenek bir dizgidir (`network`, `background`, `storage`) ve çekirdek onu yorumlamaz, yalnız `has` içinde olup olmadığına bakar.

`assess` her koşul için her özelliği değerlendirir: koşul dışta, özellik içte döner. Her kayıt `level`, `feature`, `condition` ve `missing` alanlarını taşır. `printLevels` kayıtları basar; `countLevels` dört işlerliği sabit sırayla sayar ve son satırda etkilenen toplamını verir. Etkilenen, kısıtlı, ertelenen ve kapalı kayıtların toplamıdır: özelliğin tasarlandığı gibi çalışmadığı kayıt sayısı. Tam kayıt bu sayıya girmez.

## Dokuz Kayıt

Senaryo, paylaşılan kodla iki platformda yayımlanan bir mağaza uygulamasıdır. Üç özellik vardır. `Catalog` ağdan içerik okur; ağ yokken önbellekteki içeriğe düşer. `Checkout` ödeme yapar ve hiçbir yedeği yoktur. `PhotoUpload` fotoğraf gönderir; hem ağa hem arka plan işine ihtiyaç duyar ve ikisinin yokluğunda da işini sonraya bırakır. Üç koşul vardır: `online` her yeteneği taşır, `offline` ağı kaybeder, `low-power` ağı korur ama arka plan işini kaybeder.

```javascript
// main.mjs
import { feature, condition, assess, printLevels, countLevels } from "./operability.mjs";

const features = [
  feature("Catalog", ["network"], { network: "kisitli" }),
  feature("Checkout", ["network"]),
  feature("PhotoUpload", ["network", "background"], {
    network: "ertelenen",
    background: "ertelenen",
  }),
];
const conditions = [
  condition("online", ["network", "background"]),
  condition("offline", ["background"]),
  condition("low-power", ["network"]),
];
const records = assess(features, conditions);
printLevels(records);
countLevels(records);
```

```text
tam: Catalog @ online eksik=-
tam: Checkout @ online eksik=-
tam: PhotoUpload @ online eksik=-
kisitli: Catalog @ offline eksik=network
kapali: Checkout @ offline eksik=network
ertelenen: PhotoUpload @ offline eksik=network
tam: Catalog @ low-power eksik=-
tam: Checkout @ low-power eksik=-
ertelenen: PhotoUpload @ low-power eksik=background
tam: 5
kisitli: 1
ertelenen: 2
kapali: 1
etkilenen: 4
```

İlk üç satır `online` koşuludur: her yetenek vardır, üç özellik de tamdır. `offline` koşulunda ağ yoktur. `Catalog` ağ için yedek tanımladığı için kısıtlıdır, `PhotoUpload` işini sonraya bıraktığı için ertelenendir, `Checkout`'un yedeği olmadığı için `Checkout @ offline` kapalıdır. `low-power` koşulunda ağ vardır ama arka plan yoktur: arka plana ihtiyaç duymayan `Catalog` ve `Checkout` tamdır, `PhotoUpload` ertelenendir.

Dokuz kaydın beşi tam, biri kısıtlı, ikisi ertelenen, biri kapalıdır; etkilenen dört. Bu sayı kursun açılış sayısıdır. Sonraki dersler ona atıfla anar, değiştirmez; her ders kendi kesitini ayrıca ölçer. Kullanıcıya hiçbir şey sunmayan tek kayıt `Checkout @ offline`'dır. Etkilenen dört kaydın üçünde özellik bir şekilde çalışmayı sürdürür.

**PM1.** Model, bir özelliğin bir koşuldaki davranışını yalnız yetenek kümesi olarak taklit eder. Kural yeteneği ve yedeği görür; işin kendisini, kullanıcıyı ve süreyi görmez. Kısıtlı `Catalog`'un önbellekteki içeriği ne kadar eski göstereceği, ertelenen `PhotoUpload`'ın işi ne zaman yapacağı ve kaç kez deneyeceği modelde yoktur ve işlerliği değiştirmez. Model, bu işlerliğin kuralını kurar; model çerçevenin kendisi değildir.

## Paylaşılan Modül ve Platforma Özgü Katman

Çapraz platform bir uygulamada kod iki parçaya ayrılır. **Paylaşılan modül** iki platformda aynı yazılan koddur: iş kuralları, veri modeli, akış mantığı. **Platforma özgü katman** her platformun kendi dilinde ve kendi API'siyle yazılan koddur: kamera, bildirim, dosya sistemi, biyometri. Paylaşılan modül bu yeteneklere doğrudan uzanmaz. İstediğini bir sözleşme olarak söyler; platforma özgü katman sözleşmeyi karşılar.

İki parçanın arasındaki çizgiye katman sınırı denir. Sınırın iyi çizilmesi, platforma özgü kodun az ve dar kalması demektir: paylaşılan modül ne istediğini söyler, hangi platformda nasıl karşılandığını bilmez. Aşağıdaki parça sözleşmeyi ve onu kullanan paylaşılan özelliği gösterir. Parça ölçülmez.

```kotlin
// Platform kodu: paylasilan sozlesme
interface PlatformLayer {
    val hasScanner: Boolean
    fun scan(onCode: (String) -> Unit)
}

class ScanFeature(private val layer: PlatformLayer) {
    fun open(onCode: (String) -> Unit): Boolean {
        if (!layer.hasScanner) return false
        layer.scan(onCode)
        return true
    }
}
```

`ScanFeature` iki platformda aynı koddur. Yeteneğin varlığını katmana sorar; yoksa `false` döner ve hiçbir şey olmaz. Sözleşmenin iki karşılığı platforma göre ayrılır. Android tarafı Kotlin'dedir, iOS tarafı aynı sözleşmenin Swift karşılığına uyar.

```kotlin
// Platform kodu: Android katmani (tarayici henuz yazilmadi)
class AndroidLayer : PlatformLayer {
    override val hasScanner = false
    override fun scan(onCode: (String) -> Unit) = Unit
}
```

```swift
// Platform kodu: iOS katmani
final class IosLayer: PlatformLayer {
    let hasScanner = true

    func scan(onCode: @escaping (String) -> Void) {
        // kamera oturumu kurulur, okunan kod onCode ile iletilir
    }
}
```

Model bu ayrımı bir işlevle kurar. `platformLayer(platform)` bir platformun katmanından koşul üretir: katman bir yeteneği karşılıyorsa koşulun `has` listesinde o yetenek vardır, karşılamıyorsa yoktur. Gerçek uygulamada yetenek kümesini kod aygıtın ve katmanın durumundan üretir; model de aynı yolu izler.

```javascript
// layers.mjs — platforma ozgu katmanin sundugu yetenekleri uretir
import { condition } from "./operability.mjs";

const LAYERS = {
  ios: ["network", "storage", "scanner"],
  android: ["network", "storage"],
};

export function platformLayer(platform, written = []) {
  return condition(platform, [...LAYERS[platform], ...written]);
}
```

İlk ölçümde iki özellik iki katmana karşı değerlendirilir. İkisi de yalnız her iki katmanın karşıladığı yeteneklere ihtiyaç duyar.

```javascript
// main.mjs
import { feature, assess, printLevels } from "./operability.mjs";
import { platformLayer } from "./layers.mjs";

const features = [
  feature("Catalog", ["network"], { network: "kisitli" }),
  feature("Profile", ["storage"]),
];
const conditions = [platformLayer("ios"), platformLayer("android")];
printLevels(assess(features, conditions));
```

```text
tam: Catalog @ ios eksik=-
tam: Profile @ ios eksik=-
tam: Catalog @ android eksik=-
tam: Profile @ android eksik=-
```

Dört kaydın dördü tamdır. Paylaşılan kodun iki platformda aynı işi gördüğü durum budur ve sık görülen durum da budur. Sınır, katmanın bir yeteneği karşılamadığı yerde görünür olur.

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

Sınırlayıcı ölçümde listeye tek bir özellik eklenir: `Scan`. Tarama özelliğinin iş mantığı paylaşılan modüldedir ve iki platformda aynı koddur. Ama kamerayı kullanabilmek için `scanner` yeteneği gerekir ve bu yetenek platforma özgü katmandan gelir. Senaryoda katman iOS için yazılmıştır, Android için henüz yazılmamıştır. `Scan` için yedek tanımlanmamıştır.

```javascript
// main.mjs
import { feature, assess, printLevels, countLevels } from "./operability.mjs";
import { platformLayer } from "./layers.mjs";

const features = [
  feature("Catalog", ["network"], { network: "kisitli" }),
  feature("Scan", ["scanner"]),
];
const conditions = [platformLayer("ios"), platformLayer("android")];
const records = assess(features, conditions);
printLevels(records);
countLevels(records);
```

```text
tam: Catalog @ ios eksik=-
tam: Scan @ ios eksik=-
tam: Catalog @ android eksik=-
kapali: Scan @ android eksik=scanner
tam: 3
kisitli: 0
ertelenen: 0
kapali: 1
etkilenen: 1
```

Dersin odak kaydı `Scan @ android`'dir ve kapalı çıkar. `Scan` iki platformda aynı paylaşılan koddur; iOS'ta tamdır. Android'de `scanner` yeteneği eksiktir, özelliğin o yetenek için yedeği yoktur, bu yüzden kural ikinci soruda kapalıya varır. Bu ölçümün etkilenen sayısı bir, açılıştaki dört değildir; iki ölçüm farklı kümeleri sayar.

**PM2.** Model, Android'de kameranın kullanılamadığını söylemez. Senaryo yalnız bu uygulamanın Android katmanında tarayıcı sözleşmesinin henüz karşılanmadığını kurar. `scanner` dersin kurgusudur ve çekirdek onu yorumlamaz. Katmanı yazmanın ne kadar iş olduğu modelde yoktur.

Bu sonuç M32/K01'in sorusundan farklıdır. O ders kodun platformlar arasındaki dağılımını sordu: ne kadarı paylaşılıyor, ne kadarı platforma özgü. İşlerlik bu soruyu sormaz. Tamamen paylaşılan bir modül de bir platformun koşulunda kapalı olabilir; işlerlik kodun nerede yazıldığını değil, o koşulda ne kadar çalıştığını sınıflar. Kodun ne kadarının paylaşıldığı kaydı değiştirmez, çünkü `feature` bir paylaşım oranı taşımaz ve kural yalnız `needs`, `fallback` ve `has`'e bakar. `Scan`'in iş mantığının tamamı paylaşılsa da bir kısmı paylaşılsa da `Scan @ android` aynı kalır.

Kapalıyı değiştiren şey platformun katmanıdır. İkinci ölçüm Android katmanına `scanner` yeteneğini yazdırır ve aynı özelliği yeniden değerlendirir.

```javascript
// main.mjs
import { feature, assess, printLevels } from "./operability.mjs";
import { platformLayer } from "./layers.mjs";

const scan = [feature("Scan", ["scanner"])];
printLevels(assess(scan, [platformLayer("android")]));
printLevels(assess(scan, [platformLayer("android", ["scanner"])]));
```

```text
kapali: Scan @ android eksik=scanner
tam: Scan @ android eksik=-
```

Paylaşılan modüldeki tek satır değişmedi; yalnız katman yeteneği karşıladı ve kayıt tama döndü. Kapalının bir başka çıkışı da yedek tasarlamaktır. `Scan` için kodun elle girilmesi gibi bir yedek tanımlansaydı aynı kayıt kısıtlı olurdu. Kapalı olması, bir yedeğin tasarlanmadığını söyler.

## Özet

- Bu dersin işlerliği: kapalı. `Scan @ android` kaydında `scanner` yeteneği eksiktir ve yedeği yoktur; paylaşılan modül tamamen ortak olsa da kayıt kapalı çıkar.
- İşlerlik bir kuralın çıktısıdır: eksik yetenek yoksa tam, yedeği olmayan bir eksik varsa kapalı, aksi hâlde eksiklerin en ağır yedeği (ertelenen, kısıtlıdan ağırdır).
- Açılış ölçümünde dokuz kaydın beşi tam, biri kısıtlı, ikisi ertelenen, biri kapalı çıktı; etkilenen dört.
- Paylaşılan modül sözleşmeyi söyler, platforma özgü katman yeteneği karşılar; katman sınırı bu çizgidir.
- Kodun paylaşım oranı kaydı değiştirmez; `Scan @ android` kapalıdan tama ancak Android katmanı `scanner` yeteneğini karşılayınca döndü.

## Sonraki Adım

Bu derste platforma göre değişen şey bir yetenekti ve eksik olduğunda özellik kapandı. Sıradaki ders, `Tasarım Sistemi Uyarlaması`, platforma göre değişen şeyin görünüm olduğu durumu ölçer: tek bir tasarım dili iki platformda farklı biçimde uyarlanır ve bir tarih seçici iki biçimde de tam çalışır.
