Karşılaştığınız en kötü anti-kalıplar [kapalı]


9

Bir programcı olarak kariyerinizde karşılaştığınız en kötü anti-paternler nelerdir?

Büyük olasılıkla dilden bağımsız olmasına rağmen çoğunlukla java ile ilgileniyorum.

Bence en kötüsü ana anti-desen diyorum . Tüm mantığı içeren tek, son derece büyük sınıftan (bazen bir çift küçük sınıfın eşlik ettiği) oluşan program anlamına gelir. Genellikle tüm iş mantığının bulunduğu büyük bir döngü ile, bazen on binlerce kod satırı vardır.

Yanıtlar:


38

Yorum kodu. Blokları, belki de yüzlerce satır. Teori, hey yorum, hiçbir zarar vermez ve belki de gelecekte buna ihtiyacımız olacak.


7
En azından güvenle silebilirsiniz. Birlikte çalıştığım birinin aksine, sık sık prosedürleri yeniden adlandırır ve ölü kodu erişilebilir bırakır. Blech.
Jay

@Cyrena, Eric ile de mi çalıştın?!?
CaffGeek

Bir şey kod kilitlemek için #ifdef YORUM kullanılan bir kez vardı. Bir kişi COMMENT tanımlayana kadar harika çalıştı.
Michael Kohne

9
Bu, sürüm kontrolünü kullanmanın işe yaradığı başka bir durumdur. Birkaç tuşa basarak tekrar alınabileceğinden, gelecekte ihtiyacınız olup olmayacağını sormak zorunda kalmadan kodu silebilirsiniz.
Jason B

5
Bence yorumlanmış kod bir yere sahiptir, öneki neden orada olduğunu açıklayan bir yorum ile. Bazen, almayı düşündüğüm potansiyel bir yolu temsil eden yorumlanmış bir blok bırakacağım ve neden yapmadığım hakkında bir yorum bırakacağım. @Jason, bunun sürüm kontrolünün rolü olduğunu kesinlikle duydum, ancak sürüm kontrolünde silinen kod çok keşfedilemez.
nlawalker

19

"Kopya makarna" ile bir diğer bariz olana çarpacağım. İstediğinizle neredeyse aynı olan kodu kopyalayın, ardından birkaç şeyi değiştirin (bir yönteme çıkarmak yerine).

Bu, özellikle 90'ların sonlarından itibaren bazı fonksiyonel ve API test kodlarında yaygındır: Kelimenin tam anlamıyla, 3 veya 4 parametre alan birkaç işleve ayrılabilen yüzlerce (hatta binlerce) neredeyse aynı test örneği - veya daha da iyisi , veri odaklı bir şey. Üniversiteden ilk işim tam anlamıyla 8 aylık yeniden yazma ve kullanımdan kaldırılan yöntemleri kullanan binlerce satır makarnayı yeniden düzenleme oldu. Yapıldığım zaman, test dosyaları orijinal boyutlarının 10'undan daha azdı ve çok daha sürdürülebilir (ve okunabilir!).


16

Pattern Mania ve çok daha az çaba ile çözülebilecek çözümler hakkında çok şey yazabileceğimi düşünüyorum , ancak son zamanlarda basit bir çözümün nasıl aşırı karmaşık olabileceğine dair harika bir örnekle okuduğum harika bir makaleye işaret etmeyi tercih ederim. .

Java'da Faktöriyel nasıl yazılır (ya da değil) veya algoritmanıza bir fabrika koyduk


3
Müthiş! Şimdi FactorialWebService nerede? : P
Hayal kırıklığına

1
Ben buna Desen Ateşi diyorum ... herkes kariyerinin bir noktasında. Aramızda daha iyi olan, bunun ötesinde büyür. Adam bana kalıpları ne zaman düşünmem gerektiğini sorduğu bir röportaj yaptım. Ona sisteme dönüşmelerine izin verdiğimi söyledim. "Hayır, baştan kalıp kullanmalısın" dedi.
Michael Brown

FactoryFactories, gerçek seçimi mümkün olduğunca ertelemek istemesinin bir belirtisidir, ancak yine de sabit kodlama veya harici bir dize değerini bir kod parçasına eşleme ile sonuçlanır. Bağımlılık Enjeksiyonu daha iyi bir çözümdür.

