İçeriğe geç
academia.sh

Ders 08 / 10

Yerel Modül İhtiyacı

Ortak kod her platform yeteneğine ulaşamaz. Ders, biyometrik doğrulama isteğini her platformda ayrı yazılan bir yerel modül olarak ikiz diye sınıflar ve yalnız bir platformda bulunan yeteneğin tek çıktığını ölçer.

Yayın Güncelleme

Bu derste

  • Platform yeteneğine dokunan kodun neden yerel modül gerektirdiğini açıklar
  • İki platformda ayrı yazılan biyometrik doğrulama modülünü ikiz olarak sınıflar
  • Ortak koddan yerel modüle yapılan çağrının ortak kalabildiğini, modülün ise ikiz kaldığını ölçer
  • Yalnız bir platformda bulunan yeteneğin özelliğini tek olarak sınıflar
İçindekiler

Önceki ders gezinme kalıbını ortak koddan seçmenin mümkün olduğunu gösterdi, çünkü seçim yalnız bir dizgiydi. Aynı yol platformun kendi yeteneğine dokunan bir işte kapanır: kullanıcının yüzünü ya da parmak izini okuyan donanım ortak koddan çağrılamaz. Ortak kod, platformun sunduğu yeteneği ancak o platformda yazılmış bir parça aracılığıyla kullanır. Kursun sorusu aynı kalır: bu özelliğin kodu platformlar arasında nasıl paylaşılıyor? Dört yanıtın tanımı açılış dersindeki gibidir ve burada yeniden yazılmaz.

Kuralı çekirdek verir ve her derste aynı dosyayla gelir.

// sharing.mjs — bir ozelligin kodunun platformlar arasinda nasil paylasildigini siniflandirir
export const PLATFORMS = ["ios", "android"];

export class Sharing {
  constructor(label, impl, samples) {
    this.label = label;
    this.total = samples.length;
    this.missing = PLATFORMS.filter((p) => typeof impl[p] !== "function");
    const present = PLATFORMS.filter((p) => !this.missing.includes(p));
    this.code = new Set(present.map((p) => impl[p])).size;
    if (this.missing.length > 0) {
      this.differ = null;
      this.verdict = "tek";
      return;
    }
    this.differ = samples.filter((s) => {
      const outs = PLATFORMS.map((p) => JSON.stringify(impl[p](s, p)));
      return new Set(outs).size > 1;
    }).length;
    if (this.code > 1) this.verdict = "ikiz";
    else this.verdict = this.differ === 0 ? "ortak" : "dalli";
  }

  line() {
    const detail = this.differ === null
      ? `eksik=${this.missing.join(",")}`
      : `fark=${this.differ}/${this.total}`;
    console.log(`${this.label}: kod=${this.code} | ${detail} -> ${this.verdict}`);
  }
}

export function countSharing(items) {
  for (const name of ["ortak", "dalli", "ikiz", "tek"]) {
    console.log(`${name}: ${items.filter((s) => s.verdict === name).length}`);
  }
}

Yerel Modül Nedir

Yerel modül (native module), platformun kendi dilinde yazılmış ve ortak koddan çağrılan küçük bir parçadır. Biyometrik doğrulamada bu parça, platformun doğrulama arayüzünü açar ve sonucu ortak koda geri döndürür. Ortak kod modülün içini bilmez; yalnız adını ve aldığı değerleri bilir. Bu çağrı yoluna platform kanalı (platform channel) denir: ortak koddan platforma bir ad ve bir bağımsız değişken gider, platformdan bir yanıt gelir.

Modülün yazılması gerekir, çünkü doğrulama penceresini ortak kod çizemez. Pencerenin biçimi, kayıtlı yüz ya da parmak izinin okunuşu, kullanıcı vazgeçtiğinde dönen durum, hepsi platformun işidir. İki platformun arayüzleri farklı olduğu için ortaya iki ayrı parça çıkar.

PG1. Model, bu paylaşımın kuralını kurar; model çerçevenin kendisi değildir. Modelde biyometrik doğrulama, kayıt durumunu alıp bir istek dizgisi döndüren işlevdir; ekranda hiçbir pencere açılmaz. Gerçek modül ise her platformda şuna benzer iki parçadır.

// Platform kodu: IosBiometricModule
import LocalAuthentication

func requestBiometric(reply: @escaping (Bool) -> Void) {
    let context = LAContext()
    var error: NSError?
    guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
        reply(false)
        return
    }
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
                           localizedReason: "Hesabini ac") { success, _ in
        reply(success)
    }
}
// Platform kodu: AndroidBiometricModule
fun requestBiometric(activity: FragmentActivity, reply: (Boolean) -> Unit) {
    val executor = ContextCompat.getMainExecutor(activity)
    val callback = object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) = reply(true)
        override fun onAuthenticationError(code: Int, message: CharSequence) = reply(false)
    }
    val info = BiometricPrompt.PromptInfo.Builder()
        .setTitle("Hesabini ac")
        .setNegativeButtonText("Vazgec")
        .build()
    BiometricPrompt(activity, executor, callback).authenticate(info)
}

