Yapabiliyorsak yerel değişkenleri ortadan kaldırmalı mıyız?


95

Örneğin, bir işlemciyi Android'de açık tutmak için aşağıdaki gibi kod kullanabilirim:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();

ama bence yerel değişkenler powerManagerve wakeLockelimine edilebilir:

((PowerManager)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
    .acquire();

benzer sahne iOS uyarı görünümünde görünür, örneğin:

UIAlertView *alert = [[UIAlertView alloc]
    initWithTitle:@"my title"
    message:@"my message"
    delegate:nil
    cancelButtonTitle:@"ok"
    otherButtonTitles:nil];
[alert show];

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    [alertView release];
}

için:

[[[UIAlertView alloc]
    initWithTitle:@"my title"
    message:@"my message"
    delegate:nil
    cancelButtonTitle:@"ok"
    otherButtonTitles:nil] show];

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    [alertView release];
}

Kapsamda bir kez kullanılmışsa, yerel bir değişkeni ortadan kaldırmak iyi bir uygulamadır mı?


95
Şart değil. Bazen bir kerelik değişkenleri kullanmak için kodu daha açık hale getirir ve çoğu iyi programlama dilinde, bu ek değişkenler için çok az (varsa) çalışma zamanı maliyeti vardır.
Robert Harvey,

75
Ayrıca, hata ayıklayıcı w / kodu kullanarak adım atmayı daha da zorlaştırır. Ayrıca (dile bağlı olarak) ilk ifadenin NULL veya hata olmadığından da emin olmalısınız.
GrandmasterB

78
Hayır değil. Aslında, yöntem çağrılarının zincirlerini kırmak için yerel değişkenleri tanıtmak iyi bir uygulamadır . Üretilen makine kodunun aynı olması muhtemeldir ve kaynak kodun neredeyse daha okunaklı olması, dolayısıyla daha iyi olması garanti edilir.
Kilian Foth

48
Bunu dene. Şimdi hata ayıklayıcısını takın ve PowerManager veya WakeLock'ın durumunu görmeye çalışın. Hatanı anlayın. Ben de zamanımın çoğunu kod araştırmak için harcamak zorunda kalıncaya kadar aynı şeyi düşünürdüm ("tüm bu yerlilerde ne var?").
Faerindel,

42
Örneğinizde bile, "elendiğiniz" sürümünüzün kaydırma çubuğu vardır ve ekranıma tamamen sığmaz, bu da okumasını çok zorlaştırır.
Erik

Yanıtlar:


235

Kod, yazıldığından çok daha fazla okunur, bu nedenle, bundan altı ay sonra (bu siz olabilirsiniz) kodu okumak zorunda kalacak olan zavallı ruha merhamet etmeli ve en açık, anlaşılması en kolay kod için uğraşmalısınız. Benim düşünceme göre, yerel değişkenli ilk biçim çok daha anlaşılabilir. Tek satırda üç eylem yerine üç satırda üç eylem görüyorum.

Ve eğer yerel değişkenlerden kurtularak herhangi bir şeyi optimize ettiğinizi düşünüyorsanız, değilsiniz. Modern bir derleyici , yöntemi çağırmak için yerel bir değişken kullanılmış olsun olmasın powerManagerbir kayıt defterine 1 koyacaktır newWakeLock. Aynı şey için de geçerlidir wakeLock. Her iki durumda da aynı derlenmiş kodla bitirdiniz.

1 Beyanname ile yerel değişkenin kullanımı arasında çok fazla müdahale kodu varsa, bu yığın üzerinde olabilir, ancak küçük bir detaydır.


2
Çok fazla kod olup olmadığını bilemezsiniz, en iyi duruma getirici bazı işlevleri sıraya koyabilir ... Aksi takdirde, kabul edilen, ilk olarak okunabilirlik için çabalamak doğru harekettir.
Matthieu M.

2
Ben bunun tam tersi, eğer yerelde bir değişken olduğunu, her ne zaman kullanılabileceği bir nitelik olmak yerine, her fonksiyonda birçok kez başlatıldığını görürsem, nedenini araştıracağım, temelde satırları tamamen okuyacağım ve sadece bunları karşılaştıracağım. aynı olduklarından emin olun. Bu yüzden zaman harcayacağım.
Walfrat

15
@Walfrat Yerel değişkenler birden çok kez başlatılıyor mu? Ahh. Kimse yerlileri yeniden kullanmayı
önermedi

