İçeriğe geç
academia.sh

Ders 16 / 19

Sağlık ve Ölçüm Uçları

Bir uygulama hiç yazılmadan var olan uçlarla ayağa kalkar — kabın kendisi ekler; yeni bir ölçüm ucu bir açıklamayla eklenebilir. Sınırlayıcı ölçüm ayrı bir daraltma bölümünde kapanır — kabın kurduğu varsayılan uçlar her bilgiyi açmaz, hangi alanın dışarı verildiği açık bir işaretlemeye bağlıdır, ve bu işaretleme yanlış bir alana konursa nesne kabı hiçbir hata vermeden onu da dışarı verir.

İçindekiler

Önceki ders hangi bileşenlerin kurulduğunu saydı — dilim testi iki, tam bağlam testi dört bileşen kurmuştu, ve ikisi de kaynakta yazılı bir kararın sonucuydu: bağlama tablosu. Bu ders hiç kurulmayan, hiç yazılmayan bir şeyi soruyor: bir uygulamanın çalışır durumda olup olmadığını dışarıdan soran uçlar var, ve bu uçların çoğu kaynakta hiç görünmüyor — ne bir sınıf, ne bir yöntem, ne bir açıklama. Sağlık ve ölçüm uçlarının kavramı ve gözlemlenebilirliğin genel çerçevesi M22/K06 Gözlemlenebilirlik ve İşletim kursunda kuruldu ve burada tekrarlanmıyor; bu ders yalnız bu uçların kaynakta ne kadar iz bıraktığını ve hangi bilginin dışarı verildiğini sayıyla ölçüyor. Gerçek bir ölçüm değeri, gerçek bir süre ya da gerçek bir bellek kullanımı yazılmıyor; sayılan şey uç sayısı ve alan varlığı. Ölçümün üçüncü bölümü ayrı bir daraltma bölümünde duruyor, çünkü varsayılan uçların var olması her bilginin dışarı verildiği anlamına gelmiyor — bu, ayrı bir karar.

Gerçek bir uygulamada sağlık ucu genellikle tek bir sözcük döndürür — çalışıyor mu, çalışmıyor mu — ve ölçüm ucu sayaçlar, oranlar, iç durumlar taşır. Bu ders ikisini de modelliyor, ama sorduğu soru sağlık ile ölçüm arasındaki fark değil; ikisinin de ortak noktası: kaynakta bir çağrı olmadan var olabilmeleri. /saglik bir sağlık ucu, /olcum/… öneki taşıyan her uç bir ölçüm ucu, ama ikisi de aynı kurala tabi — kabın kendisi ya otomatik olarak ekliyor ya da bir işaretten okuyor.

Uçlar: Kaynakta Hiç Geçmeyenler ve Açıklamadan Gelenler

Modellenen nesne kabı kurulduğu anda iki uçla doğuyor: /saglik ve /canlilik. Bu iki uç hiçbir uygulama sınıfının, hiçbir açıklamanın sonucu değil — kabın kurucusu içine yazılmış, her kurulumda otomatik olarak var olan bir çift. Üçüncü bir uç türü de var: bir bileşenin alanına konan @OlcumUcu işareti, nesne kabı tarafından okunup yeni bir uç olarak kaydediliyor.

// OlcumUcu.java — bir alani disari verilecek bir olcum ucu olarak isaretleyen aciklama tipi (yardimci kaynak, main yok)
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD)
@interface OlcumUcu { String ad(); }
// Kap.java — kurulur kurulmaz iki varsayilan ucu var eden, aciklamayla yeni uc ekleyebilen kucuk bir nesne kabi (yardimci kaynak, main yok)
import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;

class Kap {
    final Map<String, Supplier<String>> uclar = new LinkedHashMap<>();
    final int varsayilanUcSayisi;

    Kap() {
        // varsayilan uclar: hicbir uygulama sinifi bunlari hic cagirmiyor, kabin kendisi ekliyor
        uclar.put("/saglik", () -> "calisiyor");
        uclar.put("/canlilik", () -> "evet");
        varsayilanUcSayisi = uclar.size();
    }

    void kaydet(Object bilesen) {
        for (Field f : bilesen.getClass().getDeclaredFields()) {
            OlcumUcu o = f.getAnnotation(OlcumUcu.class);
            if (o == null) continue;
            f.setAccessible(true);
            uclar.put("/olcum/" + o.ad(), () -> {
                try { return String.valueOf(f.get(bilesen)); }
                catch (Exception e) { return "?"; }
            });
        }
    }