Desenler iyi tasarımın eserleridir - bu şekilde ele alınmalıdır. Onları çözümden ziyade tanım olarak tanımlamayı seviyorum. İletişim kurarken faydalıdırlar, ancak tasarımda olması gerekmez.
Michael K

Bunun için teşekkürler, iyi okuma.
Syg


14

bölgeler

C # 'da IDE içinde daraltılabilen bir kod bölgesi tanımlayabilir ve böylece bu kodla uğraşmak istemediğiniz sürece onu gizleyebilirsiniz. Bölgelerin yüzlerce hatta yayıldığı bir projede bulundum (abartmak isterdim) ve bin hat fonksiyonunda birden fazla bölge vardı (yine keşke şaka yapsaydım).

Yukarı tarafta, bölgeyi yapan geliştirici, bir bölgedeki belirli işlevleri tanımlamak için çok iyi bir iş çıkardı. O kadar ki bölgede bir özüt yöntemi yapabildim ve devam ettim.

Bölgeler geliştiricileri boklarını düz bir şekilde "gizlemeye" teşvik eder.


15
Bölgeler için +1, geliştiricileri boklarını düz bir şekilde "gizlemeye" teşvik eder. Ancak, doğru kullanıldığında, bölgelerin kodu mantıksal olarak gruplandırmasına ve daha sonra kolayca bulmasına yardımcı olduğunu buldum.
Darren Young

Bu, katlama editörlerinde uzun zamandır bir sorun olmuştur. En son OCCAM'da programladığımda aynı şeyi yapardım.
Michael Kohne

2
Bölgeleri seviyorum ... ama sadece organizasyon için ... dijital kod yığınlarını gizlemiyorum.
IAbstract

3
+1. Bu nedenle bölgelerin kullanılması StyleCop SA1124 kuralını ihlal ediyor DoNotUseRegions.
Arseni Mourzenko

1
SQL alanların çok sayıda ile çalışan projeler var ve güncelleştirir / oluşturur kodu birçok satır. Bir bölge #region SQL Updateonu katlanabilir hale getirir, böylece daha az kaydırma gerekir.
JYelton


9

Aşırı yükleme yöntemleri:

// Do something
public int doSomething(Data d);

// Do same thing, but with some other data
public int doSomething2(SomeOtherData d);

Programcının aşırı yüklemeyi anlamadığını açıkça göstermektedir.



5

Yumuşak kodlama , yani programcılar sabit kodlamadan kaçınmak ve "sert kodlanmış" bağımlılıklar olmak üzere ölçeğin diğer tarafında olmak üzere kendi yollarından çıktığında.


4

İstemcide durumu koru.

Bir kez tüm durumun tarayıcıda tutulduğu bir web uygulaması ile çalıştı. (Sorunsuz ölçeklenebilirlik sağlamak için tüm istisnalar dikkate alınmamıştır).


Lütfen biraz açıklayabilir misiniz? Imho, bir Web uygulaması için, tarayıcıdaki tek durum (yani, çerezler) olduğunda ve sunucu 'hiçbir şey paylaşmıyorsa' iyi olur. Yoksa 'uygulama veritabanında' olduğu gibi 'durum' mu demek istediniz?
keppla

Durum: Üzerinde çalışılacak gerçek verilerdeki gibi.

OO benim en derin sempatilerim var.
keppla

4

Büyük Checkin

Bir geliştiricinin bir hafta içinde check-in yapmadığını gördüğümde nefret ediyorum. Bu, ya sıkışmış ve yardım aramamış ya da bir sürü özelliği tek bir büyük check-in'e topluyor olduğu anlamına geliyor. (En kötü senaryoyu bıraktım, sadece bir şey yapmıyor. Çözülmesi kolay ... işe alınmış gibi iki kelime geliyor.)

Büyük bir check-in yapıyorsanız, bir değişiklik setini belirli bir özelliğe bağlayabilmeniz gibi SCM'nin birçok avantajını kaybedersiniz. Ayrıca yapacak çok fazla kaynaşmanız da muhtemeldir ve doğru olması kolay değildir.