32
@Walfrat üyeleri yan etkileri doğurur ve yalnızca kamu üyelerine yapılan çağrılar arasındaki durumu korumak istediğinizde kullanılmalıdır. Bu sorunun, geçici olarak ara hesaplamaların depolanması için yerel kullanımı ile ilgilendiği görülmektedir.
Gusdor

4
S: Yapabiliyorsak yerel değişkenleri ortadan kaldırmalı mıyız? A: Hayır.
simon

94

Bazı çok eleştirilen yorumlar bunu belirtti, ancak gördüğüm cevapların hiçbiri yapmadı, ben de cevap olarak ekleyeceğim. Bu konuda karar vermedeki ana faktörün şudur:

Debuggability

Genellikle, geliştiriciler kod yazmaktan çok daha fazla zaman ve çaba harcarlar.

İle yerel değişkenler şunları yapabilirsiniz:

  • Atanan çizgide kesme noktası (koşullu kesme, vb. Gibi tüm diğer kesme noktası süslemelerinde)

  • Yerel değişkenin değerini inceleyin / izleyin / yazdırın / değiştirin

  • Dökümler nedeniyle ortaya çıkan sorunları yakalayın.

  • Okunabilir yığın izleri var (XYZ hattında 10 yerine bir işlem var)

Yerel değişkenler olmadan, yukarıdaki görevlerin tümü hata ayıklayıcınıza bağlı olarak ya çok daha zor, çok zor veya tamamen imkansızdır.

Bu şekilde, rezil makamı izleyin (kodu, kendinizden sonra korumak için bir sonraki geliştiricinin, nerede oturduğunuzu bilen çılgınca bir deliymiş gibi yazacağınız şekilde yazın) ve hata ayıklamanın daha kolay , yerel değişkenleri kullanmanın yanına bakın .


20
Tek bir hatta çok çağrı yapıldığında yığınların çok daha az faydalı olduğunu eklerdim. 50. satırda boş bir işaretçi istisnası varsa ve bu hatta 10 arama varsa, elbiseyi çok daraltmaz. Bir üretim uygulamasında, bu genellikle bir hata raporundan elde ettiğiniz bilgilerin toplu olacaktır.
JimmyJames

3
Kodda adım atmak da daha zordur. Call () -> call () -> call () -> call () varsa, üçüncü yöntem çağrısına adım atmak zordur. Dört yerel değişken varsa, çok daha kolay
gnasher729

3
@FrankPuffer - Gerçek dünyayla başa çıkmalıyız. Hata ayıklayıcıların önerdiğin şeyi yapmadığı yer.
DVK

