Dinamik kapsamda bir dilde çalışmama şansına sahip olanlar için, bunun nasıl çalıştığı hakkında size biraz bilgi vereyim. "RUBELLA" adlı sahte bir dil düşünün:
function foo() {
print(x); // not defined locally => uses whatever value `x` has in the calling context
y = "tetanus";
}
function bar() {
x = "measles";
foo();
print(y); // not defined locally, but set by the call to `foo()`
}
bar(); // prints "measles" followed by "tetanus"
Yani, değişkenler çağrı yığınını yukarı ve aşağı serbestçe yayar - içinde tanımlanan tüm değişkenler foo
arayan tarafından görülebilir (ve değiştirilebilir) bar
ve bunun tersi de doğrudur. Bunun kodun yeniden düzenlenebilirliği üzerinde ciddi etkileri vardır. Aşağıdaki koda sahip olduğunuzu düşünün:
function a() { // defined in file A
x = "qux";
b();
}
function b() { // defined in file B
c();
}
function c() { // defined in file C
print(x);
}
Şimdi, aramalar a()
yazdırılacak qux
. Ama sonra, bir gün, b
biraz değişmen gerektiğine karar verdin . Tüm arama bağlamlarını bilmiyorsunuz (bazıları kod tabanınızın dışında olabilir), ancak bu iyi olmalı - değişiklikleriniz tamamen içsel olacak b
, değil mi? Yani şöyle yeniden yazıyorsunuz:
function b() {
x = "oops";
c();
}
Ve yerel bir değişken tanımladığınız için hiçbir şeyi değiştirmediğinizi düşünebilirsiniz. Ama aslında, kırıldın a
! Şimdi, a
baskılar oops
yerine qux
.
Bunu sahte diller alanından geri getirmek, farklı sözdizimiyle de olsa MUMPS'un tam olarak böyle davrandığıdır.
MUMPS'un modern ("modern") sürümleri, NEW
değişkenlerin bir çağrıdan arayan kişiye sızmasını önlemenizi sağlayan deyim içerir . Yaptığımız olsaydı Yani yukarıdaki ilk örnekte, NEW y = "tetanus"
içinde foo()
, daha sonra print(y)
içinde bar()
(açıkça başka bir şeye ayarlı sürece Kabakulak içinde, tüm isimler boş bir dizeye işaret) hiçbir şey basacaktır. Ancak değişkenlerin bir arayandan bir arayana sızmasını önleyebilecek hiçbir şey yoktur: function p() { NEW x = 3; q(); print(x); }
bildiğimiz kadarıyla, açıkça bir parametre olarak almamasına rağmen , q()
mutasyon geçirebilirsek . Bu hala içinde olmak kötü bir durum, ama muhtemelen eskisi kadar kötü değil .x
x
Bu tehlikeleri göz önünde bulundurarak, MUMPS veya dinamik kapsam belirleme özelliğine sahip başka bir dilde kodu nasıl güvenle yeniden düzenleyebiliriz?
Yeniden düzenlemeyi kolaylaştırmak için, NEW
kendiniz başlattığınız ( ) dışında bir işlevde değişkenleri asla kullanmamak veya açık bir parametre olarak iletmek ve bir işlevin arayanlarından dolaylı olarak geçirilen parametreleri açıkça belgelemek gibi bazı belirgin iyi uygulamalar vardır . Ama onlarca yaşında, ~ 10 8 -LOC kod temeli, bunlar genellikle sahip olmadığı lükslerdir.
Ve elbette, temel olarak sözlük kapsamı olan dillerde yeniden düzenleme için tüm iyi uygulamalar, dinamik kapsam - yazma testleri vb. Dillerde de uygulanabilir. Öyleyse soru şu: dinamik olarak kapsamlı kodun kırılganlığının yeniden düzenlenmesi sırasında özel olarak ortaya çıkardığı riskleri nasıl azaltıyoruz?
( Dinamik bir dilde yazılan kodda nasıl gezinir ve yeniden düzenleme yapıyorsunuz? Bu soruya benzer bir başlık olsa da, bunun tamamen ilgisiz olduğunu unutmayın.)