Bu antipattern için isim? Yerel değişkenler olarak alanlar [kapalı]


68

Gözden geçirdiğim bazı kodlarda, aşağıdakilerin ahlaki karşılığı olan şeyler görüyorum:

public class Foo
{
    private Bar bar;

    public MethodA()
    {
        bar = new Bar();
        bar.A();
        bar = null;
    }

    public MethodB()
    {
        bar = new Bar();
        bar.B();
        bar = null;
    }
}

Alan barburada mantıksal değeri yöntem çağrıları arasında varlığını hiç düşünmemiş gibi, yerel bir değişken. Ancak, çoğu yöntemin Footüründe bir nesneye ihtiyaç duyması nedeniyle Bar, orijinal kod yazarı az önce bir tür alanı oluşturmuştur Bar.

  1. Bu tabii ki kötü, değil mi?
  2. Bu antipattern için bir isim var mı?

60
Bu yeni bir tane. Umarım bu sınıf çok iş parçacıklı bir bağlamda kullanılmaz, aksi halde ileride ilginç zamanlarınız olacak!
TMN

8
Bu gerçekten nadir mi? Bunu kariyerimde birçok kez gördüm.
JSB ձոգչ

32
@TMN İş parçacığı güvenli değil, ama daha kötüsü, hatta nezaketsiz değildir. Herhangi bir kod MethodAveya MethodBneden MethodAveya MethodBherhangi bir şekilde çağrılacaksa (ve bartekrar kullanıldığında bar.{A,B}(), suçlu olması durumunda ), herhangi bir eşzamanlılık olmadan bile benzer sorunlarınız var.

73
Birinin yapabileceği her aptalca şeyin adı olmalı mı? Sadece ona Kötü Bir Fikir de.
Caleb

74
Sarkmak zor değil, sarkan anti-desen özelleştirir.
psr,

Yanıtlar:


86

Bu tabii ki kötü, değil mi?

Evet.

  • Merak etmeyen yöntemleri yapar, ki bunlar aynı örnek üzerinde yinelemeli olarak veya çok iş parçacıklı bir bağlamda çağrılırsa sorun olur.

  • Bu, bir çağrının durumunun başka bir aramaya sızması anlamına gelir (yeniden başlatmayı unutursanız).

  • Kodun anlaşılmasını zorlaştırır, çünkü kodun gerçekte ne yaptığından emin olmak için yukarıdakileri kontrol etmeniz gerekir. (Yerel değişkenlerin kullanılmasıyla kontrast.)

  • Her Fooörneği olması gerekenden daha büyük yapar . (Ve bunu N değişkenleri için yapmayı hayal edin ...)

Bu antipattern için bir isim var mı?

IMO, buna antipattern denmeyi hak etmiyor. Bu sadece kötü bir kodlama alışkanlığı / Java yapılarının / crap kodunun kötüye kullanılmasıdır. Öğrenci ders atlarken ve / veya programlama yeterliliği olmadığında lisans kodunda görebileceğiniz bir şeydir. Üretim kodunda görüyorsanız, çok daha fazla kod incelemesi yapmanız gerektiğinin bir işaretidir ...


Kayıt için, bunu yazmanın doğru yolu:

public class Foo
{
    public methodA()
    {
        Bar bar = new Bar();  // Use a >>local<< variable!!
        bar.a();
    }

    // Or more concisely (in this case) ...
    public methodB()
    {
        new Bar().b();
    }
}

Java tanımlayıcıları için kabul edilen stil kurallarına uyması için yöntemi ve değişken adlarını da düzelttiğime dikkat edin.


11
"Üretim kodunda görürseniz , işe alım sürecinizi yeniden gözden geçirmeniz gerektiğinin bir işaretidir "
Beta

@ Beta - Bu, kötü kod kodlama alışkanlıklarını bu tür kodlama alışkanlıklarını düzelterek düzeltmeniz gerekir.
Stephen C

Bit kod hakkında daha fazla kod incelemesi için +1. İnsanların düşündüklerine rağmen, işe alım uygulamalarını geliştirmek bu tür bir sorunu engellemeyecektir - işe alım bir saçmalıktır, yapabileceğiniz en iyi şey zarları lehinize yüklemek.
mattnz

