Sadece bir değişkenin kapsamını azaltmak için bloklar oluşturmak mantıklı mı?


38

Java'da bir noktada anahtar depom için bir şifre yüklemem gereken bir program yazıyorum. Sadece eğlence için, şifremi Java'da olabildiğince kısa tutmaya çalıştım:

//Some code
....

KeyManagerFactory keyManager = KeyManagerFactory.getInstance("SunX509");
Keystore keyStore = KeyStore.getInstance("JKS");

{
    char[] password = getPassword();
    keyStore.load(new FileInputStream(keyStoreLocation), password);
    keyManager.init(keyStore, password);
}

...
//Some more code

Şimdi, bu örnekte bunun biraz aptalca olduğunu biliyorum. Yapabileceğim bir sürü başka şey var, çoğu aslında daha iyi (hiç bir değişken kullanamazdım).

Ancak, bunu yapmanın çok aptal olmadığı bir durum olup olmadığını merak ediyordum. Aklıma gelen tek şey count, ya da gibi ortak değişken isimlerini tekrar kullanmak isteyip istemediğiniz temp, ancak iyi isimlendirme kuralları ve kısa yöntemler, bunun faydalı olacağını pek mümkün kılmaz.

Sadece değişken kapsamı azaltmak için blok kullanmanın bir anlamı var mı?


13
@gnat .... ne? Dupe hedefine daha az benzemek için sorumu nasıl düzenleyeceğimi bile bilmiyorum. Bunun hangi kısmı, bu soruların aynı olduğuna inanmanıza neden oldu?
Lord Farquaad,

22
Bunun olağan cevabı, adsız bloğunuzun bunun yerine önemli bir isme sahip bir yöntem olması gerektiğidir, bu da size otomatik dokümantasyon ve istediğiniz kapsamı azaltır. Sonuçta, bir yöntemi çıkarmanın çıplak bir blok eklemekten daha iyi olmadığı bir durum düşünemiyorum.
Kilian Foth,

4
Bunu C ++ için isteyen benzer birkaç soru var: Kod blokları oluşturmak kötü mü? ve Kıvrımlı parantezli Yapı Kodu . Belki bunlardan biri C ++ ve Java bu açıdan çok farklı olsa da, bu sorunun cevabını içerir.
amon


4
@gnat Bu soru neden açık bile? Ben var en geniş şeylerden biri hiç görmüş. Kanonik bir soruya teşebbüs mü?
jpmc26

Yanıtlar:


34

İlk olarak, temel mekanikle konuşurken:

C ++ kapsam == ömür boyu b / c yıkıcılar kapsamdan çıkışta çağrılır. Ayrıca, C / C ++ 'da önemli bir ayrım yerel nesneler olarak ilan edilebilir. C / C ++ çalışma zamanında, derleyici genellikle, her kapsam için girişte daha fazla yığın alanı ayırmak yerine (değişkenleri bildiren) önceden gerekebilecek kadar büyük bir yöntem için bir yığın çerçevesi tahsis eder. Dolayısıyla, derleyici kapsamları daraltmakta veya düzleştirmektedir.

C / C ++ derleyicisi, kullanım ömrü boyunca çakışmayan yerliler için yığın depolama alanını yeniden kullanabilir (genellikle kapsamdan daha doğru olan b / c yerine, bunu belirlemek için gerçek kodun analizini kullanır!).

C / C ++ b / c Java'nın sözdiziminden, yani küme parantezlerinden ve kapsamdan bahsettiğim en azından kısmen bu aileden türemiştir. Ve ayrıca C ++ soru yorumlarıyla geldi.

Bunun aksine, Java'da yerel nesnelere sahip olmak mümkün değildir: tüm nesneler yığın nesnesidir ve tüm yereller / formaller referans değişkenler veya ilkel türlerdir (btw, aynısı statik için de geçerlidir).

Ayrıca, Java kapsamı ve ömrü tam olarak eşit değildir: kapsam dahilinde / dışarıda olmak, çoğunlukla erişilebilirlik ve isim çatışmalarına giden derleme zamanı bir kavramdır; Java'da değişkenlerin temizlenmesi ile ilgili kapsam çıkışında gerçekten hiçbir şey olmuyor. Java'nın çöp koleksiyonu, nesnelerin ömrünün (bitiş noktası) belirler.