    String cagir(String yol) {
        Supplier<String> s = uclar.get(yol);
        return s == null ? "yok" : s.get();
    }

    static void goster(String etiket, Object deger) {
        System.out.printf("%-46s: %s%n", etiket, deger);
    }
}
// Uygulama.java — istek sayisi disari verilecek sekilde isaretlenmis, kalan iki alan hic isaretlenmemis (yardimci kaynak, main yok)
class Uygulama {
    @OlcumUcu(ad = "istek-sayisi") int istekSayaci = 42;
    String dahiliAnahtar = "ic-yapilandirma";
    String surum = "3";
}
// VarsayilanUclar.java — nesne kabi kurulur kurulmaz var olan uc sayisi, ve bir bilesen kaydedildikten sonraki toplam
public class VarsayilanUclar {
    public static void main(String[] args) {
        Kap kap = new Kap();
        Kap.goster("nesne kabi kurulur kurulmaz var olan uc sayisi", kap.varsayilanUcSayisi);
        Kap.goster("bu uclari kaynakta cagiran uygulama sinifi sayisi", 0);

        kap.kaydet(new Uygulama());
        Kap.goster("Uygulama kaydedildikten sonra toplam uc sayisi", kap.uclar.size());
        Kap.goster("/saglik", kap.cagir("/saglik"));
        Kap.goster("/canlilik", kap.cagir("/canlilik"));
        Kap.goster("/olcum/istek-sayisi", kap.cagir("/olcum/istek-sayisi"));
    }
}
nesne kabi kurulur kurulmaz var olan uc sayisi: 2
bu uclari kaynakta cagiran uygulama sinifi sayisi: 0
Uygulama kaydedildikten sonra toplam uc sayisi: 3
/saglik                                       : calisiyor
/canlilik                                     : evet
/olcum/istek-sayisi                           : 42

GT17. Kabın kurulduğu anda, hiçbir uygulama sınıfı hiç yazılmadan var olan uçlar vardır; bunlar varsayılandan doğar — /saglik ile /canlilik’in kaynakta karşılığı Kap’ın kurucusundaki iki satır, ve bu satırları hiçbir uygulama kodu çağırmıyor. GT18. Yeni bir ölçüm ucu bir açıklamayla eklenir; istekSayaci alanının üzerindeki @OlcumUcu işareti, /olcum/istek-sayisi ucunu doğuruyor, ama bu ucu okuyan çağrı Uygulama sınıfının içinde hiç yok — okuyan ve kaydeden taraf Kap’ın kendisi. Toplam üç uçtan ikisi kaynakta hiç geçmeden, biri bir işaretle var oluyor; kaynağı yalnızca okuyan biri Uygulama.java’da tek satır görür, ama uygulamanın dışarıya verdiği yüzey üç uçtan oluşuyor.

Varsayılan uçların sayısı sabit ve Kap’ın kurucusunda okunabilir; kaç tane olduğunu öğrenmek için hiçbir uygulama sınıfını taramaya gerek yok, varsayilanUcSayisi alanı kurulur kurulmaz bu sayıyı taşıyor. Açıklamadan gelen uçlar için durum farklı: onların sayısı kaydet çağrısının kaç kez ve hangi sınıflarla yapıldığına bağlı, ve bu sayı ancak uygulamanın bütün bileşenleri kaydedildikten sonra kesinleşiyor. İki türün bu farkı — biri sabit, biri kurulum zamanında büyüyen — dersin ilerleyen bölümünde tekrar karşımıza çıkacak: dağıtık yapılandırma dersinde de bazı değerler kurulurken sabitlenirken bazıları kurulumdan sonra değişebilecek.

Neyin Dışarı Verildiği Ayrı Bir Karardır

Uygulama sınıfı üç alan taşıyor, ama yalnız biri /olcum altında görünüyor. Kalan iki alan — dahiliAnahtar, surum — sınıfın içinde duruyor, hiçbir uç onları anmıyor, çünkü üzerlerinde hiçbir işaret yok. Bu, dersin en önemli ayrımı: bir bileşenin taşıdığı bilgi miktarı ile o bileşenin dışarı verdiği bilgi miktarı aynı şey değil.

// AlanSayisi.java — Uygulama'nin tasidigi toplam alan sayisi ile isaretli alan sayisi karsilastiriliyor
import java.lang.reflect.*;