2
@DVK: Aslında herhangi bir ifadeyi kontrol etmenize veya izlemenize izin verdiğimi düşündüğümden daha fazla hata ayıklayıcı var. MS Visual Studio (2013'ten beri) C ++ ve C # için bu özelliğe sahiptir. Eclipse, Java için var. Başka bir yorumda Faerindel, JS için IE11'den bahsetti.
Frank Puffer,

4
@DVK: Evet, birçok gerçek dünya hata ayıklayıcısı önerdiğim şeyi yapmıyor. Ancak yorumumun ilk kısmı ile ilgisi yok. Ben sadece kodumu koruyacak olan kişinin temelde bir hata ayıklayıcı ile etkileşime gireceğini varsaymayı delice buluyorum. Hata ayıklayıcılar belirli amaçlar için harikadır ancak kod analizi için ana aracı elde ederlerse, bir şeylerin ciddi şekilde yanlış olduğunu söyleyebilirim ve kodu daha fazla hata ayıklamak yerine düzeltmeye çalışırım.
Frank Puffer,

47

Sadece kodun anlaşılmasını kolaylaştırırsa. Örneklerinde, okumayı zorlaştırdığını düşünüyorum.

Derlenmiş koddaki değişkenleri ortadan kaldırmak saygın bir derleyici için önemsiz bir işlemdir. Doğrulamak için çıktıyı kendiniz inceleyebilirsiniz.


1
Değişkenlerin kullanımı kadar stil ile de ilgisi var. Soru şimdi düzenlendi.
Jodrell

29

Sorunuz "Sadece bir kez kullanıldığında yerel bir değişkeni ortadan kaldırmak iyi bir pratik midir?" yanlış kriterleri test ediyor. Bir yerel değişkenin yardımcı programı, kullanılma sayısına bağlı değildir, ancak kodu daha açık hale getirip getirmediğine bağlıdır. Ara değerlerin anlamlı adlarla etiketlenmesi, kodu kodunuzu daha küçük, daha sindirilebilir, parçalara ayırdığı için sunduğunuz gibi durumlarda netliği artırabilir.

Benim görüşüme göre, sunduğunuz değiştirilmemiş kod değiştirilmiş kodunuzdan daha açık ve bu nedenle değiştirilmemelidir. Aslında, netliği arttırmak için yerel bir değişkeni değiştirilmiş kodunuzdan çıkarmayı düşünürdüm.

Yerel değişkenlerden herhangi bir performans etkisi beklemem ve her ne kadar kodun programın kritik bir bölümünde çok dar bir döngüde olmadıkça dikkate alınmayacak kadar küçük olması muhtemeldir.


Bunun stil ve beyaz alanın herhangi bir şey olarak kullanımı ile ilgisi olduğunu düşünüyorum. Soru düzenlendi.
Jodrell

15

Olabilir.

Şahsen bir typecast katılıyorsa yerel değişkenleri ortadan kaldırmaktan çekinirim. Parantez sayısı sahip olduğum zihinsel bir limite yaklaşmaya başladığında, kompakt versiyonunuzu daha az okunabilir buluyorum. Yerel bir değişken kullanarak biraz daha ayrıntılı sürümde gerekmeyen yeni bir parantez seti bile sunar.

Kod editörü tarafından sağlanan sözdizimi vurgulaması, bu endişeleri bir dereceye kadar azaltabilir.

Gözlerime göre, bu daha iyi bir uzlaşmadır:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc").acquire();

Böylece bir yerel değişkeni tutmak ve diğerini kazmak. C # 'da ilk satırdaki var anahtar sözcüğünü kullanırdım, çünkü typecast zaten tip bilgisini veriyordu.


13

Yerel değişkenleri destekleyen cevapların geçerliliğini kabul etsem de, şeytanın avukatı oynayacağım ve karşıt bir görüş sunacağım.

Kişisel değişkenleri sadece belgeleme amaçları için hangi miktarlarda kullanılacağına dair yalnızca yerel değişkenleri kullanmaya karşıyım, bu nedenin kendisi uygulamanın bir değeri olduğunu gösterir: yerel değişkenler kodu etkin bir şekilde sahte olarak belgelemektedir.

Senin durumunda, asıl sorun değişkenlerin olmaması değil, girintilemedir. Kodu aşağıdaki gibi biçimlendirebilirsiniz (ve gerekir):

((PowerManager)getSystemService(POWER_SERVICE))
        .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag")
        .acquire();

Bunu yerel değişkenlerle olan sürümle karşılaştırın:

PowerManager powerManager=(PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"abc");
wakeLock.acquire();

Yerel değişkenlerle: isimler okuyucuya bir miktar bilgi ekler ve türler açıkça belirtilir, ancak gerçek yöntem çağrıları daha az görülür ve (bence) net olarak okunmuyor.

Yerel değişkenleri kullanmadan: daha özlüdür ve yöntem çağrıları daha belirgindir, ancak ne döndürüleceği hakkında daha fazla bilgi isteyebilirsiniz. Ancak bazı IDE'ler size bunu gösterebilir.

Üç ek yorum:

  1. Benim görüşüme göre, işlevsel kullanımı olmayan bir kod eklemek bazen okuyucunun gerçekten işlevsel bir kullanımının olmadığını ve “dokümantasyon” için orada olduğunu fark etmesi gerektiği için kafa karıştırıcı olabilir. Örneğin, bu yöntem 100 satır uzunluğunda olsaydı, tüm değişkenleri okumadığınız sürece yerel değişkenlerin (ve bu nedenle de yöntem çağrısı sonucunun) daha sonraki bir noktada gerekli olmadığı açık olmazdı.

  2. Yerel değişkenleri eklemek, türlerini belirtmeniz gerektiği anlamına gelir ve bu, kodda aksi durumda olmayacak bir bağımlılık getirir. Metotların dönüş tipi önemsizce değiştiyse (örneğin, yeniden adlandırıldıysa), kodunuzu güncellemeniz gerekirken, yerel değişkenler olmadan bunu yapmazsınız.

  3. Hata ayıklayıcınız yöntemlerden döndürülen değerleri göstermiyorsa, hata ayıklama yerel değişkenlerle daha kolay olabilir. Ancak bunun için düzeltme, hata ayıklayıcılardaki eksiklikleri gidermek, kodu değiştirmek değildir.


Diğer yorumlarınızla ilgili olarak: 1. Yerel değişkenlerin kullanıldıkları yere olabildiğince yakın olarak ilan edildiği ve yöntemlerinizi makul bir uzunlukta tuttuğunuz anlaşmasını izliyorsanız, bu bir sorun olmamalıdır. 2. Tip çıkarımı olan bir programlama dilinde değil. 3. İyi yazılmış bir kod genellikle bir hata ayıklayıcısına ihtiyaç duymaz.
Robert Harvey,

2
İlk kod örneğiniz yalnızca nesnelerinizi akıcı arabirimler veya kodumda her yerde kullanmayacağım "oluşturucu" desenleri kullanarak hazırladığınızda çalışır, ancak yalnızca seçmeli olarak çalışır.
Robert Harvey,

1
Bence, soru yerel değişkenlerin işlevsel olarak gereksiz olduğunu ve bu nedenle bu tip bir arayüzün gerekli olduğunu varsaymaktadır. Muhtemelen çeşitli engellerden geçtiyse yerlileri çıkarmayı başarabilirdik, ama basit bir olaya bakıyorduk.
rghome

1
Varyantınızı okunabilirlik için daha da kötü buluyorum. VB.net’e çok fazla maruz kalmış olabilirim, ancak örneğimi görünce ilk olarak "WITH ifadesi nereye gitti? Yanlışlıkla sildim mi?" Neler olup bittiğine iki kez bakmam gerekiyor ve birkaç ay sonra kodu tekrar gözden geçirmem gerektiğinde bu iyi değil.
Tonny

1
@Tonny, benim için daha okunaklı: yerliler bağlamdan açık olmayan bir şey eklemiyor. Java kafam açık, yani ifade yok with. Java’da normal biçimlendirme kuralları normal olurdu.
rghome

6

Burada motivasyon gerginliği var. Geçici değişkenlerin tanıtılması kodun okunmasını kolaylaştırabilir. Ancak, Ayıklama Yöntemi ve Sıcaklığı Sorgula Değiştirme gibi diğer olası yeniden alevlendirmeleri de önleyebilir ve görmeyi zorlaştırabilir . Bu sonraki yeniden yapılandırma tipleri, uygun olduğunda, genellikle geçici değişkenden çok daha büyük yararlar sağlar.

Fowler , bu yeniden yapılanmalar için motivasyon üzerine şöyle yazıyor :

“Temps ile ilgili sorun geçici ve yerel olmalarıdır. Yalnızca kullanıldıkları yöntem bağlamında görülebildiklerinden, temps daha uzun yöntemleri teşvik etme eğilimindedir, çünkü temp'a ulaşmanın tek yolu budur. temp parametresini bir sorgu yöntemiyle değiştirmek, sınıftaki herhangi bir yöntem bilgiyi alabilir. Bu, sınıf için daha temiz bir kodun gelmesinde çok yardımcı olur. "

Bu nedenle, evet, kodları daha okunaklı kılarlarsa, özellikle sizin ve ekibiniz için yerel bir norm ise temps kullanın. Ancak, bunu yapmanın bazen daha büyük alternatif gelişmeleri tespit etmeyi zorlaştırabileceğinin farkında olun. Bu kadar temps olmadan gitmenin ve ne zaman yapmanın daha rahat olabileceğini hissetme yeteneğinizi geliştirebilirseniz, bu muhtemelen iyi bir şeydir.

FWIW Ben şahsen on yıl boyunca Fowler'ın "Refactoring" kitabını okumaktan kaçındım çünkü bu kadar basit konularda söylenecek fazla bir şey olmadığını hayal ettim. Tamamen yanılmışım. Sonunda okuduğumda, günlük kodlama uygulamalarım değişti, daha iyisi için.


1
Mükemmel cevap. Yazdığım (ve diğerlerinden gördüğüm) en iyi kod, genellikle bu geçici değişkenlerin yerini alabilecek çok sayıda küçük (2, 3 satır) yöntem kullanıyordu. İlgili bu tartışmalı özel yöntemler kıyameti almak .... İyi düşündüm ve sık sık doğru buldum.
Stijn de Witt

Bu sorudaki temps zaten fonksiyonlara atıfta bulunuyor, bu yüzden bu cevap OP'lerin sorusuyla alakasız.
user949300,

@ user949300 Ben alakasız olduğunu sanmıyorum. Evet, OP'nin özel örneğindeki temps, fonksiyonlardan veya yöntemlerden elde edilen dönüş değerleridir. Ancak OP bunun sadece bir örnek senaryo olduğu çok açık. Asıl soru, daha genel bir sorudur "Yapabileceğimiz zaman geçici değişkenleri ortadan kaldırmalı mıyız?"
Jonathan Hartley

1
Tamam, satıldım ** yorumumu değiştirmeye çalıştım. Fakat çoğu zaman OP sorusunun sınırlı kapsamının ötesine geçtiğimde canım sıkılıyor. SO kararsız olabilir ... :-). Er, düzenlemeyi
yapmadan oyumu