Ayrıca Java'nın bytecode mekanizması (Java derleyicisinin çıktısı), sınırlı kapsamlar içinde bildirilen kullanıcı değişkenlerini yöntemin en üst seviyesine çıkarmaya meyillidir, çünkü bytecode düzeyinde kapsam özelliği yoktur (bu, C / C ++ işlemine benzer yığın). En iyi durumda, derleyici yerel değişken yuvalarını yeniden kullanabilir, ancak (C / C ++ 'ın aksine) yalnızca türleri aynıysa.

(Yine de, çalışma zamanındaki temel JIT derleyicisinin, aynı yığın depolama alanını, bayt kodunun yeterince analiz edilmesiyle, farklı şekilde yazılmış (ve farklı oluklu) yereller için yeniden kullanabildiğinden emin olmak için.)

Programcının avantajına göre, bir kereye mahsus olsa bile (özel) bir yöntemin daha iyi bir yapı olduğunun diğerleriyle aynı fikirdeyim.

Yine de, isimleri çözmek için kullanmakta gerçekten yanlış bir şey yok.

Bireysel yöntemler yaparken bir yük olduğunu nadir durumlarda bunu yaptım. Örneğin, switchbir döngü içinde büyük bir deyim kullanarak bir tercüman yazarken , (faktörlere bağlı olarak) case, her vakayı farklı bir yöntem yapmak yerine, her vakayı birbirinden ayrı tutmak için her biri için ayrı bir blok oluşturabilirim (her biri bu sadece bir kez çağrılır).

(Bloklardaki kod olarak, bireysel vakaların, "son;" ve "devam;" ifadelerine, kapatma döngüsüne ilişkin erişime sahip olduğunu unutmayın; oysaki yöntemler, geri dönen boole'ları ve arayan kişinin şartlarını bu kontrol akışına erişmek için kullanmasını gerektirir. ifadeleri.)


Çok ilginç bir cevap (+1)! Ancak bir C ++ kısmı için tamamlayıcı. Parola bir bloktaki bir dize ise, dize nesnesi serbest depoda bir yere değişken boyut bölümü için alan tahsis eder. Bloğu terk ederken, dize tahrip olacak ve değişken bölümün serbest bırakılmasıyla sonuçlanacak. Ancak yığında olmadığı için hiçbir şey yakında üzerine yazılacağını garanti etmez. Dize tahrip edilmeden önce karakterlerinin her birinin üzerine yazarak gizliliği daha iyi yönetin ;-)
Christophe

1
@ErikEidt "C / C ++" kelimesini gerçekten "bir şey "miş gibi konuşma problemine dikkat çekmeye çalışıyordum, ama öyle değil: " C / C ++ çalışma zamanında derleyici genellikle bir yığın çerçevesini tahsis eder İhtiyaç duyulabilecek kadar büyük olan yöntem için " ancak C'nin hiçbir yöntemi yoktur. Fonksiyonları var. Bunlar özellikle C ++ 'da farklı.
tchrist

7
" Buna karşın, Java'da yerel nesnelere sahip olmak mümkün değildir: tüm nesneler yığın nesnesidir ve tüm yereller / formaller referans değişkenler veya ilkel türlerdir (btw, aynısı statik için de geçerlidir). " Tamamen doğru değil, özellikle yöntem yerel değişkenleri için. Kaçış analizi , nesneleri yığına tahsis edebilir.
Örümcek Boris,

1
En iyi ihtimalle derleyici yerel değişken yuvaları yeniden kullanabilir, ancak (C / C ++ aksine) yalnızca türleri aynıysa. “Sadece yanlış. Bayt kodu düzeyinde, yerel değişkenler atanabilir ve istediğiniz şekilde yeniden atanabilir, tek kısıtlama sonraki kullanımın en son atanan öğenin türüyle uyumlu olmasıdır. Yerel değişken yuvalarını tekrar kullanmak , örneğin { int x = 42; String s="blah"; } { long y = 0; }, longdeğişkenle birlikte , her iki değişkenin de yuvalarını tekrar kullanır xve stüm kullanılan derleyicilerle ( javacve ecj) kullanılır.
Holger