public class AlanSayisi {
    public static void main(String[] args) {
        Kap kap = new Kap();
        Uygulama uygulama = new Uygulama();
        kap.kaydet(uygulama);

        int toplamAlan = Uygulama.class.getDeclaredFields().length;
        long isaretliAlan = 0;
        for (Field f : Uygulama.class.getDeclaredFields()) {
            if (f.isAnnotationPresent(OlcumUcu.class)) isaretliAlan++;
        }

        Kap.goster("Uygulama sinifinin tasidigi toplam alan sayisi", toplamAlan);
        Kap.goster("@OlcumUcu ile isaretli alan sayisi", isaretliAlan);
        Kap.goster("/olcum/dahili-anahtar (hic isaretlenmedi)", kap.cagir("/olcum/dahili-anahtar"));
        Kap.goster("/olcum/surum (hic isaretlenmedi)", kap.cagir("/olcum/surum"));
    }
}
Uygulama sinifinin tasidigi toplam alan sayisi: 3
@OlcumUcu ile isaretli alan sayisi            : 1
/olcum/dahili-anahtar (hic isaretlenmedi)     : yok
/olcum/surum (hic isaretlenmedi)              : yok

Üç alanın yalnız biri açığa çıkıyor; kalan ikisi için cagir yöntemi yok döndürüyor, çünkü Kap’ın uclar haritasında böyle bir anahtar hiç kayıtlı değil. GT19. Bir bileşenin taşıdığı alan sayısı ile dışarı verilen alan sayısı aynı değildir; yalnız işaretli alanlar dışarı çıkar, işaretsiz her alan kabın hiç bilmediği bir alan olarak kalır. GT20. Bu, dersin sınırlayıcı ölçümünün ilk yarısı: varsayılan uçların var olması her bilginin açıldığı anlamına gelmiyor. /saglik ve /canlilik var, ama bu ikisi Uygulama’nın iç durumuna hiç dokunmuyor; iç durumdan ne çıkacağı yalnızca işaretlemeyle belirleniyor, ve işaretleme yoksa hiçbir şey çıkmıyor. Kap’ın kaydet yöntemi Uygulama.class.getDeclaredFields() ile bütün alanları görüyor — dahiliAnahtar ve surum da bu taramadan geçiyor — ama işaret taşımayan her alan döngüde continue ile atlanıyor. Görülmek ile dışarı verilmek bu yüzden aynı şey değil: nesne kabı her alanı görüyor, yalnız işaretlenmiş olanı kaydediyor.

Genişletmenin Bedeli: Yanlış İşaretlenen Bir Alan

İşaretleme mekanizması iki yönlü çalışıyor: bir alanı @OlcumUcu ile işaretlemek onu görünür kılıyor, işaretlemeyi doğru alana koymak ise ayrı bir sorumluluk. Kap’ın kaydet yöntemi işaretli her alanı aynı biçimde işliyor — hangi alanın “güvenli” hangisinin “hassas” olduğuna dair hiçbir ayrım taşımıyor.

// HassasBilesen.java — iki alan da isaretli; biri olculmek istenen sayac, biri yanlislikla isaretlenmis ic bilgi (yardimci kaynak, main yok)
class HassasBilesen {
    @OlcumUcu(ad = "yapilandirma-anahtari") String dahiliAnahtar = "ic-yapilandirma-degeri";
    @OlcumUcu(ad = "aktif-oturum") int aktifOturumSayisi = 7;
}
// YanlisIsaretleme.java — nesne kabi iki isareti de ayni bicimde isliyor, hangisinin yanlislikla konuldugunu ayirt etmiyor
public class YanlisIsaretleme {
    public static void main(String[] args) {
        Kap kap = new Kap();
        kap.kaydet(new HassasBilesen());

        Kap.goster("/olcum/aktif-oturum (kastedilen olcum)", kap.cagir("/olcum/aktif-oturum"));
        Kap.goster("/olcum/yapilandirma-anahtari (yanlislikla isaretlendi)", kap.cagir("/olcum/yapilandirma-anahtari"));
        Kap.goster("nesne kabi bu isaretlemeyi reddetti mi", "hayir, hicbir hata verilmedi");
    }
}
/olcum/aktif-oturum (kastedilen olcum)        : 7
/olcum/yapilandirma-anahtari (yanlislikla isaretlendi): ic-yapilandirma-degeri
nesne kabi bu isaretlemeyi reddetti mi        : hayir, hicbir hata verilmedi