@StephenC "Tekrarlayan olmayan veya çok iş parçacıklı bir bağlamda aynı örnekte çağrılırsa sorun olan metotları önemsiz kılar." . Reentrancy'nin ne olduğunu biliyorum, ancak yöntemler hiç kilit kullanmadığından, burada bir nokta göremiyorum. Açıklayabilir misiniz lütfen .
Geek

@Geek - Belirli bir örneğe çok fazla odaklanıyorsunuz. Yöntemin birden fazla iş parçacığından ya da özyinelemeli olarak çağrılabileceği genel durumdan bahsediyorum .
Stephen C

39

Değişken için gereksiz geniş kapsam derim. Bu ayar ayrıca, birden fazla iş parçacığı MethodA ve MethodB'ye erişiyorsa yarış koşullarına izin verir.


12
Özellikle, "değişken kapsamı" konunun burada adı olduğunu düşünüyorum. Bu kişinin yerel değişkenlerin ne olduğunu ve bunları nasıl / ne zaman kullanacağını öğrenmesi gerekir. Olumlu örnek veya genel kural, her değişken için mevcut olan en küçük kapsamı kullanmak ve yalnızca gerektiği kadar genişletmektir. Açık olmak gerekirse, bu hata sadece kötü bir tarz değil. Böyle bir yarış koşulunu kodlamak bir hatadır.
GlenPeterson,

30

Bu, olarak bilinen genel bir model için belirli bir durumdur global doorknobbing. Bir ev inşa ederken, sadece bir kapı tokmağı satın almak ve etrafta yatarak bırakmak caziptir. Birisi bir kapı veya dolap kullanmak istediğinde, sadece bir küresel kapı tokmağını yakalarlar. Kapı kolları pahalı ise, iyi bir tasarım olabilir.

Ne yazık ki, arkadaşınız geldiğinde ve kapı tokmağı aynı anda iki farklı yerde kullanıldığında, gerçeklik paramparça olur. Kapı kolu, yalnızca birini karşılayabileceğiniz kadar pahalıysa, insanların kapı kolu için sırasını beklemelerini güvenli bir şekilde sağlayan bir sistem kurmak buna değer.

Bu durumda kapı tokmağı sadece referans, bu yüzden ucuz. Kapı kolu gerçek bir nesneyse (ve yalnızca referans yerine nesneyi yeniden kullanıyorlarsa), o zaman yeterince pahalı olabilirdi prudent global doorknob. Ancak, ucuz olduğunda, bir olarak bilinir cheapskate global doorknob.

Örneğin cheapskateçeşitliliği var.


19

Buradaki öncelikli kaygı eşzamanlılık olacaktır - Foo birden fazla iş parçacığı tarafından kullanılıyorsa, bir sorun yaşarsınız.

Bunun ötesinde, sadece saçma - yerel değişkenler kendi yaşam döngülerini mükemmel şekilde yönetiyorlar. Onları, artık kullanışlı olmadıklarında geçersiz kılmaları gereken örnek değişkenlerle değiştirmek, hataya karşı bir davettir.


15

"Değişken yeniden kullanım" tarafı olan özel bir "uygunsuz kapsam belirleme" durumu.


7

Bu bir anti-patern değil. Anti-paternler, insanları bilerek yapmaya iten iyi bir fikir gibi görünmesini sağlayan bazı özelliklere sahiptir; desen olarak planlanmışlar ve sonra çok yanlış gidiyor.

Aynı zamanda, bir şeyin bir kalıp mı, anti-kalıp mı, yoksa bazı yerlerde hala kullanımda olan yaygın olarak uygulanan bir kalıp mı olduğu tartışmaları için de geçerlidir.

Bu sadece yanlış.

Biraz daha eklemek için.

Bu kod batıl inançlıdır veya en iyi durumda kargo kültü uygulamasıdır.

Bir batıl inanç, açık bir gerekçe göstermeden yapılan bir şeydir. Gerçek bir şeyle ilişkilendirilebilir, ancak bağlantı mantıklı değildir.

Bir kargo-kült uygulaması, daha bilgili bir kaynaktan öğrendiğiniz bir şeyi kopyalamaya çalıştığınız bir yöntemdir, ancak aslında süreçten ziyade yüzey eserlerini kopyalarsınız (Papua Yeni Gine’de bir kült için adlandırılır) 2. Dünya Savaşı Japon ve Amerikan uçaklarının geri gelmesini umarak bambudan çıkan uçak kontrol telsizleri).