1
@ Örümcek Borisi: Bu, olup bitenlerle eşleşmeyen, sıklıkla tekrarlanan bir konuşma ifadesidir. Kaçış Analizi, nesnenin alanlarının değişkenlere ayrışan Skalarizasyonu etkinleştirebilir ve daha sonra diğer optimizasyonlara tabi tutulabilir. Bunlardan bazıları kullanılmayan olarak elimine edilebilir, diğerleri onları başlatmak için kullanılan kaynak değişkenlerle katlanabilir, diğerleri CPU kayıtlarına eşlenebilir. Sonuç, insanların “yığında tahsis edilmiş” derken hayal edebildikleri ile nadiren eşleşiyor.
Holger

27

Bence bloğu kendi yöntemine çekmek daha açık olacaktır. Bu bloğu bıraktıysanız, bloğu neden ilk sıraya yerleştirdiğinizi açıklayan bir yorum görmeyi umuyorum. Bu noktada, yalnızca initializeKeyManager()parola değişkenini yöntemin kapsamı ile sınırlı tutan ve kod bloğu ile amacınızı gösteren yöntem çağrısı yapmak daha temiz hissettirir .


2
Sanırım cevabınız kilit bir usecase tarafından desteklenir, bu bir refaktör sırasında ara bir adımdır. Kapsamı sınırlandırmak ve bir yöntemi ayıklamadan hemen önce kodunuzun hala çalıştığını bilmek faydalı olabilir.
RubberDuck

16
@RubberDuck doğru, ancak bu durumda geri kalanımız onu asla görmemelidir, bu yüzden ne düşündüğümüzün önemi yoktur. Bir yetişkin kodlayıcının ve onaylayan bir derleyicinin kendi kabinlerinin mahremiyetinde ne elde edeceği, başka kimsenin endişesi değildir.
candied_orange