aktifOturumSayisi tam da amaçlanan şeyi ölçüyor — kaç oturum açık. dahiliAnahtar ise aynı işaretle yanlışlıkla dışarı verildi, ve Kap bu iki durumu ayırt etmiyor: ikisi de @OlcumUcu taşıyor, ikisi de aynı yoldan geçip aynı biçimde kaydediliyor. kaydet yönteminin kendisi bu iki alan arasında hiçbir fark görmüyor, çünkü zaten hiçbir fark gözlemleyecek bilgiye sahip değil — elinde yalnız bir alan adı, bir açıklama ve bir değer var; alanın “hassas” mı “zararsız” mı olduğuna dair hiçbir sınıflandırma yansımanın kendisinde bulunmuyor. Bu sınıflandırmayı yapacak taraf yalnızca @OlcumUcu işaretini koyan kişi, ve o karar bir kez yanlış verildiğinde kabın kendisi bunu düzeltmiyor. GT21. Yanlış bir alana konan ölçüm işareti nesne kabı tarafından hiçbir hata verilmeden dışarı verilir; bu, dersin sınırlayıcı ölçümünün ikinci yarısı. İlk yarı neyin dışarı verilmediğini gösterdi — işaretsiz alan hiç çıkmaz; ikinci yarı neyin yanlışlıkla dışarı verilebileceğini gösteriyor — işaretli her şey, doğru işaretlenmiş olsun ya da olmasın, çıkar. Sağlık ve ölçüm uçlarının kurduğu görünürlük bu yüzden tek yönlü bir güvenlik değil; hangi bilginin dışarı verildiği kaynaktaki işaretlerin toplamı kadar, o işaretlerin doğru konulup konulmadığına da bağlı.

Bu dersin dört ölçümü, hangi bilginin nereden geldiğini ve nereye çıktığını tek bir tabloda topluyor:

Soru Yanıt Kaynaktaki karşılığı
Kaç uç hiç kod yazılmadan var oldu 2 (/saglik, /canlilik) yok — kabın kurucusu
Kaç uç bir açıklamayla eklendi 1 (/olcum/istek-sayisi) @OlcumUcu işareti
Kaç alan taşınıyor, kaçı dışarı çıkıyor 3 alan, 1 dışarı çıkan işaretin varlığı
Yanlış işaretlenen alan reddediliyor mu hayır işaretin doğruluğu denetlenmiyor

Tablonun son satırı ilk üçünden farklı bir sınıfa ait: ilk üçü “ne var” sorusuna sayıyla yanıt veriyor, son satır “bu sayının ne kadar güvenilir olduğu” sorusuna yanıt veriyor — ve yanıt olumsuz. Bir uç noktanın var olması onun doğru amaçla var olduğu anlamına gelmiyor.

Özet

  • Kabın kurulduğu anda, hiçbir uygulama sınıfı hiç yazılmadan var olan uçlar vardır; bunlar varsayılandan doğar.
  • Yeni bir ölçüm ucu bir açıklamayla eklenir; kaynakta bu ucu çağıran hiçbir satır yoktur.
  • Bir bileşenin taşıdığı toplam alan sayısı ile dışarı verilen alan sayısı aynı değildir; yalnız işaretli alanlar dışarı çıkar.
  • Varsayılan uçların var olması her bilginin dışarı verildiği anlamına gelmez; hangi bilginin açıldığı ayrı, açık bir işaretleme kararıdır.
  • Yanlış bir alana konan ölçüm işareti nesne kabı tarafından hiçbir hata verilmeden dışarı verilir; işaretleme mekanizması “doğru” ile “yanlış” işaretlemeyi ayırt etmez.

Dört ölçümün ortak noktası, üçü de aynı kaynağı paylaşıyor olması: Kap’ın kendi kararı. İki varsayılan uç kabın kurucusunda, açıklama tabanlı uçların kabulü kaydet yönteminde, yanlış işaretlemenin fark edilmemesi de yine kaydet yönteminin ne yapmadığında yatıyor. Uygulama kodu bu üç kararın hiçbirini vermiyor; yalnız işareti koyuyor ya da koymuyor, geri kalanı kabın kuralı.

Sonraki Adım

Bu ders bir bileşenin iç durumunun dışarı nasıl sızdığını ölçtü. Sıradaki ders tersini soruyor: dışarıdaki bir değer içeri nasıl giriyor, ve bir kez girdikten sonra o değer değiştiğinde hangi bileşen bunu görüyor. Bir uygulamanın birden çok parçası aynı yapılandırma değerine bakıyorsa, değer değiştiğinde hepsinin aynı anda haberdar olup olmadığı hiç açık değil — sıradaki ders bunu koşturarak ölçüyor.

İ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