1
Hiçbir şey yapmamak her zaman en kötü durum senaryosu değildir. Bazen yeniden yazmak için kodlara göre sıfırdan yazmak daha iyidir ...
Malachi

4

Şu anda, eski bir kod parçası ile çalışıyorum ve önceki kodlayıcının bir listenin ilk öğesini almasını seviyorum:

String result;
for(int i = 0; i < someList.size(); i++) {
    result = someList.get(i);
    break;
}

Ama imho kötü bu kodda gördüm sınıfları satır içi JSPs sayfaları tanımlamak, scriptlet ve out.println :-( kullanarak tüm HTML, CSS ve Javascript yazın


4

Gördüğüm en kötü davranış karşıtı kalıplardan biri, kodun sadece üretimden sonra sürüm kontrolüne kontrol edilmesine izin veren bir dükkandı. VSS'deki özel kontrollerle birleştiğinde, bir sonraki sürümden önce bir üretim arızasının düzeltilmesi gerekiyorsa, bir sonraki sürüm için belirli bir dosyayı değiştirmek isteyen birden fazla kişinin olması durumunda, karışık bir geri alma işlemine yol açtı.

Bunun bir departman politikası olması, onu bu şekilde davranan tek bir geliştiricinin durumundan daha da kötüleştirdi.


3

Bir String dizgesinde kilitleme

synchronized("one") { /* block one A*/ }

synchronized("one") { /* block one B*/ }

Çok uzun sınıf isimleri. (JRE'de)

com.sun.java.swing.plaf.nimbus.
InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState

Kötü kalıtım yapısı

com.sun.corba.se.internal.Interceptors.PIORB extends
com.sun.corba.se.internal.POA.POAORB extends
com.sun.corba.se.internal.iiop.ORB extends
com.sun.corba.se.impl.orb.ORBImpl extends
com.sun.corba.se.spi.orb.ORB extends
com.sun.corba.se.org.omg.CORBA.ORB extends 
org.omg.CORBA_2_3.ORB extends
org.omg.CORBA.ORB

Olmayan bir İstisna.

public interface FlavorException { }

Anlamsız ve şifreli hata işleme

if (properties.size() > 10000)
   System.exit(0);

Gereksiz nesne oluşturma

Class clazz = new Integer(0).getClass();
int num = new Integer(text).intValue();

Başka amaçlar için bir istisna atma

try {
    Integer i = null;
    Integer j = i.intValue();
} catch (NullPointerException e) {
    System.out.println("Entering "+e.getStackTrace()[0]);
}

Statik yöntemler için örnek nesneler kullanma.

Thread.currentThread().sleep(100);

Nihai olmayan bir alanda senkronizasyon

synchronized(list) {
   list = new ArrayList();
}

Sabit bir String'in anlamsız kopyası

String s = new String("Hello world");

String.toString () için anlamsız çağrı

String s = "Hello";
String t = s.toString() + " World";

Hafızada yer açmak için System.gc () işlevini çağırır

Bazı belleği boşaltmak için yerel değişkeni null olarak ayarlama

    // list is out of scope anyway.
    list = null;
}

Performans nedenleriyle (veya başka bir mikro-mikro optimizasyon) i ++ yerine ++ i kullanma


Bunlar mutlaka anti-desen değil, sadece kötü kodlamadır.
Gary Willoughby

@Gary, ya da zayıf gelişim kalıpları görüyorum. Belki de bir anti-paternin katı tanımı içinde değil.
Peter Lawrey

1
@Peter: "System.gc () bazı bellek boşaltmak için çağırır", GC açıkça çağrılmadığı sürece .NET OutOfMemory istisna ile patlayacak bir durum gördüm. Tabii ki bir kuraldan çok bir istisnaydı.
Kodlayıcı

3

Kod serpiştirildi:

// TODO: 

veya

// TODO: implement feature 

ek bilgi olmadan.


2

Aptallar için yineleyici:

Iterator iCollection = collection.iterator();
for(int i = 0 ; i < collection.size() ; i++ ){
    if(collection.get(i) == something){
       iCollection.remove();
    }
 }

Singletono-Fabrika:

public class SomeObject{
   private SomeObject() {}
   public static SomeObject getInstance(){
       return new SomeObject();
   }
}

başka-güdümlü kalkınma (açık kapanış ilkesi de denir - anlaşılmaya yakın değişiklik için açık)

if (sth1){
...  
}else if(sth2){
..
}
...
..
else if(sth1000000000000){
...
}

StringPattern (StringObject olarak da bilinir):

a) sendercode
if(sth1)
   str+="#a";