Her iki durumda da, yapılacak hiçbir gerçek durum yok.

Bir anti-kalıp, ister küçük isterse (ele alınması gereken ekstra dava ile başa çıkmak için ekstra dallanma, spagetti koduna yol açan bu fazla dallanma) ya da kasıtlı olarak çok fazla bir kalıp uyguladığınız yerde ya itibarsızlaştırılmış ya da tartışılmış (birçoğu, yalnızca salt okunur olmayanlar hariç - örneğin günlüğe kaydetme nesneleri veya salt okunur örneğin, yapılandırma ayarları nesneleri - ve bazılarını bile kınıyorlardı) tek tekleri açıklar; yanlış bir sorun (.NET ilk ortaya çıktığında, MS hem yönetilmeyen hem de tek kullanımlık yönetilen alanlarınız olduğunda elden çıkarmayla başa çıkmak için bir kalıp önerdi - aslında bu durumla çok iyi bir şekilde başa çıktı, ama asıl sorun şu ki elinizde. aynı sınıftaki her iki alan türü).

Bu nedenle, bir anti-patern, dili, problem alanını ve mevcut kütüphaneleri iyi bilen bir akıllı insanın kasıtlı bir şekilde yapacağı, hala baştan aşağı bir dezavantajı olan (ya da olduğu iddia edilen) bir şeydir.

Hiçbirimiz belirli bir dili, problem alanını ve mevcut kitaplıkları iyi tanımaya başladığımızdan beri ve herkes makul bir çözümden diğerine giderken bir şeyi özleyebileceğinden (örneğin, bir alanda iyi bir kullanım için bir şeyi depolamaya başlayın ve sonra deneyin) işini bitirmek, ancak işi tamamlamak değil, ve sorudaki gibi bir kodla biteceksin), ve hepimiz öğrenmede zaman zaman bir şeyleri özlediğimiz için, hepimiz bir yerde batıl inançlı veya kargo kült kodu oluşturduk . İşin iyi yanı, aslında anti-kalıplardan daha iyi tanımlamaları ve düzeltmeleri. Gerçek anti-paternler ya tartışmasız anti-paternler değil ya da çekici bir kaliteye sahipler ya da en azından kötü olarak tanımlansalar bile bir tanesini cezalandırma yöntemine sahipler (çok fazla ve çok az tabaka hem tartışmasız hem de kötü diğerine yol açar).


1
Ama insanlar yok onlar kod yeniden kullanım şeklidir olduğunu düşünüyorum, muhtemelen bunun iyi bir fikir olduğunu düşünüyorum.
JSB ձոգչ

Yeni başlayanlar genellikle iki değişkeni tanımlamanın bir şekilde iki kez boşluk gerektirdiğini düşünüyor ve bu nedenle değişkenleri yeniden kullanmayı tercih ediyor gibi görünüyor. Bu, bellek modelinin yanlış anlaşıldığını (ücretsiz mağaza vs. yığın, yığın konumlarının tekrar kullanılması olasılığı) ve tüm derleyicilerin gerçekleştirebileceği optimizasyonları gösterir. Yeni başlayanların bu nedenle değişkeni tekrar kullanmanın iyi bir fikir olduğunu düşünebilirler, bu yüzden bir antipattern olarak sınıflandırılabilir.
Philipp

Bu bir batıl inançtır, antipattern değildir.
Jon Hanna

3

(1) İyi olmadığını söyleyebilirim.

Yığının yerel değişkenlerle otomatik olarak yapabileceği şekilde el ile ev yapılmasıdır.

Her yöntem çağrısı için "yeni" olarak adlandırıldığından performans avantajı yoktur.

EDIT: Sınıfın hafıza alanı daha büyüktür çünkü çubuk imleci her zaman sınıfın kullanım ömrü boyunca hafızayı tutar. Çubuk işaretçisi yerel olsaydı, yalnızca yöntem çağrısının ömrü boyunca belleği kullanırdı. İşaretçinin hafızası okyanusta sadece bir damladır, fakat yine de gereksiz bir damladır.

Çubuk, sınıftaki diğer yöntemlerle görülebilir. Çubuğu kullanmayan yöntemler onu görmemelidir.

Durum tabanlı hatalar. Bu özel durumda, durum temelindeki hatalar yalnızca çoklu iş parçacığında meydana gelmelidir, çünkü her seferinde "yeni" denir.

