Ders 18 / 19
Mağaza İnceleme ve Politikalar
Uygulamanın beyan ettiği ama kullanmadığı izinleri modül başına sayar ve bütçeyle karşılaştırır. Kullanılmayan izinler çıkarılınca aşımın nasıl kapandığını, kuralın ise bulgunun ağırlığını görmediğini gösterir.
Yayın Güncelleme
Bu derste
- Uygulama mağazasının incelemesinin neyi denetlediğini ve neyi denetlemediğini ayırt eder
- Beyan edilen ama kullanılmayan izinleri modül başına sayar
- İzin bütçesini ekibin kararı olarak koyar ve modüllerin aşımını sınıflar
- Kullanılmayan izinler çıkarılınca aşımın kapandığını gösterir
İçindekiler
Önceki ders yayını aşama aşama genişletti ve her aşamada çökme sayısına baktı. Ama bir derleme kullanıcıya ulaşmadan önce, uygulama mağazasının kendi denetiminden de geçer. Mağaza, yüklenen her sürümü politikalara göre inceler (store review): uygulamanın beyan ettiği izinler gerçekten kullanılıyor mu, kullanıcı verisi nasıl işleniyor, mağaza sayfasındaki açıklama uygulamanın yaptığıyla örtüşüyor mu.
İncelemenin ayrıntısını bir mağazadan ötekine ve bir zamandan ötekine değişen politikalar belirler; bu ders politikaların içeriğini ya da kaç tane olduğunu saymaz. Onun yerine ekibin kendi elinde olan bir şeyi ölçer: uygulamanın beyan edip kullanmadığı izinler. Kursun sorusu burada da aynıdır: bu ölçüm bütçesini kaç örnekte aşıyor? Ölçüm bir modüldeki, beyan edilen ama kullanılmayan izin sayısıdır (policyFindings), bütçe ekibin kabul ettiği sayıdır, her modül bir örnektir.
// Overrun.kt — bir olcumun butcesini kac ornekte astigini siniflandirir
class Budget(val name: String, val limit: Int)
class Overrun(val label: String, val budget: Budget, samples: List<Int>) {
val total: Int = samples.size
val over: Int = samples.count { it > budget.limit }
val verdict: String = when {
over == 0 -> "icinde"
over == total -> "hepsinde"
over * 2 < total -> "azinda"
else -> "cogunda"
}
fun line() {
println("$label: butce=${budget.name}<=${budget.limit} | asan=$over/$total -> $verdict")
}
}
fun countOverruns(overruns: List<Overrun>) {
for (name in listOf("icinde", "azinda", "cogunda", "hepsinde")) {
println("$name: ${overruns.count { it.verdict == name }}")
}
}
Overrun sınırı kesin aşan örnekleri sayar ve yaygınlığı dört adla verir: içinde, azında, çoğunda, hepsinde. Kural kaç modülün aştığını görür; bir modülün bir mi yoksa üç kullanılmayan izin mi taşıdığı aşan her örnek için aynıdır.
İzin Beyanı
Bir uygulama, kullanıcının verisine ya da aygıtın bir donanımına erişmek istediğinde bu isteği bir bildirim dosyasında önceden beyan eder. Beyan, uygulamanın ne yapabileceğini kullanıcıya ve mağazaya söyleyen sözleşmedir.
<!-- Platform kodu: izin beyani --> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Bu parça bir yapılandırma dosyasıdır; çalıştırılmaz ve çıktı iddia etmiyoruz. Model, bu ölçümün kuralını kurar; model aracın kendisi değildir. Modelde bir izin bir addır; bir modül hem beyan ettiği izin kümesini hem de kodunda gerçekten kullandığı izin kümesini taşır. Bulgu, ikisinin farkıdır: beyan edilip kullanılmayan izin.
Bu bulgunun neden önemli olduğunu düşünmek kolaydır. Kullanılmayan bir izin kullanıcıya gereksiz bir istek gibi görünür ve incelemede açıklama gerektirir. Bu yüzden ekipler izinleri yalnız gerçekten kullandıkları kadar beyan etmeye çalışır.
Beyan iki ayrı okura söylenir ve ikisi farklı şeyi arar. Kullanıcı beyanı bir istek olarak görür: uygulama kameraya erişmek istiyor, buna izin verilsin mi? Mağaza beyanı bir tutarlılık sorusu olarak okur: beyan edilen şey uygulamanın açıklamasıyla ve davranışıyla örtüşüyor mu? Yukarıdaki iki satırlık parça bu yüzden yalnız bir yapılandırma değildir; ekibin kullanıcıya ve mağazaya verdiği bir sözdür. Söz gereğinden geniş verilirse kullanıcı gereksiz bir izin görür ve mağaza açıklama ister. Dar verilirse özellik çalışmaz. İkisinin arasındaki yol, beyan kümesiyle kullanım kümesini eşitlemektir ve bu dersin ölçümü bu eşitsizliği sayar.
Modeli Kurmak
Yardımcı dosya sekiz modülü, her birinin beyan ettiği ve kullandığı izinleri ve bulgu sayısını kurar. İzin adları düz sözcüklerdir; platformdaki gerçek adlar değil, derste kullanılan kısa etiketlerdir.
// PolicyModel.kt — beyan edilen ama kullanilmayan izinleri modul basina modeller
class AppModule(val label: String, val declared: Set<String>, val used: Set<String>)
fun unusedPermissions(module: AppModule): List<String> =
(module.declared - module.used).sorted()
fun policyFindings(module: AppModule): Int = unusedPermissions(module).size
fun trimmed(module: AppModule): AppModule =
AppModule(module.label, module.declared.intersect(module.used), module.used)
fun appModules(): List<AppModule> = listOf(
AppModule("ana", setOf("konum", "kamera"), setOf("konum")),
AppModule("giris", setOf("kisiler"), setOf("kisiler")),
AppModule("odeme", setOf("kamera", "konum", "kisiler"), setOf("kamera")),
AppModule("harita", setOf("konum", "depolama"), setOf("konum")),
AppModule("profil", setOf("kamera", "depolama", "kisiler"), setOf("kamera", "depolama")),
AppModule("arama", setOf("mikrofon"), setOf("mikrofon")),
AppModule("yardim", setOf("konum", "takvim"), emptySet()),
AppModule("ayarlar", setOf("depolama", "takvim"), setOf("takvim")),
)
Bulguların Ölçümü
Ekibin kuralı basittir: bir modül, kullanmadığı hiçbir izni beyan etmemeli. Bütçe sıfırdır: tek bir kullanılmayan izin bile aşımdır.
// Main.kt — her modulun kullanilmayan izinleri sayilir, butce sifir
fun main() {
val modules = appModules()
for (module in modules) {
println("${module.label}: kullanilmayan=${unusedPermissions(module)}")
}
val samples = modules.map { policyFindings(it) }
println("bulgu: $samples")
Overrun("kullanilmayan-izin", Budget("bulgu", 0), samples).line()
}
ana: kullanilmayan=[kamera] giris: kullanilmayan=[] odeme: kullanilmayan=[kisiler, konum] harita: kullanilmayan=[depolama] profil: kullanilmayan=[kisiler] arama: kullanilmayan=[] yardim: kullanilmayan=[konum, takvim] ayarlar: kullanilmayan=[depolama] bulgu: [1, 0, 2, 1, 1, 0, 2, 1] kullanilmayan-izin: butce=bulgu<=0 | asan=6/8 -> cogunda
Altı modül, bütçe sıfırken aştı; yalnız giris ve arama temiz çıktı. Sekizin yarısından fazlası aştığı için yanıt çoğunda. Bu, dersin aşımıdır.
DA3. Model bir izni bir ad olarak sayar. Gerçekte bir izin yalnız bir modülden değil birden çok modülden kullanılabilir, bir izin başka bir izinle birlikte gelebilir ya da bir kitaplık bir izni uygulamanın haberi olmadan ekleyebilir. Model bu üç durumu kurmaz. Beyan ve kullanım kümeleri de elle yazılmış girdilerdir; gerçek bir uygulamada kullanım, kodun taranmasından çıkar.
Bütçe Bir Karardır
Aynı sekiz modülü üç ayrı bütçeyle ölçelim: iki, bir, sıfır kullanılmayan izin.
// Main.kt — ayni sekiz modul uc ayri butceyle uc ayri asim verir
fun main() {
val samples = appModules().map { policyFindings(it) }
val roomy = Overrun("iki-izin", Budget("bulgu", 2), samples)
val normal = Overrun("bir-izin", Budget("bulgu", 1), samples)
val strict = Overrun("sifir-izin", Budget("bulgu", 0), samples)
listOf(roomy, normal, strict).forEach { it.line() }
countOverruns(listOf(roomy, normal, strict))
}
iki-izin: butce=bulgu<=2 | asan=0/8 -> icinde bir-izin: butce=bulgu<=1 | asan=2/8 -> azinda sifir-izin: butce=bulgu<=0 | asan=6/8 -> cogunda icinde: 1 azinda: 1 cogunda: 1 hepsinde: 0
Bütçe ikiyken hiçbir modül aşmadı. Bire inince yalnız iki kullanılmayan izni olan odeme ve yardim aştı. Sıfırda altı modül aştı. Üç sonuç aynı ölçümden çıktı; birbirini çürütmez, yalnız bütçenin neyi kabul ettiğini gösterir. Bütçeyi sıfıra koymak sıkı bir ekip kuralıdır ve kural gevşetilmediği sürece yanıt hepsinde çıkamaz, çünkü iki modül hiç bulgu taşımaz.
Sayım Ağırlığı Görmez
Sayım iki bulguyu eşit sayar, oysa bulguların hepsi aynı ağırlıkta değildir. Kamera, konum, kişiler ve mikrofon izinleri kullanıcının daha hassas verisine uzanır; depolama ve takvim izinleri derste daha az hassas varsayılacaktır. Bu bir model varsayımıdır, platformun sınıflandırması değildir.
// Main.kt — sayim agirligi gormez, hassas izin sayisi ayri olculur
fun main() {
val sensitive = setOf("kamera", "konum", "kisiler", "mikrofon")
val modules = appModules()
for (module in modules) {
val unused = unusedPermissions(module)
val heavy = unused.count { it in sensitive }
println("${module.label}: bulgu=${unused.size} hassas=$heavy")
}
val samples = modules.map { policyFindings(it) }
Overrun("kullanilmayan-izin", Budget("bulgu", 0), samples).line()
}
ana: bulgu=1 hassas=1 giris: bulgu=0 hassas=0 odeme: bulgu=2 hassas=2 harita: bulgu=1 hassas=0 profil: bulgu=1 hassas=1 arama: bulgu=0 hassas=0 yardim: bulgu=2 hassas=1 ayarlar: bulgu=1 hassas=0 kullanilmayan-izin: butce=bulgu<=0 | asan=6/8 -> cogunda
harita ve ayarlar modülleri bir bulgu taşır ama hassas bulguları yoktur; ana ve profil de bir bulgu taşır ve bulgunun hassas olduğu görülür. Kural dördünü aynı sayar: dördü de aşan örnektir. Kategori çoğunda, ve bu kategori hangi modülün incelemede daha riskli olduğunu söylemez.
İncelemenin kararı bu sayımdan çıkmaz. Mağaza bir sürümü reddedebilir ya da düzeltme isteyebilir; bu karar kategoriye değil, incelemenin kendi değerlendirmesine bağlıdır. Model ret kararını kurmaz ve burada ret ya da kabul iddia etmiyoruz.
DA4. Hassaslık ayrımı bu derste varsayılmış bir kümedir; hangi iznin hassas sayılacağı gerçek bir mağaza politikasında ayrıca belirlenir ve zamanla değişir. Model bu kümeyi bir girdi olarak alır.
Sürümler Arası Fark
Beyan bir kez yazılıp kalmaz; her sürümde yeni bir izin eklenebilir. Yeni sürümde eklenen bir izin, incelemede gerekçesi sorulabilecek yeni bir beyandır. Bu yüzden ekip için asıl soru yalnız bugünkü fazlalık değil, bu sürümde ne eklendiğidir. Aşağıdaki ölçüm her modül için önceki sürümün beyanını bir girdi olarak alır ve iki sayım verir: eklenen izinlerin sayısı ve eklenen izinlerden kullanılmayanların sayısı. Bütçe ikisinde de sıfırdır.
// Main.kt — yeni surumde eklenen izinlerin kac tanesi kullanilmiyor
fun main() {
val previous = mapOf(
"ana" to setOf("konum"),
"giris" to setOf("kisiler"),
"odeme" to setOf("kamera", "konum"),
"harita" to setOf("konum", "depolama"),
"profil" to setOf("kamera", "depolama", "kisiler"),
"arama" to emptySet<String>(),
"yardim" to setOf("konum"),
"ayarlar" to setOf("depolama", "takvim"),
)
val modules = appModules()
val added = modules.map { it.declared - previous.getValue(it.label) }
val addedUnused = modules.mapIndexed { index, module -> (added[index] - module.used).size }
println("eklenen: ${added.map { it.size }}")
println("eklenen ve kullanilmayan: $addedUnused")
val budget = Budget("izin", 0)
Overrun("eklenen", budget, added.map { it.size }).line()
Overrun("eklenen-kullanilmayan", budget, addedUnused).line()
}
eklenen: [1, 0, 1, 0, 0, 1, 1, 0] eklenen ve kullanilmayan: [1, 0, 1, 0, 0, 0, 1, 0] eklenen: butce=izin<=0 | asan=4/8 -> cogunda eklenen-kullanilmayan: butce=izin<=0 | asan=3/8 -> azinda
DA5. Önceki sürümün beyanı elle yazılmış bir girdidir ve modül adlarının sürümler arasında değişmediği varsayılır. Gerçekte bir modül bölünebilir, birleşebilir ya da yeniden adlandırılabilir; model bu durumları kurmaz. Eklenen iznin yeni bir özellik için mi yoksa bir kitaplığın yan etkisi olarak mı geldiğini de ayırt etmez.
Sınırlayıcı Ölçüm
Kullanılmayan izinleri çıkaralım: her modülün beyanı yalnız kullandığı izinlere iner. Bu, bulgunun tam olarak kapandığı durumdur. Sınırlayıcı ölçüm bu yüzden dersin sorusuna verilebilecek en iyi yanıtı gösterir ve bütçenin ulaşılabilir olup olmadığını söyler.
// Main.kt — kullanilmayan izinler cikarilinca butun moduller butceye girer
fun main() {
val before = appModules()
val after = before.map { trimmed(it) }
val budget = Budget("bulgu", 0)
val beforeSamples = before.map { policyFindings(it) }
val afterSamples = after.map { policyFindings(it) }
Overrun("once", budget, beforeSamples).line()
Overrun("sonra", budget, afterSamples).line()
println("beyan once: ${before.sumOf { it.declared.size }}")
println("beyan sonra: ${after.sumOf { it.declared.size }}")
}
once: butce=bulgu<=0 | asan=6/8 -> cogunda sonra: butce=bulgu<=0 | asan=0/8 -> icinde beyan once: 16 beyan sonra: 8
Kullanılmayan izinler çıkarılınca aşım çoğunda kategorisinden içinde kategorisine indi; beyan edilen izin sayısı on altıdan sekize düştü. Bu sonuç bir sayımdır: sekiz izin uygulamanın kodunda hiç kullanılmıyordu ve çıkarılması işlevi değiştirmedi. Çıkarılan izinlerden birinin kodda başka bir yolla kullanıldığı ortaya çıkarsa, kullanım kümesi yanlıştı demektir. O zaman düzeltilmesi gereken beyan değil, kullanımın nasıl tespit edildiğidir. Bu sonuç bütçenin ulaşılabilir olduğunu gösterir, ama ulaşmanın bedelini göstermez. Sekiz iznin çıkarılması işlevi değiştirmedi, ancak bir iznin gerçekten kullanılmadığını söylemek kullanımın nasıl tespit edildiğine bağlıdır. Model kullanım kümesini girdi olarak aldı; gerçek bir uygulamada bu küme koddan çıkarılır ve çıkarım dolaylı kullanımları, örneğin bir kitaplığın uygulama adına yaptığı çağrıları kaçırabilir. Bu yüzden sınırlayıcı ölçümün sonucu, çıkarmadan önce kullanımın bağımsız bir yolla doğrulanması koşuluyla okunur.
Kullanım Kümesi Nereden Gelir
Dersin ölçümü iki kümenin farkına dayanır, ama kümelerden yalnız biri bir dosyada yazılıdır. Beyan kümesi bildirim dosyasından okunur ve açıktır. Kullanım kümesi ise kodun hangi izin gerektiren çağrıları yaptığının sonucudur ve bir tarama ya da bir derleyici çıktısı ister. Bu iki kaynağın güvenilirliği aynı değildir: beyan kesindir, kullanım bir çıkarımdır. Fark bu asimetriden doğar. Kullanım kümesi eksik hesaplanırsa fazlalık olduğundan büyük görünür ve çıkarılan bir izin bir özelliği kırar. Kullanım kümesi fazla hesaplanırsa fazlalık olduğundan küçük görünür ve gereksiz bir izin kalır. İlk hata kullanıcıya, ikincisi incelemeye yansır.
Ekip bu yüzden iki yönü de ayrı ayrı sınar: her çıkarılan izin için o izni kullanan özelliğin gerçekten bulunmadığını, her kalan izin için de kullanan bir özelliğin bulunduğunu doğrular. Model bu doğrulamayı kurmaz; kullanım kümesini doğru kabul eder ve yalnız farkı sayar.
Yaygın Yanılgılar
“Bulgu yoksa inceleme geçilir.” Geçilmez. Sayım yalnız beyan ile kullanım arasındaki farkı ölçer; inceleme başka politikaları da denetler.
“Bulgu sayısı azsa risk azdır.” Sayı bulgunun ağırlığını göstermez. Bir hassas bulgu, birkaç hassas olmayan bulgudan daha önemli olabilir.
“Yeni izin eklemek her zaman bir sorundur.” Sorun, eklenip kullanılmayan izindir. arama modülü bu sürümde yeni bir izin ekledi ve izin kodda kullanılıyordu; ilk sayımda aşım görünse de ikinci sayımda görünmedi.
“Beyanı küçültmek özellikleri etkilemez.” Kullanım kümesi doğruysa etkilemez. Kullanım kümesi eksikse, yani bir izin kodda başka bir yolla kullanılıyorsa, beyanı küçültmek o özelliği kırar. Küçültmeden önce kullanım tespitinin güvenilir olduğunu doğrulamak gerekir.
“Her izin çıkarılmalıdır.” Yalnız kullanılmayanlar çıkarılır. Kullanılan bir izni çıkarmak, o özelliği çalışmaz hâle getirir.
“Hassas olmayan izin sorun değildir.” Hassaslık kümesi bu derste bir varsayımdı. Hassas sayılmayan bir izin de kullanılmıyorsa bütçeyi aşar ve incelemede açıklama ister. Hassaslık yalnız hangi bulgunun önce ele alınacağını sıralamaya yarar; bulgunun varlığını ortadan kaldırmaz.
“Beyanı temiz tutmak tek seferlik bir iştir.” Her sürümde yeni bir özellik yeni bir izin getirebilir ve bir özellik kaldırıldığında izin beyanda kalabilir. Bu yüzden sayım bir sürüm kapısında, her yayından önce tekrar koşar; bir kez koşup kapanan bir denetim, bir sonraki sürümde yeniden fazlalık biriktirir.
“Bütçeyi sıfır tutmak her zaman gerçekçidir.” Sıfır, bu derste ekibin seçtiği sıkı bir kuraldı. Üç bütçe ölçümü gösterdi ki aynı sekiz modül sıfırda çoğunda, birde azında, ikide içinde çıkar. Gerçekçi bütçe, ekibin hangi bulguyu inceleme öncesinde kapatabildiğine bağlıdır.
Özet
- Bu dersin aşımı: çoğunda. Sekiz modülden altısı, sıfırlık bütçede kullanılmayan izin taşıdı; yarısından fazlası aştığı için yanıt çoğunda.
- Mağaza incelemesi politikalara göre denetler; bu ders politikaların içeriğini değil, ekibin elindeki bulgu sayımını ölçtü.
- Aynı sekiz modül iki, bir ve sıfır bütçelerinde sırayla içinde, azında ve çoğunda çıktı.
- Kural dört bulguyu aynı sayar ama iki tanesi hassas izindi; sayım ağırlığı ve ret kararını göstermez.
- Önceki sürüme göre eklenen izinlerin kusuru eklenmesinde değil, kullanılmamasındadır; iki sayım bunu ayırır.
- Kullanılmayan izinler çıkarılınca beyan on altıdan sekize indi ve aşım içinde oldu.
Sonraki Adım
Uygulama incelemeden geçti, aşama aşama genişledi ve kullanıcılara ulaştı. Ancak yayın bitmedi; kullanıcılar uygulamayı gerçek koşullarda kullanmaya başlayınca asıl veri gelir. Sıradaki ders, Yayın Sonrası İzleme, yayından sonraki günlerin çökme sayısını bütçeyle karşılaştırır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.