if(sth2)
   str+="#b";
...
if(sth1000)
   str+="#n";

b) receiver
   regexp testing if str contains #a, #b, ... #n

Yine else ifde bu genellikle işleri halletmenin tek yoludur. Dizeleri düşünüyorum; anahtar kullanamazsınız. Koşulların faydalı olabilmesi için benzer olması gerekir.
Michael K

IMHO her biri / else yerine basit haritalama veya ziyaretçi kalıbı ile değiştirilebilir. Dizeler halinde yani aşağıdaki gibi bir dosya dosyanız olabilir: someString1 = some.package.ObjectToHandleSomeString1
Marcin Michalski

2
Tekil olan bir fabrika . Bu kodda yanlış bir şey yok. Yanlış olabilecek tek şey, dış kodun her getInstanceörneği aynı örneği döndürdüğü varsayımını yapmaktır. Böyle bir varsayım kapsüllenmeyi bozar ve aslında en yaygın anti-kalıplardan biridir.
back2dos

tam olarak bu yüzden kafa karıştırıcı :) yöntem create () olarak adlandırılmışsa veya her şey mükemmel olacak her seferinde aynı örneği dönecekti
Marcin Michalski

2

Bu bir kodlama modeli değil, davranışsal bir desen, oldukça kötü olsa da: koddaki bir şeyi değiştirmek (gereksinimlerin değiştiğini söyleyelim), daha sonra kod geçene kadar tüm birim testlerini düzenleyin. Tüm test kodunu test yönteminden değiştirmek veya kaldırmak, ancak yöntemi orada bırakmak.

Bu daha genel bir modelle bağlantılıdır, That That Do pattern, bunun için temsili bir kod satırı:

int num = new Integer( stringParam ).parseInt( stringParam );

Sonuçta çalışıyor.


2

Kesinlikle soyutlama tersini veya yüksek seviyeli ilkellerin üstünde düşük seviyeli ilkelleri yeniden icat etmeyi hor görüyorum . Bununla birlikte, bazen, kötü programcılardan değil, kötü dil tasarımcılarından kaynaklanır. Örnekler:

  1. Bir işlev işaretçisi yerine, üye değişkenleri ve karşılık gelen bir arabirimi olmayan (işlev işaretçileri tabloları açısından uygulanır) tek bir yöntem sınıfı kullanma. Java gibi dillerde başka seçeneğiniz olmayabilir.

  2. MATLAB ve R'de, her şeyin bir ilkelden ziyade bir vektör / matris olduğu ısrarı.

  3. MATLAB'ı varken, tamsayı olmaması gerçeğine ne dersiniz, yani bir tamsayıya ihtiyaç duyduğunuzda bir çift kullanmanız gerekir.

  4. Bir döngü yazmak için işlev çağrılarını kullanmanız gereken tamamen işlevsel diller.


1

Kesinlikle kopyala / yapıştır olurdu, bu yüzden kovboy kodlama ve ondan türeyen her şey yüzünden yapıldığım bir sürü kötü kod gördüm. (Tanrı Sınıfları, ekstra büyük yöntemler, kötü düşünülmüş algoritmalar vb.)

Ve tasarım modellerine izin verilirse, şunu söyleyebilirim: Herhangi bir tasarım veya etki alanı analizi yapmadan bir plandan eylemler kümesi olarak bir proje yapmak.


1

Çok amaçlı java fasulyesi -

Birkaç farklı işlemde kullanılan çok değişkenli bir java fasulyesi. Her işlem fasulye değişkenlerinin rastgele bir alt kümesini kullanır ve diğerlerini yok sayar. Gui durumu için birkaç değişken, bileşenler arasında dolaşmak için atılan birkaç değişken, muhtemelen artık kullanılmayan birkaç değişken. En iyi örneklerde, modelin takdir edilmesini engelleyecek hiçbir belge yoktur.