@candied_orange Anlamadım diye korkuyorum :( Ayrıntılara dikkat eder misiniz?
doubleOrt

@doubleOrt Ara yeniden yapılanma adımlarının gerçek ve gerekli olduğunu, ancak herkesin bakabileceği kaynak kontrolünde kesinlikle korunmasına gerek olmadığını kastediyorum. Sadece check-in
işleminden

@candied_orange Ah, tartıştığını ve RubberDuck'ın argümanını genişletmediğini sanıyordum.
doubleOrt

17

Sıkı ödünç alma kuralları ile Rust'ta faydalı olabilirler. Ve genellikle, işlevsel dillerde, bu bloğun bir değer döndürdüğü. Ama Java gibi dillerde? Fikir zarif görünse de, pratikte nadiren kullanılır, bu yüzden onu görmekten kaynaklanan karışıklık değişkenlerin kapsamını sınırlandırmanın potansiyel netliğini caydıracaktır.

Bunu yararlı bulduğum yerde bir durum var - bir switchaçıklamada! Bazen bir değişkeni aşağıdaki gibi bildirmek istersiniz case:

switch (op) {
    case ADD:
        int result = a + b;
        System.out.printf("%s + %s = %s\n", a, b, result);
        break;
    case SUB:
        int result = a - b;
        System.out.printf("%s - %s = %s\n", a, b, result);
        break;
}

Ancak bu başarısız olacaktır:

error: variable result is already defined in method main(String[])
            int result = a - b;

switch ifadeler tuhaf - bunlar kontrol ifadeleridir, ancak ortaya çıktıkları için kapsam tanımıyorlar.

Yani - sadece kapsamları oluşturmak için blokları kullanabilirsiniz:

switch (op) {
    case ADD: {
        int result = a + b;
        System.out.printf("%s + %s = %s\n", a, b, result);
    } break;
    case SUB: {
        int result = a - b;
        System.out.printf("%s - %s = %s\n", a, b, result);
    } break;
}

6
  • Genel dava:

Sadece değişken kapsamı azaltmak için blok kullanmanın bir anlamı var mı?

Yöntemleri kısa tutmak için genellikle iyi bir uygulama olarak kabul edilir. Bazı değişkenlerin kapsamını azaltmak, yöntemlerin yeterince uzun olduğuna dair bir işaret olabilir, bu nedenle değişkenlerin kapsamının azaltılması gerektiğini düşünebilirsiniz. Bu durumda, muhtemelen kodun bu bölümü için ayrı bir yöntem oluşturmaya değer.

Sorunlu bulacağım durumlar, kodun bu bölümünün bir avuç argümandan daha fazlasını kullanmasıdır. Her birinin çok fazla parametre harcadığı (ya da birden fazla değerin geri dönüşünü simüle etmek için geçici çözümü gereken) küçük yöntemlerle son bulabileceğiniz durumlar vardır. Bu özel sorunun çözümü, kullandığınız çeşitli değişkenleri elinde tutan ve uygulayan tüm adımları nispeten kısa yöntemlerinde uygulayan başka bir sınıf oluşturmaktır: Bu, bir Oluşturucu deseni kullanmak için tipik bir kullanım durumudur .

Bununla birlikte, tüm bu kodlama kuralları bazen gevşek bir şekilde uygulanabilir. Bazen, biraz daha uzun bir yöntemde tutarsanız, küçük alt yöntemlere (veya oluşturucu düzenlerine) bölmek yerine, kodun daha okunaklı olabileceği garip durumlar vardır. Bu, genellikle orta büyüklükte, oldukça doğrusal olan ve çok fazla bölünmenin gerçekte okunabilirliği engellediği yerlerde (özellikle kodun ne yaptığını anlamak için çok fazla yöntem arasında atlamanız gerekiyorsa) ortaya çıkar.

Mantıklı gelebilir ama çok nadir.

  • Kullanım durumunuz:

İşte kodunuz:

KeyManagerFactory keyManager = KeyManagerFactory.getInstance("SunX509");
Keystore keyStore = KeyStore.getInstance("JKS");

{
    char[] password = getPassword();
    keyStore.load(new FileInputStream(keyStoreLocation), password);
    keyManager.init(keyStore, password);
}

Bir tane yaratıyorsun FileInputStreamama asla kapatmıyorsun.

Bunu çözmenin bir yolu, kaynakları ile deneme ifadesi kullanmaktır . Bu kapsamdadır InputStreamve isterseniz bu bloğu diğer değişkenlerin kapsamını azaltmak için de kullanabilirsiniz (bu satırlar birbiriyle ilişkili olduğu için nedenle)

KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
Keystore keyStore = KeyStore.getInstance("JKS");

try (InputStream fis = new FileInputStream(keyStoreLocation)) {
    char[] password = getPassword();
    keyStore.load(fis, password);
    keyManager.init(keyStore, password);
}

( Bu arada, getDefaultAlgorithm()bunun yerine kullanmak çoğu zaman daha iyidir SunX509.)

Ek olarak, kod parçalarını ayrı yöntemlere ayırma tavsiyesi genellikle sağlamdır. Yalnızca 3 satır için nadiren buna değer (eğer bir şey varsa, ayrı bir yöntem oluşturmanın okunabilirliği engellediği bir durum).


"Bazı değişkenler kapsamını azaltmak için yöntem oldukça uzun bir işareti olabilir" - Bu edebilir bir işaret olabilir ama aynı zamanda can ve IMHO gerektiğini amacıyla kullanılacak belgeye yerel değişkenin değeri ne kadar süreyle kullanıldığı. Aslında, iç içe kapsamları desteklemeyen diller için (örneğin Python) Karşılık gelen bir kod yorumunun bir değişkenin "yaşamın sonu" olduğunu belirtirseniz memnun olurum. Aynı değişkenin daha sonra tekrar kullanılması durumunda, daha önce başka bir yerde (ancak "yaşamın sonu" yorumundan sonra) yeni bir değerle başlatılması gerekip gerekmediğini anlamak kolay olacaktır.
Jonny Dee

2

Alçakgönüllü görüşüme göre, genel olarak üretim kodu için büyük ölçüde kaçınmak bir şeydir, çünkü farklı görevleri yerine getiren sporadik işlevler dışında, genellikle bunu yapmak için cazip olmuyorsunuz. Bir şeyleri test etmek için kullanılan bazı hurda kodlarında yapmaya meyilliyim, ancak üretim kodunda her işlevin ne yapması gerektiğine dair önceden düşündüğüm üretim kodunda bir cazibe bulmuyorum çünkü o zaman işlevin doğal olarak çok yerel durumuna göre sınırlı kapsam.

tryKapsamı neden azaltamayacağı sorusunu yalın bir şekilde anlamlı bir şekilde azaltmak için bu şekilde kullanılmakta olan (koşulsuzlar, bir işlem için bir blok, vb.) Kullanılan adsız blok örnekleri hiç görmedim eğer gerçekten anonim bloklardan orijinal bir SE açısından gerçekten faydalanmışsa, daha az kapsamlı daha basit fonksiyonlara bölünebilir. Genelde eklektik kod, bunun için en çok istediğimiz yerde gevşek bir şekilde ilgili veya çok ilgisiz şeyler yapıyor.

Örnek olarak, bunu bir değişkeni yeniden kullanmak için yapmaya çalışıyorsanız count, iki farklı şeyi saydığınızı gösterir. Eğer değişken ismi en kısa olacaksa count, onu sadece fonksiyonun bağlamına bağlamak mantıklı olur, bu sadece potansiyel olarak bir şeyi sayıyor olabilir. Ardından, fonksiyonun adına ve / veya dokümantasyonuna anında bakabilir, counttüm kodu analiz etmeden fonksiyonun ne yaptığı bağlamında ne anlama geldiğini anında görebilirsiniz . Bir fonksiyon için, aynı değişken adını yeniden kullanan iki farklı şeyi, adsız kapsamları / blokları alternatiflere göre daha çekici hale getiren şekillerde saymak için genellikle iyi bir argüman bulamıyorum. Bu, tüm işlevlerin yalnızca bir şeyi sayması gerektiğini göstermez. BEN'mühendislik, iki veya daha fazla şeyi saymak için aynı değişken adını yeniden kullanan ve her bir sayının kapsamını sınırlamak için adsız bloklar kullanan bir fonksiyona yarar sağlar. İşlev basit ve açıksa, birincisi ideal olarak gerekenden daha fazla birkaç kapsam alanı görünürlük çizgisine sahip olan iki farklı adlandırılmış sayı değişkenine sahip olmak dünyanın sonu değildir. Bu tür işlevler genellikle, yerel değişkenlerinin asgari kapsamını daha da azaltmak için bu tür adsız blokların bulunmadığı hataların kaynağı değildir.

Gereksiz Yöntemler İçin Bir Öneri Değil

Bu, sadece kapsamı azaltmak için zorla yöntemler oluşturmanızı önermez. Muhtemelen bu kadar kötü ya da daha kötü bir şey ve benim önerdiğim şey, isimsiz kapsamlara olan bir ihtiyaçtan daha garip, özel "yardımcı" yöntemlerine ihtiyaç duymaması gerektiği yönünde. Bu, şimdi olduğu gibi kod hakkında çok fazla düşünmek ve değişkenlerin kapsamını azaltmak için sorunu arabirim düzeyinde kavramsal olarak nasıl çözeceğinizi düşünmekten ziyade, yerel fonksiyon durumlarının doğal olarak blokların derin bir şekilde iç içe yerleştirilmeden temiz ve kısa görünürlüğünü sağlayacak şekillerde düşünmektir. ve 6+ girinti seviyeleri. Bruno'ya, kod satırlarını bir işleve zorla 3 satır ekleyerek engelleyebileceğinizi kabul ediyorum, ancak bu, mevcut uygulamanıza göre oluşturduğunuz işlevleri geliştirdiğiniz varsayımıyla başlar, uygulamalara karışmadan fonksiyonları tasarlamak yerine. İkinci yolu yaparsanız, bir değişkenin kapsamını sadece birkaç daha az zararsız kod satırına düşürmek için gayretli bir şekilde denemeyi denemeden belli bir yöntemde değişken kapsamı azaltmanın ötesinde bir amaca hizmet etmeyen anonim bloklara çok az ihtiyaç duydum bu anonim blokların egzotik tanıtımı tartışmasız çıkardıkları kadar entelektüel ek yüke katkıda bulunuyor.

Asgari Kapsamları Daha da Azaltmaya Çalışmak

Yerel değişken kapsamlarını mutlak minimuma indirgemek faydalı olsaydı, bunun gibi geniş bir kod kabulü olmalıdır:

ImageIO.write(new Robot("borg").createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())), "png", new File(Db.getUserId(User.handle()).toString()));