İki parça aynı adı taşır ve aynı işi yapar, ama aralarında ortak tek satır yoktur: biri bir bağlam nesnesi ve politika ister, öbürü bir activity nesnesi, bir yürütücü ve bir geri çağrı nesnesi. Parçalar çıktı vermez; ölçülen yalnız modeldeki iki işlevdir.

Bu soru, M31/K02’de sorduğumuz soruya benzer ama aynı değildir. Orada bir isteğin çalışma anındaki sonucu sınıflanıyordu: tam, ikame, bekleyen ya da karşılıksız. Burada sonuç sınıflanmaz; isteği yapan kodun platformlar arasındaki dağılımı sınıflanır. Aynı istek bir platformda tam, öbüründe karşılıksız sonuçlansa bile kod yine ikiz olabilir.

İki Platform, İki Modül

Model, her platformun kayıt durumuna göre ne yaptığını gösteren iki ayrı işlevdir: iosBiometric ve androidBiometric. Örnekler dört kayıt durumudur: parmak izi kayıtlı, yüz kayıtlı, hiç kayıt yok, kilitli. İki işlev ayrı nesnelerdir; kural bunu kod sayısı olarak görür.

// main.mjs — biyometrik dogrulama istegi her platformda ayri yazilir
import { Sharing } from "./sharing.mjs";

const states = ["parmak-izi", "yuz", "kayit-yok", "kilitli"];

function iosBiometric(state) {
  if (state === "kayit-yok") return "parola-yedegi";
  if (state === "kilitli") return "bekle";
  return "yerel-onay-penceresi";
}

function androidBiometric(state) {
  if (state === "kayit-yok") return "ayara-yonlendir";
  if (state === "kilitli") return "bekle";
  return "sistem-onay-penceresi";
}

new Sharing("biyometrik-istek", { ios: iosBiometric, android: androidBiometric }, states).line();
biyometrik-istek: kod=2 | fark=3/4 -> ikiz

Kod iki, ve dört durumun üçünde iki platformun isteği ayrılıyor. Kilitli durumda iki modül de bekliyor; bu örnekte sonuç aynı çıksa da özellik ikizdir, çünkü kural önce kod sayısına bakar. Burada dallı çıkması mümkün değildir: iki ayrı işlev verildiğinde sonuç ne olursa olsun kural ikiz der.

Bir modül yazmanın bedeli iki yerde ödenir. Her yeni durum, örneğin ikinci bir doğrulama türü, iki modüle ayrı ayrı eklenir. Her hata düzeltmesi de iki modülde aranır. Kural bu bedeli görmez: üç satırlık bir ikiz ile üç yüz satırlık bir ikiz aynı sınıfa girer. Bedelin büyüklüğünü düzyazı söyler.

Çağrı Ortak, Modül İkiz

Aynı özelliğin iki parçası vardır ve ikisi aynı biçimde paylaşılmaz. Çağrıyı yapan taraf ortak kodda durur: kanal adını ve bağımsız değişkeni hazırlar, çağrıyı gönderir. Çağrının karşılandığı taraf yerel modüldür. Çağrı iki platformda da aynıdır, çünkü ortak koddur; karşılayan taraf aynı değildir.

// main.mjs — ortak koddan yerel module giden cagri
import { Sharing, countSharing } from "./sharing.mjs";

const states = ["parmak-izi", "yuz", "kayit-yok", "kilitli"];

function invokeModule(state) {
  return { channel: "biyometrik", argument: state };
}

function channelName() {
  return "biyometrik";
}

const rows = [
  new Sharing("kanal-cagrisi", { ios: invokeModule, android: invokeModule }, states),
  new Sharing("kanal-adi", { ios: channelName, android: channelName }, states),
];
rows.forEach((r) => r.line());
countSharing(rows);
kanal-cagrisi: kod=1 | fark=0/4 -> ortak
kanal-adi: kod=1 | fark=0/4 -> ortak
ortak: 2
dalli: 0
ikiz: 0
tek: 0

İki satırda da kod bir ve fark sıfır; ikisi de ortaktır. channelName sabit dönüş verdiği için ortak olmaya mahkûmdur. invokeModule ise bir argümanı sarıp ileten gerçek bir işlevdir ve yine de iki platformda aynı sonucu verir, çünkü platform farkı çağrının içinde değil, çağrının karşılığındadır. Ortak kodun çağrısı ortak kalır; özelliğin geri kalanı kalmaz.

Aynı Özellik, İki Ölçüm Düzeyi

Bir özelliğin paylaşımı, kurala hangi işlev nesnelerini verdiğinize bağlıdır. Çağıran tarafta platforma göre doğru modülü seçen tek bir sarmalayıcı yazalım. Bu sarmalayıcıyı iki platform için de aynı nesne olarak verirsek kural kod sayısını bir görür. Modüllerin kendisini verirsek iki görür.

// main.mjs — ayni ozellik, iki olcum duzeyi
import { Sharing, countSharing } from "./sharing.mjs";

const states = ["parmak-izi", "yuz", "kayit-yok", "kilitli"];

