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.