... bu durum, ilk etapta bunlara atıfta bulunmak için değişkenler yaratarak bile devletin asgari görünürlüğüne neden olmaktadır. Dogmatik olarak gelmek istemiyorum ama aslında pragmatik çözümün, yukarıdaki kodlu kod satırından kaçınmak için olduğu gibi mümkün olduğunda isimsiz blokları önlemek ve doğruluk ve değişmezleri bir işlev içinde sürdürme perspektifinden sonra, kodunuzu işlevler halinde nasıl düzenlediğinizi ve arabirimlerinizi tasarlamanın kesinlikle yeniden incelenmeye değer olduğunu düşünüyorum. Doğal olarak, yönteminiz 400 satır uzunluğundaysa ve bir değişkenin kapsamı gereğinden fazla 300 satır kod tarafından görülebilirse, bu gerçek bir mühendislik sorunu olabilir, ancak bu adsız bloklarla çözülmesi gereken bir sorun değildir.

Başka bir şey yoksa, her yerde anonim bloklar kullanmak, aptalca değil, aptalca değildir ve egzotik kod, kendiniz olmasa da, yıllar sonra başkaları tarafından nefret edilme riskini taşır.

Kapsam Azaltmanın Pratik Yararı

Değişkenlerin kapsamını azaltmanın nihai yararı, devlet yönetimini doğru almanıza ve doğru tutmanıza izin vermek ve bir kod tabanının herhangi bir kısmının - kavramsal değişmezleri koruyabilmeniz için ne olduğu hakkında kolayca akıl vermenize izin vermektir. Tek bir işlevin yerel durum yönetimi o kadar karmaşıksa, sonlandırılmış ve iyi olması amaçlanmayan koddaki anonim bir bloğu kullanarak kapsamı zorla azaltmak zorunda kalırsanız, o zaman yine, işlevin kendisinin yeniden incelenmesi gerektiğinin bir işareti . Yerel bir işlev kapsamındaki değişkenlerin durum yönetimi hakkında akıl yürütme zorluğunuz varsa, tüm sınıfın her yöntemine erişilebilen özel değişkenler hakkında akıl yürütmenin zorluğunu hayal edin. Görünürlüklerini azaltmak için adsız blok kullanamayız. Benim için değişmezlerin bakımını yapmakta zorluk çekeceğiniz bir noktaya gelmemek koşuluyla, değişkenlerin ideal olarak pek çok dilde olması gerekenden biraz daha geniş bir kapsama alanına sahip olma eğiliminin kabul edilmesi ile başlamaya yardımcı olur. Pragmatik bir bakış açısıyla kabul ettiğim gibi, isimsiz bloklarla çözülecek bir şey değil.