function iosBiometric(state) {
  if (state === "kayit-yok") return "parola-yedegi";
  if (state === "kilitli") return "bekle";
  return "yerel-onay-penceresi";
}

function androidBiometric(state) {
  if (state === "kayit-yok") return "ayara-yonlendir";
  if (state === "kilitli") return "bekle";
  return "sistem-onay-penceresi";
}

function authenticate(state, platform) {
  return platform === "ios" ? iosBiometric(state) : androidBiometric(state);
}

const rows = [
  new Sharing("yerel-modul", { ios: iosBiometric, android: androidBiometric }, states),
  new Sharing("dogrulama-sarmalayici", { ios: authenticate, android: authenticate }, states),
];
rows.forEach((r) => r.line());
countSharing(rows);
yerel-modul: kod=2 | fark=3/4 -> ikiz
dogrulama-sarmalayici: kod=1 | fark=3/4 -> dalli
ortak: 0
dalli: 1
ikiz: 1
tek: 0

Modüller ikiz, sarmalayıcı dallı. İkisi aynı özelliğin iki yüzüdür ve kural ikisine iki ayrı yanıt verir.

PG2. Model, kuralın hangi işlevi gördüğünü ölçer; ekibin özelliği hangi sınırda kestiğini ölçmez. Bu derste özelliğin kodu denince yerel modül anlaşılır, çünkü ihtiyaç duyulan şey odur. Sarmalayıcıyı ölçmek yanlış değildir ama başka bir soruya yanıt verir: seçimin tek yerde yapılıp yapılmadığına.

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

Şimdi bir yeteneğin yalnız bir platformda bulunduğunu varsayalım. Uygulama arka plana alınırken ekranı bulanıklaştıran bir gizlilik yeteneği olsun. Yeteneğin yalnız iOS tarafında bulunduğunu kabul ediyoruz; Android tarafında karşılığı yok. Modül yalnız tek tarafta yazılır. Ortak koddan modüle giden çağrı ise iki platformda da aynı kalır.

PG3. Burada varsayım, yeteneğin yalnız bir platformda bulunmasıdır; model bunu platformun gerçek durumu olarak sunmaz, bir ihtiyaç örneği olarak kurar. Gerçek bir yeteneğin hangi platformlarda bulunduğu platform belgesinden doğrulanmadan bir ders ya da ürün kararına dayanak yapılmaz.

// main.mjs — yalniz bir platformda bulunan yetenek
import { Sharing, countSharing } from "./sharing.mjs";

const states = ["on-plan", "arka-plan", "kilitli"];

function invokeModule(state) {
  return { channel: "gizlilik", argument: state };
}

function iosPrivacyScreen(state) {
  return state === "arka-plan" ? "bulaniklastir" : "goster";
}

const rows = [
  new Sharing("kanal-cagrisi", { ios: invokeModule, android: invokeModule }, states),
  new Sharing("gizlilik-ekrani", { ios: iosPrivacyScreen }, states),
];
rows.forEach((r) => r.line());
countSharing(rows);
kanal-cagrisi: kod=1 | fark=0/3 -> ortak
gizlilik-ekrani: kod=1 | eksik=android -> tek
ortak: 1
dalli: 0
ikiz: 0
tek: 1

Çağrı ortak, özellik tek. Kural eksik tarafı ayrıca yazar: eksik=android. Ortak kodun çağrısı iki platformda da çalışsa da çağrının karşılığı bir platformda yoktur ve özelliğin kodu orada yazılmamıştır. Bu bir hata değildir; yalnız bir platformun sunduğu bir yetenekte ortak kodun yapabileceği en fazla şey, o platformda çağrıyı sessizce karşılamamak ya da bir yedek yazmaktır.

Tek, ikiz kadar bedelli olmayabilir. İkizde iki modülün birlikte yaşatılması gerekir; tekte bakılacak tek modül vardır. Ama tek, özelliğin iki platformda aynı görünmediğini de söyler. Kural bu eşitsizliğin kullanıcıya etkisini görmez; bunu ekip tartar.

Özet

  • Bu dersin paylaşımı: ikiz. Biyometrik doğrulama isteği her platformda ayrı bir yerel modül olarak yazıldı ve kural iki kod saydı.
  • Ortak koddan modüle giden çağrı ortak çıktı; çağrı ortak kalsa da modül ikiz kaldı.
  • Aynı özellik, modüller verilince ikiz, onları seçen sarmalayıcı verilince dallı çıktı: kural hangi işlevi gördüğünü ölçer.
  • Yalnız bir platformda bulunan yeteneğin modülü tek çıktı; ortak kodun çağrısı ortak olsa da özelliğin kodu bir platformda yoktur.
  • Kural kod sayısını görür, modülün büyüklüğünü ve bakım bedelini görmez; bunları düzyazı söyler.

Sonraki Adım

Bu derste yerel modül bir doğrulama penceresini açtı ve iş birimi olarak sayılacak bir şey üretmedi. Sıradaki ders, Başarım Beklentileri, yerel kodun bir başka nedenini ele alır: sık çalışan bir yolu ortak koddan çıkarıp yerel kod olarak yazmanın, ortak koddan her geçişte neye mal olduğunu.

İ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