@ user949300 Kutsal inek! Meseleleri dikkatlice değerlendirdikten sonra fikrini değiştiren bir kişi! Siz bayım, çok nadirsiniz, ve şapkamı size keserim.
Jonathan Hartley

3

Eh, yerel değişkenleri ortadan kaldırmak için iyi bir fikirdir sen eğer bu şekilde kod daha okunabilir olun. Sizin uzun bir gömlek sizin okunabilir değil, ancak daha sonra ayrıntılı bir OO stilini takip ediyor. Eğer böyle bir şeye indirgeyebilirsen

acquireWakeLock(POWER_SERVICE, PARTIAL, "abc");

o zaman muhtemelen iyi bir fikir olacağını söyleyebilirim. Belki de onu benzer bir şeye indirgemek için yardımcı yöntemler sunabilirsiniz; Bunun gibi bir kodun birden çok kez görünmesi durumunda, buna değer olabilir.


2

Burada Demeter Yasasını düşünelim . LoD hakkındaki Wikipedia makalesinde aşağıdakiler belirtilmiştir:

İşlevler için Demeter Yasası, O nesnesinin m yönteminin yalnızca aşağıdaki nesne türlerinin yöntemlerini çağırmasını gerektirebilir: [2]

  1. O
  2. m'nin parametreleri
  3. M içinde oluşturulan / örneklenen nesneler
  4. O'nun doğrudan bileşen nesneleri
  5. M kapsamında O tarafından erişilebilen global bir değişken