Ayrıca, sevgili unutamam

try{ 
   ... //many lines of likely dangerous operations
}
catch(Exception e){}

IMHO, istisnalar kokuyor. Onları düzeltmek için çok zorlar ve sahte bir güvenlik duygusu ekliyorlar.
Kodlayıcı

İstisnaların kokuşması hakkındaki görüşünüz ne olursa olsun, sessizce yutmak daha fazla kokmak zorundadır.
Steve

1

Eski bir iş arkadaşı, sadece yenilerini oluşturmak yerine, özelliklerinin üzerine yazarak nesneleri yeniden kullanma alışkanlığına sahipti. Yeni özellikler uygulanırken ortaya çıkan sorunların miktarını asla hayal edemezdim.


1

Bana çok fazla keder veren bir şey "Gökyüzündeki büyük harita" kalıbı. Uygun nesneleri kullanmak yerine bir haritayı atmak. Hata ayıklamadan ne "değişkenler" içerdiği hakkında hiçbir fikriniz yok ve kodu geriye doğru izlemeden ne içerebileceğini bilmiyorsunuz. Genellikle Dizeleri Nesnelerle veya Dizeleri Dizelerle eşler; bunlar potansiyel olarak temel öğeleri ayrıştırmanız gerekir.


Ne yazık ki sıklıkla gerekli olan sayfalar arasında veri yığınlarını geçmek için ASP.NET'te Session ve ViewState'e güvenmek gibi geliyor ...
Wayne Molina

1

Benim en sevdiğim gelişme anti-desen biri programlı olarak bir veya daha fazla tabloya sürekli olarak ek sütunlar gerektiren bir veritabanı "tasarım" kullanılmasıdır . Bu, bir varlığın her örneği için yeni bir tablo oluşturan "tasarım" ın bir kuzenidir. Her ikisi de kaçınılmaz olarak veritabanı sunucusunun sınırlamalarına ulaştı, ancak genellikle sistem oldukça uzun bir süre üretimde olana kadar değil.


0

Ben gördüğüm en kötü anti-desen biri bilgisayar belleği yerine geçici depolama olarak bir Veritabanı tablo kullanmayı içerir.

Sorunlu alanın mülkiyeti, açıklamama izin vermiyor, ancak temel sorunu anlamak gerekli değil. Bu, Java'da bir arka uç Veritabanı ile yazılmış bir GUI uygulamasıydı. Belirli girdi verilerini almak, manipüle etmek ve ardından işlenen verileri veritabanına vermekti.

Projemiz, daha sonra işlenmek üzere ara değerleri kaydeden oldukça karmaşık bir algoritmaya sahiptir. Geçici nesneleri ... nesnelerinde kapsüllemek yerine "t_object" gibi bir veritabanı tablosu oluşturuldu. Her değer hesaplandığında, bu tabloya eklendi. Algoritma çalışmayı bitirdikten sonra, tüm ara değerleri seçer ve hepsini tek bir büyük Map nesnesinde işler. Tüm işlemler tamamlandıktan sonra, kaydedilmek üzere işaretlenmiş kalan değerler gerçek veritabanı şemasına eklenir ve "t_object" tablosundaki geçici girişler atılır.

Tablo aynı zamanda benzersiz bir liste gibi kullanıldı, veriler yalnızca bir kez var olabilir. Bu, tabloya Kısıtlamalar uygulamış olsaydık tasarımın iyi bir özelliği olabilirdi, ancak verilerin var olup olmadığını görmek için tüm tabloyu tekrarladık. (Hayır, CONTAINS ile belirtilen maddelerde kullanılan sorguları bile kullanmadık)

Bu tasarım nedeniyle karşılaştığımız bazı problemler özellikle hata ayıklama idi. Uygulama, veriyi bu algoritmaya gelmeden önce önceden işleyecek birden fazla GUI olacak şekilde boru hattı verilerine yapılandırılmıştır. Hata ayıklama işlemi, bir test senaryosunu işlemek ve ardından yukarıdaki bölümü bitirdikten hemen sonra duraklamaktı. Sonra bu tabloda hangi verilerin bulunduğunu görmek için veritabanını sorgulayacağız.