(2) Bunda bir isim olup olmadığını bilmiyorum, çünkü bir kaç sorun var.
- otomatik kullanılabilir olduğunda manuel temizlik -
gerekli durum -
kullanım ömrü boyunca daha uzun süre dayanan durum -
görünürlük veya kapsam çok yüksek


2

Ben buna "Wenering Xenophobe" diyorum. Yalnız kalmak istiyor ama tam olarak nerede ya da ne olduğunu bilmeden açılıyor. Bu yüzden başkalarının da söylediği gibi kötü bir şey.


2

Buradaki tanelere karşı gelmekle birlikte verilen örneği şu anki haliyle olduğu gibi iyi kodlama tarzı olarak görmeme rağmen, birim testi yapılırken kalıp mevcuttur.

Ünite testi yapmanın bu oldukça standart yolu

public class BarTester
{
    private Bar bar;

    public Setup() { bar = new Bar(); }
    public Teardown() { bar = null; }

    public TestMethodA()
    {
        bar.A();        
    }

    public TestMethodB()
    {
        bar.B();
    }
}

bu sadece OP kodunun eşdeğerinin yeniden düzenlenmesidir

public class BarTester
{
    private Bar bar;

    public TestMethodA()
    {
        bar = new Bar();
        bar.A();
        bar = null;
    }

    public TestMethodB()
    {
        bar = new Bar();
        bar.B();
        bar = null;
    }
}

OP'nin örneğinde olduğu gibi hiçbir zaman kod yazmam, yeniden yakıcı çığlık atıyor, ancak kalıbın ne geçersiz ne de bir antiptern olduğunu düşünüyorum .


Bu durumda, fikstür her test için bağımsız olarak başlatılır ve değişken yeniden kullanımı veya eşzamanlılık ile ilgili sorunlar ortaya çıkmaz. Genel durumda (dış ünite testleri), her nesnede en fazla bir yöntemin çağrılıp çağrılmadığı bilinmemektedir.
Philipp

1
@Philipp - Yeniden kullanım veya eşzamanlılık sorununa itiraz etmiyorum, ancak OP'nin sorusu ünite testlerinde yaygın olarak kullanılan modelle ilgiliydi. Fikstürün her test için somutlaştırılmış olması, test çerçevesinin bir uygulama detayıdır. Birim testinde bile, desen yalnızca test çerçevesi kullanılması gerektiği gibi kullanıldığında güvenlidir. Bu modeli üretim kodunda kullanırken de aynı sebep geçerlidir.
Lieven Keersmaekers

Ayarlamak için gerek yoktur bariçin nullJUnit Zaten her deney yöntemi için yeni bir test örneği oluşturur.
oberlies

2

Bu kod kokusuna Beck / Fowler tarafından Yeniden yapılanmada Geçici Alan denir.

http://sourcemaking.com/refactoring/temporary-field

Moderatörlerin isteği ile daha fazla açıklama eklemek için düzenlendi: Yukarıda belirtilen URL’deki veya kitabın basılı kopyasındaki kod kokusu hakkında daha fazla bilgi edinebilirsiniz. OP, bu özel antipattern / kod kokusunun adını aradığı için, 10 yaşından daha eski olan yerleşik bir kaynaktan daha önce belirtilmeyen bir referansa atıfta bulunmanın yardımcı olacağını düşündüm. Bu sorudaki oyun, bu yüzden cevabın oylanıp kabul edilme olasılığı düşük.

Kişisel olarak tanıtılmıyorsa, gelecek olan Çoğul Görüş dersimde, Ağustos 2013'te yayınlanmasını umduğum Refactoring Temelleri adlı bu özel kod kokusuna gönderme ve açıklama yapıyorum.

Daha fazla değer ekleyerek, bu sorunu nasıl çözeceğimizden bahsedelim. Birkaç seçenek var. Alan gerçekten yalnızca bir yöntemle kullanılıyorsa, yerel bir değişkene indirgenebilir. Bununla birlikte, eğer iletişim kurmak için alanı (parametrelerin yerine) kullanan birden fazla yöntem kullanılıyorsa, bu, Yeniden Düzenleme'de açıklanan klasik durumdur ve alanın parametrelerle değiştirilmesiyle veya bu kodla çalışan yöntemlerin yakından kullanılmasıyla düzeltilebilir. İlişkili, Extract Class, yöntemleri ve alanları / alanları alanın her zaman geçerli bir durumda olduğu (belki de inşaat sırasında ayarlanmış) olduğu ve bu yeni sınıfın durumunu temsil ettiği kendi sınıflarına çekmek için kullanılabilir. Parametre yolunda ilerliyorsanız ancak geçilecek çok fazla değer varsa, başka bir seçenek de yeni bir Parametre Nesnesi tanıtmaktır.