Son bir uyarı olarak, daha önce de bahsettiğim gibi, zaman zaman isimsiz blokları sık sık hurda kodu için ana giriş noktası yöntemlerinde kullanıyorum. Başka biri yeniden düzenleme aracı olarak bahsetti ve bence sonuç iyi, bence sonuç arabuluculuk yapıyor ve kodun düzeltilmemesi için daha fazla düzeltilmesi gerekiyor. Yararlarını tamamen iskonto etmiyorum, ancak yaygın olarak kabul edilen, iyi test edilmiş ve doğru kod yazmayı deniyorsanız, isimsiz bloklara olan ihtiyacı çok az görüyorum. Bunları kullanma konusunda takıntılı olmak, odağı doğal olarak küçük bloklarla daha net fonksiyonlar tasarlamaktan uzaklaştırabilir.

2

Sadece değişken kapsamı azaltmak için blok kullanmanın bir anlamı var mı?

Bence motivasyon bir blok oluşturmak için yeterli neden, evet.

Casey'nin belirttiği gibi, blok bir işleve blok çıkarmanın daha iyi olabileceğini gösteren bir "kod kokusu" dur. Ama sen olmayabilirsin.

John Carmark , 2007'de satır içi kod hakkında bir not yazdı .

  • Bir işlev yalnızca tek bir yerden çağrılıyorsa, onu satır içine almayı düşünün.
  • Birden fazla yerden bir işlev çağrılırsa, işin tek bir yerde, belki bayraklarla ve bununla aynı çizgide yapılması için düzenlemenin mümkün olup olmadığına bakın.
  • Bir işlevin birden fazla sürümü varsa, daha büyük olasılıkla varsayılan olan parametrelerle tek bir işlev yapmayı düşünün.
  • Eğer iş tamamen işlevsel bir yere yakınsa, küresel duruma çok az atıfta bulunarak, onu tamamen işlevsel hale getirmeye çalışın.