Keşfettiğimiz bir diğer sorun, verilerin bu geçici tablodan düzgün bir şekilde silinmemesidir; bu, gelecekte run'lara müdahale eder. Bunun, İstisnaların düzgün bir şekilde işlenmemesinden ve dolayısıyla uygulamanın düzgün bir şekilde çıkmamasından ve kontrol ettiği tablodaki verileri silmemesinden kaynaklandığını keşfettik.

Temel Nesneye Dayalı Tasarım'ı kullansaydık ve her şeyi Bellekte tutsaydık, yukarıdaki sorunlar asla gerçekleşmezdi. İlk olarak, uygulamadaki kesme noktalarını kolayca ayarlayabildiğimiz ve daha sonra yığın ve yığındaki belleği inceleyebildiğimiz için hata ayıklama basit olurdu. İkincisi, uygulamadan anormal çıkıştan sonra, java belleği, veritabanından silinmesi konusunda endişe etmeden doğal olarak temizlenirdi.

NOT: Bu modelin doğası gereği kötü olduğunu söylemiyorum, ancak bu örnekte temel OO ilkeleri yeterli olduğunda gereksiz olduğunu buldum.

Böyle bir şey ilk kez gördüğüm için bu anti-desen için bir isim olduğundan emin değilim. Bu model için aklınıza gelebilecek iyi isimler var mı?


Buna battaniye sorunu demezdim. Ne kadar geçici verinin saklandığına ve neyin yapıldığına bağlı.
GrandmasterB

Gönderiye daha fazla eklemeliyim, ancak asıl sorun nesneleri değiştirmek ve bellekten verilere erişmek yerine veri kesmek sql kodu ile manipüle edildi. Bu, karmaşıklığın artmasına ve ciddi performans sorunlarına yol açtı.
jluzwick

2
Sorun alanınızdan bahsetmiyorsunuz, ancak her zaman kötü bir şey değil, böyle bir yerde durumu tutmak, işlemlerin ölçeklenmesine ve uzun çalışma süreleri boyunca iç içe geçmesine ve hata ayıklamaya yardımcı olabilir. DB erişimi performans sorunlarına veya endişelerine neden oldu mu?
Jé Queue

Makaleyi projemizde nasıl kullanıldığını daha iyi yansıtacak şekilde düzenledim, ancak hata ayıklama sırasında çok sayıda sorun yaşadık, özellikle de geçici değişkenleri görmek için veritabanını sorgulamamız gerekti. Ayrıca, veri tabanının sürekli olarak sorgulanması ve yeni verilerin var olup olmadığını kontrol etmesi nedeniyle performansla ilgili büyük sorunlar yaşadık.
jluzwick

0

Attan Önce Sepeti - aka YouMightNeedIt

Örneğin:

  • Özünde aşırı genelleştirilmiş veri küp ... - soyut kavramlar, çapraz referanslarla bir RDMBs şema oluşturma SONRA Ve bir yapar-herşey modeli çevresindeki özelikleri yazma.

Bu YAGNI'nin kötü ikiz kardeşi olurdu, değil mi?
Wayne Molina

0

IMO gördüğüm en kötü anti-desen "Herhangi bir sinsi 'desene ihtiyacımız yok" Anti-Pattern: Tasarım desenlerinin zaman kaybı olduğu ve sadece bir araya getirerek ve daha hızlı bir şekilde kod yazarak / yapıştırın.

Mansiyon, eski VB6 stilini kullanarak veritabanından bir nesne yükleyen koda sahip olmaktır:

Foobar oFoo = new Foobar();
oFoo.FooID = 42;
if (oFoo.Load()) { 
    // do something with oFoo
}

aslında bir anti-desen değil, doğru mimariden ve endişelerin ayrılmasından yararlanamadığını gösterir.

Ayrıca, bunun gibi şeyler:

// this name is misleading, we may not always want to stand in fire,
// we may want to stand in slime or voidzones or ice patches...
public Foobar StandInFire() { }

// why is this here???
public string BeatWithNerfBat(string whom) { }

// ????
public int GivePony(string to) { }
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.