Geçici Alanların bir Özütleme Sınıfı yeniden düzenleme için genellikle gerekli olduğunu belirtmek önemlidir. Ancak bunun farkında olan biri muhtemelen bu ara durumdaki kodu kontrol etmez.
oberlies

1

Derhal aşağı indiğinizde, bu gerçekten bir uyum eksikliğidir ve ona "Yanlış Uyum" adını verebilirim. Bu parayı (veya onu bir yerden alıp unutursam, "ödünç al") bu terim para kazanırdım, çünkü sınıf bir üye alanda işlem yapıyor gibi görünmektedir. Bununla birlikte, gerçekte yapmazlar, yani görünür uyumu aslında yanlıştır.

Kötü olup olmadığına gelince, açıkça öyle olduğunu söyleyebilirim ve Stephen C'nin nedenini açıklamak için mükemmel bir iş çıkardığını düşünüyorum. Bununla birlikte, "anti-patern" olarak adlandırılmayı hak edip etmemeyi hak etse de, bence ve diğer herhangi bir kodlama paradigmasının bir etiketle yapabileceğini düşünüyorum, çünkü bu genellikle iletişimi kolaylaştırır.


1

Bahsedilen sorunların dışında, bu yaklaşımı otomatik çöp toplama (örneğin C ++) olmadan ortamda kullanmak, geçici nesneler kullanımdan sonra serbest bırakılmadığından bellek sızıntılarına neden olur. (Bu biraz zorlanmış gibi görünse de, 'null' değerini 'NULL' olarak değiştiren ve kodun derlenmesinden memnun olacak insanlar var.)


1

Bu bana Flyweight modelinin korkunç bir yanlış uygulaması gibi görünüyor. Maalesef aynı "şeyi" farklı yöntemlerle defalarca kullanmak zorunda kalan birkaç geliştiriciyi tanıdım ve hafızayı kaydetme ya da performansı veya başka garip sözde optimizasyonları geliştirmek için yanlış bir girişimde bulunarak özel bir alana çıkardım. Akıllarına benzer bir sorunu çözmeye çalışıyorlar çünkü Flyweight aslında çözülmesi gereken bir problem olmadığı bir durumda yaptıklarını ele almayı amaçlıyor.


-1

Çoğu zaman, genellikle daha önce VBA For Dummies'i ilk ismi olarak alan ve girdikleri dilde nispeten büyük bir sistem yazmaya devam eden biri tarafından yazılan kodu yenilerken.

Bunun gerçekten kötü bir programlama uygulaması olduğunu söylemek doğru, ancak orijinal geliştiriciyi "daha güvenli" bir yol boyunca yönlendirmiş olabileceğimiz, bugün hepimizden keyif aldığımız gibi, internet ve meslektaşları tarafından gözden geçirilmiş kaynakların bulunmamasının bir sonucu olabilir.

Yine de "antipattern" etiketini haketmiyor - ancak OP'nin nasıl yeniden kodlanabileceği ile ilgili önerileri görmek güzeldi.


1
Stack Exchange Programcılarına hoş geldiniz, ilk cevabınızı girdiğiniz için teşekkür ederiz. Büyük olasılıkla SSS’de listelenen sebeplerden dolayı aşağı oy kullanmışsınız gibi görünüyor. programmers.stackexchange.com/faq . SSS, etkili (ve yukarı oylanan) cevapların alınması konusunda harika önerilerde bulunur. Bazen insanlar bir şekilde yanlış olup olmadığını, kopyalandığını, delilsiz düşünceyi ya da daha önceki bir cevabı tekrar eden bir ben olduğunu belirtmek için aşağı oy hakkında bir not eklemek için kibardırlar. Çoğumuz aşağı oy kullandık, kapatıldı veya cevapları kaldırdık, bu yüzden endişelenmeyin. Bu sadece başlamanın bir parçası. Hoşgeldiniz.
DeveloperDon
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.