Yani düşünüyorum , bir amaç ile seçim ve yaptığınız seçimi için motivasyonunuzu açıklayan (opsiyonel) terk kanıtları olun.


1

Benim fikrim tartışmalı olabilir, ama evet, kesinlikle bu tarz bir tarz kullanabileceğim durumlar olduğunu düşünüyorum. Ancak, "sadece değişkenin kapsamını azaltmak" geçerli bir argüman değildir, çünkü zaten bunu yapıyorsunuz. Ve sadece yapmak için bir şeyler yapmak geçerli bir sebep değildir. Ayrıca, ekibiniz bu tür bir sözdiziminin geleneksel olup olmadığını çözmüşse, bu açıklamanın bir anlamı olmadığını unutmayın.

Öncelikle bir C # programcısıyım, ancak Java’da, parolanın char[]bellekte kalacağı süreyi azaltmanıza izin verecek şekilde bir parola döndürdüğünü duydum . Bu örnekte, işe yaramaz çünkü çöp toplayıcının kullanılmadığı andan itibaren diziyi toplamasına izin verilir, bu nedenle parola kapsamdan çıkmazsa önemli değildir. Yaptıktan sonra diziyi temizlemenin uygun olup olmadığını tartışmıyorum, ancak bu durumda, eğer yapmak istiyorsanız, değişkeni kapsamlamak mantıklı:

{
    char[] password = getPassword();
    try{
        keyStore.load(new FileInputStream(keyStoreLocation), password);
        keyManager.init(keyStore, password);
    }finally{
        Arrays.fill(password, '\0');
    }
}

Bu, kaynakları denemek ifadesine çok benziyor , çünkü kaynağı kapsamalı ve siz yaptıktan sonra üzerinde bir sonlandırma gerçekleştiriyor. Yine, lütfen şifreleri bu şekilde ele almayı tartışmadığımı, sadece yapmaya karar verirseniz, bu tarzın makul olduğunu unutmayın.

Bunun nedeni, değişkenin artık geçerli olmamasıdır. Siz yarattınız, kullandınız ve anlamlı bir bilgi içermemesi için durumunu geçersiz hale getirdiniz. Bu bloktan sonra değişkeni kullanmak hiç mantıklı değildir, bu nedenle onu kapsamlamak mantıklıdır.

Aklıma gelen başka bir örnek, aynı isim ve anlama sahip iki değişkeniniz olduğunda, ancak biriyle, sonra biriyle çalışırsınız ve onları ayrı tutmak istersiniz. Bu kodu C # dilinde yazdım:

{
    MethodBuilder m_ToString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, typeofString, Type.EmptyTypes);
    var il = m_ToString.GetILGenerator();
    il.Emit(OpCodes.Ldstr, templateType.ToString()+":"+staticType.ToString());
    il.Emit(OpCodes.Ret);
    tb.DefineMethodOverride(m_ToString, m_Object_ToString);
}
{
    PropertyBuilder p_Class = tb.DefineProperty("Class", PropertyAttributes.None, typeofType, Type.EmptyTypes);
    MethodBuilder m_get_Class = tb.DefineMethod("get_Class", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, typeofType, Type.EmptyTypes);
    var il = m_get_Class.GetILGenerator();
    il.Emit(OpCodes.Ldtoken, staticType);
    il.Emit(OpCodes.Call, m_Type_GetTypeFromHandle);
    il.Emit(OpCodes.Ret);
    p_Class.SetGetMethod(m_get_Class);
    tb.DefineMethodOverride(m_get_Class, m_IPattern_get_Class);
}

Bu ILGenerator il;yöntemin en üstünde sadece beyan edebileceğimi iddia edebilirsin , fakat aynı zamanda değişkenleri farklı nesneler için tekrar kullanmak istemiyorum (çok fonksiyonel bir yaklaşım). Bu durumda, bloklar, gerçekleştirilen işlerin sözdizimsel ve görsel olarak ayrılmasını kolaylaştırır. Ayrıca, bloktan sonra işim bittiğimi ilve hiçbir şeyin erişmemesi gerektiğini söylüyor .

Bu örneğe karşı bir argüman yöntemleri kullanıyor. Belki evet, ancak bu durumda, kod o kadar uzun değildir ve onu farklı yöntemlere ayırmanın da kodda kullanılan tüm değişkenleri geçmesi gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.