Bu Yasayı izlemenin sonuçlarından biri, diğer yöntemlerle döndürülen nesnelerin yöntemlerini, yukarıdaki ikinci örnekte gösterildiği gibi, uzun noktalı bir dizede çağırmaktan kaçınmanız gerektiğidir:

((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag").acquire();

Bunun ne yaptığını anlamak gerçekten zor. Bunu anlamak için her bir prosedürün ne yaptığını anlamanız ve daha sonra hangi nesnenin hangi nesne üzerinde çağrıldığını deşifre etmeniz gerekir. İlk kod bloğu

PowerManager powerManager=(PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock=powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"abc");
wakeLock.acquire();

ne yapmaya çalıştığınızı açıkça gösteriyor - bir PowerManager nesnesi alıyorsunuz, PowerManager'dan bir WakeLock nesnesi alıyorsunuz, ardından wakeLock'u alıyorsunuz. Yukarıdakiler LoD kural # 3'ü izler - bu nesneleri kodunuzda başlatırsınız ve böylece onları ihtiyacınız olan şeyi yapmak için kullanabilirsiniz.

Belki de düşünmenin başka bir yolu da, yazılımı oluştururken açıklık için yazmanız gerektiğini, kısalık için değil, hatırlamanızdır. Tüm yazılım geliştirmenin% 90'ı bakımdır. Asla bir kod yazmayın, saklamaktan memnun olmazsınız.

İyi şanslar.


3
Sıvı sözdiziminin bu cevaba nasıl uyduğunu merak ediyorum. Doğru biçimlendirme ile, akışkan sözdizimi yüksek oranda okunabilir.
Gusdor

12
Demeter Yasası'nın anlamı bu değil. Demeter Yasası nokta sayma alıştırması değildir; bu esasen “sadece yakın arkadaşlarınızla konuşun” anlamına gelir.
Robert Harvey,

5
Aynı yöntemlere ve üyelere bir ara değişken aracılığıyla erişilmesi, Demeter yasasını ihlal ettiği kadar şiddetlidir. Onu henüz gizlediniz, düzeltmediniz.
Jonathan Hartley

2
"Demeter Kanunu" açısından, her iki versiyon da eşit derecede "kötü" dür.
Hulk

@Gusdor, bu soru örneğindeki şekillendirme hakkında daha fazla yorum yaptı. Soru şimdi düzenlendi.
Jodrell

2

Unutulmaması gereken bir şey, kodun farklı "derinliklere" sık sık okunmasıdır. Bu kod:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();

"yağsız" kolaydır. 3 ifade var. İlk önce bir ile geldik PowerManager. Sonra bir ile geldik WakeLock. Sonra . Bunu her satırın başlangıcına bakarak kolayca görebiliyorum; basit değişken atamaları kısmen "TypeName = ..." olarak tanımlamak ve sadece zihinsel olarak "..." üzerine bakmak çok kolaydır. Benzer şekilde, son ifade açık bir şekilde ödevin şekli değildir, ancak yalnızca iki isim içerir, bu yüzden “ana esas” hemen anlaşılır. Genellikle, sadece "bu kod ne yapar?" Diye cevaplamaya çalışıyor olsaydım, bilmem gereken tek şey bu olurdu. yüksek düzeyde.acquirewakeLock

Burada olduğunu düşündüğüm zekice bir böceğin peşindeysem, açıkçası bunu daha ayrıntılı olarak incelemem gerekecek ve aslında "..." yi hatırlayacağım. Ancak ayrı ifade yapısı hala bir kerede bir açıklama yapmama yardımcı oluyor (özellikle her ifadede çağrılan şeylerin daha derine atlanması gerekirse işe yarar; geri döndüğümde “bir üniteyi” tamamen anladım. ve sonra bir sonraki ifadeye geçebilir).

((PowerManager)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
    .acquire();

Şimdi hepsi bir açıklama. Üst düzey yapı yağsız okunması kolay değildir; OP'nin orijinal versiyonunda, herhangi bir yapıyı görsel olarak iletmek için çizgiler ve girintiler olmadan, 3 basamaklı bir dizinin kodunu çözmek için parantezleri saymam gerekecekti. Çok parçalı ifadelerin bazıları, bir yöntem çağrısı zinciri olarak düzenlenmekten ziyade, birbirlerinin içine yerleştirilmişse, o zaman yine de buna benzer bir şekilde görünebilir, bu yüzden parantezleri saymadan güvenmeye dikkat etmek zorundayım. Ve eğer girintiye güveniyorsam ve tüm bunların varsayılan noktası olarak son şeyden önce kayıyorsam, .acquire()bana ne söyler?

Bazen de, istediğin bu olabilir. Dönüşümünüzü yarı yolda uygularsam ve şunu yazarsam:

WakeLock wakeLock =
     ((PowerManeger)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLockTage");
wakeLock.acquire();

Şimdi bu hızlı bir yağsız iletişim kurar "a WakeLock, o acquirezaman". İlk versiyondan bile daha basit. Hemen elde edilen şeyin bir olduğu açıktır WakeLock. Bunu elde etmek, PowerManagerbu kodun amacına göre oldukça önemsiz olan bir alt ayrıntı ise, ancak wakeLockönemli olan şey, o zaman gerçekten PowerManagerhızlı bir şekilde almaya çalışıyorsanız, üzerine atlamak için doğal olan şeyleri gömmek için yardımcı olabilir. bu kodun ne yaptığı hakkında fikir. Adlandırma değil , sadece bir kez kullanıldığını, bazen de bu olduğunu Önemli olan (kapsamın geri kalanı çok uzunsa, tekrar kullanılıp kullanılmayacağını söylemek için hepsini okumak zorundayım; ancak, açık alt kapsamları kullanmak, eğer diliniz destekliyorsa, bunu ele almanın başka bir yolu olabilir).

Bu, hepsinin içeriğe ve ne iletişim kurmak istediğine bağlı olduğunu gösterir. Doğal dilde nesir yazma gibi, orada her zaman bilgi içerik bakımından temelde eşdeğer olan bir kod verilmiş parça yazmak için pek çok yöntem. Genellikle gerektiğini aralarında seçim kadar doğal dilde düzyazı, yazma gibi değil gibi mekanik kurallarını uygulamak olmak "yalnızca bir kez oluştuğunda herhangi bir yerel değişken ortadan kaldırmak". Aksine nasılKodunuzu yazmayı seçerseniz, bazı şeyleri vurgulayacak ve diğerlerini de vurguluyorsunuz. Gerçekte vurgulamak istediklerinize dayanarak, bu seçimleri bilinçli bir şekilde yapmak için çaba göstermelisiniz (teknik nedenlerle daha az okunabilir kod yazma seçeneği dahil). Özellikle, sadece kodunuzun "özüne kavuşması" gereken okuyuculara neyin hizmet edeceğini bir düşünün (çeşitli seviyelerde), çünkü bu, ifadeye göre çok yakın bir ifadeden çok daha sık olur.


Bana göre, API hakkında bir bilgim olmasa da, değişkenler olmadan bile kodun ne yaptığı çok açık. getSystemService(POWER_SERVICE)güç müdürünü alır. .newWakeLockuyanık kilitlenir. .acquireonu satın aldı. Tamam, bütün türleri bilmiyorum, ama gerekirse bunu IDE'de bulabilirim.
rghome

Kodun ne yapması gerektiği size açık olabilir , ancak gerçekte ne yaptığı hakkında hiçbir fikriniz yok. Ben bir hata arıyorum varsa, tek bildiğim olmasıdır bazı kod bir yere bunu yapmak için ne gerekiyor yapmaz, ve ben hangi kod bulmak zorunda.
gnasher729

@ gnasher729 Evet. Böcek avı, tüm detayları dikkatlice okumanız gerektiğinde verdiğim bir örnekti. Ve yapması gerekeni yapmayan kodu bulmaya gerçekten yardımcı olan şeylerden biri, asıl yazarın amacının ne olduğunu kolayca görebilmektir.
Ben

geri döndüğümde “bir birimi” tamamen anladım ve bir sonraki ifadeye geçebilirim. Aslında hayır. Aslında yerel değişkenler bu anlayışı tam olarak önlemektedir. Çünkü hala devam ediyorlar ... zihinsel yer kaplıyorlar ... gelecek 20 ifadede onlara ne olacaklar ... drumroll ... Yerliler olmadan nesnelerin gittiğinden ve bir şey yapmanın imkansız olduğundan emin olacaktın sonraki satırlarda onlarla. Onları hatırlamana gerek yok. returnAynı sebepten, mümkün olduğunca hızlı bir şekilde metotlardan hoşlanıyorum .
Stijn de Witt

2

Bu bile kendi adıyla bir antipattern: Train Wreck . Değişimden kaçınmak için birkaç neden daha önce belirtilmiştir:

  • Okumak zor
  • Hata ayıklaması zor (hem değişkenleri izlemek hem de istisnalar konumlarını tespit etmek için)
  • Demeter Yasasının İhlali (LoD)

Bu yöntemin diğer nesnelerden çok fazla şey bildiğini düşünün. Metot zincirleme , kuplajı azaltmanıza yardımcı olabilecek bir alternatiftir.

Ayrıca, nesnelere yapılan referansların gerçekten ucuz olduğunu unutmayın.


Ehm, revize edilmiş kod metot zincirlemesi yapmıyor mu? EDIT bağlantılı makaleyi okudum, şimdi farkı görüyorum. Oldukça iyi yazı teşekkürler!
Stijn de Witt

Bunu incelediğiniz için teşekkür ederiz. Her neyse, yöntem zincirleme bazı durumlarda çalışabilirken değişkeni terk etmek uygun bir karar olabilir. İnsanların neden cevabınıza katılmadığını bilmek her zaman iyidir.
Borjab

Sanırım "Tren Kazası" nın tersi "Yerel Hat". İki büyük şehir arasındaki tren, birisinin girip çıkmasını isteme ihtimaline rağmen, çoğu kimsenin yapmamasına rağmen, her ülke köyünde durur.
rghome

1

Belirtilen soru "Yapabilirsek yerel değişkenleri ortadan kaldırmalı mıyız?"

Hayır, yapabildiğiniz için yok etmemelisiniz.

Mağazanızdaki kodlama kurallarına uymalısınız.

Çoğunlukla yerel değişkenler, kodu okumayı ve hata ayıklamayı kolaylaştırır.

Yaptıklarını beğendim PowerManager powerManager. Benim için sınıfın küçük bir örneği, sadece bir kez kullanım anlamına gelir.

Yapmamanız gereken, değişkenin pahalı kaynaklara dayanıp dayanmayacağıdır. Birçok dilde temizlenmesi / bırakılması gereken yerel bir değişken için sözdizimi vardır. C # kullanıyor.

using(SQLconnection conn = new SQLconnnection())
{
    using(SQLcommand cmd = SQLconnnection.CreateCommand())
    {
    }
}

Bu gerçekten yerel değişkenlerle değil, kaynak temizliği ile ilgili ... C # konusunda iyi bilgili değilim, ancak using(new SQLConnection()) { /* ... */ }yasal da olmazsa şaşırırdım (faydalı olup olmadığı farklı bir konudur :).
Stijn de Witt

1

Önemli cevaplardan biri diğer cevaplarda belirtilmemiştir: Bir değişken eklediğinizde, değişken duruma geçersiniz. Bu genellikle kötü bir şeydir çünkü kodunuzu daha karmaşık hale getirir ve bu nedenle anlamak ve test etmek daha zordur. Tabii ki, değişkenin kapsamı ne kadar küçükse, sorun o kadar az olur.

İstediğiniz şey aslında değeri değiştirilebilen bir değişken değil, geçici bir sabit. Bu nedenle, eğer diliniz izin veriyorsa, bunu kodunuzda ifade etmeyi düşünün. Java'da kullanabilirsinizfinal ve C ++ da kullanabilirsiniz const. Çoğu işlevsel dilde, varsayılan davranış budur.

Yerel değişkenlerin en az zararlı değişken durum olduğu doğrudur. Üye değişkenler çok daha fazla soruna neden olabilir ve statik değişkenler daha da kötüdür. Yine de, yapmanız gerekenleri kodunuzda mümkün olduğunca doğru ifade etmenin önemli olduğunu düşünüyorum. Ve daha sonra değiştirilebilecek bir değişken ile ara sonuç için yalnızca bir ad arasında çok büyük bir fark var. Diliniz bu farkı ifade etmenize izin veriyorsa, sadece yapın.


2
Cevabınızı küçümsemedim ama sanırım uzun süredir devam eden bir yöntemden bahsetmiyorsanız, zorunlu değişkenlerde yerel değişkenlerin genellikle 'devlet' sayılmadığı gerçeğiyle ilgili olduğunu tahmin ediyorum. Final / const'ın en iyi uygulama olarak kullanılmasına katılıyorum, ancak zincirleme bir çağrıyı kesmek için bir değişken kullanmanın değişken durumdan kaynaklanan sorunlara yol açması pek olası değil. Aslında, yerel değişkenlerin kullanımı değişken durumlarla baş etmeye yardımcı olur. Bir yöntem farklı zamanlarda farklı değerler döndürebilirse, aksi takdirde gerçekten ilginç bazı hatalara neden olabilirsiniz.
JimmyJames

@JimmyJames: Cevabımı bazı açıklamalar ekledim. Ancak yorumunuzun anlamadığım bir bölümü var: "yerel değişkenlerin kullanımı değişebilir durumla başa çıkmak için yardımcı olur". Bunu açıklar mısın?
Frank Puffer,

1
Örneğin, bir değeri kontrol etmem gerektiğini ve 10 yaşın üzerindeyse bir uyarı almam gerektiğini varsayalım. Bu değerin yöntemden geldiğini varsayalım getFoo(). Yerel bir if(getFoo() > 10) alert(getFoo());beyandan kaçınırsam , sonunda bitirdim Ama getFoo () iki farklı aramada farklı değerler döndürebilir. En iyi şekilde kafa karıştırıcı olan ve bana bir kusur olarak geri gelecek olan 10'a eşit veya daha küçük bir değere sahip bir uyarı gönderebilirim. Bu tür şeyler eşzamanlılıkla daha önemli hale gelir. Yerel atama atomiktir.
JimmyJames

Çok iyi bir nokta. Belki de bu halkı sevmememin nedeni ... Bu yöntemi çağırdıktan sonra bu örnekle bir şeyler yapacak mısın PowerManager? Yöntemin geri kalanını kontrol edeyim .... mmm tamam hayır. Ve sahip WakeLockolduğun bu şey ... bununla ne yapıyorsun (yöntemin geri kalanını yine taradım) ... tekrar mmm hiçbir şey ... tamam öyleyse neden oradalar? Oh evet, daha okunaklı olmalıydı ... ama onlar olmadan onları daha fazla kullanmadığınızdan eminim, bu yüzden yöntemin geri kalanını okumak zorunda kalmam.
Stijn de Witt

Son bir konuşmada konuşmacı, bir değişkenin nihai olduğunu göstermenin en iyi yolunun , değişkenin değişmediği açık olan kısa yöntemler yazmak olduğunu savundu . Eğer finalbir yöntem içinde yerel değişken ihtiyaç vardır, senin yöntem çok uzun.
user949300,
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.