8. Altın çekiç
Altın çekiç, belirli bir çözümün evrensel olarak uygulanabilir olduğuna duyulan güvenle tanımlanan bir anti-kalıptır. Örnekler:-
Bir problemle karşılaştıktan ve mükemmel çözüm için bir model bulduktan sonra, bir programcı, belirli durumlar için uygun çözümler aramak yerine, bu modeli her yere yapıştırmaya, mevcut ve gelecekteki tüm projelere uygulamaya çalışır.
-
Bazı geliştiriciler bir zamanlar belirli bir durum için kendi önbellek varyantlarını yarattılar (çünkü başka hiçbir şey uygun değildi). Daha sonra özel bir önbellek mantığı içermeyen bir sonraki projede, hazır kitaplıklar (örneğin Ehcache) kullanmak yerine yine varyantlarını kullandılar. Sonuç, bir sürü böcek ve uyumsuzluğun yanı sıra çok fazla zaman kaybı ve kızarmış sinirlerdi.
Herkes bu anti-kalıp için düşebilir. Yeni başlayan biriyseniz, tasarım kalıpları hakkında bilgi sahibi olmayabilirsiniz. Bu, tüm sorunları hakim olduğunuz tek yoldan çözmeye çalışmanıza yol açabilir. Profesyonellerden bahsediyorsak, buna profesyonel deformasyon veya nerdview diyoruz. Kendi tercih ettiğiniz tasarım desenleriniz var ve doğru olanı kullanmak yerine, geçmişte iyi bir uyumun gelecekte aynı sonucu garanti ettiğini varsayarak favorinizi kullanırsınız.
Bu tuzak, kötü, istikrarsız ve sürdürülmesi zor bir uygulamadan projenin tamamen başarısız olmasına kadar çok üzücü sonuçlara yol açabilir. Tüm hastalıklar için tek bir hap olmadığı gibi, tüm durumlar için tek bir tasarım modeli de yoktur.
9. Erken optimizasyon
Erken optimizasyon , adı kendisi için konuşan bir anti-kalıptır.10. Spagetti kodu
Spagetti kodu, sarma istisnaları, koşullar ve döngüler gibi her türlü dallanmayı içeren, kötü yapılandırılmış, kafa karıştırıcı ve anlaşılması zor bir kod tarafından tanımlanan bir anti-kalıptır. Önceden, goto operatörü bu anti-kalıpın ana müttefikiydi. Goto deyimleri artık gerçekten kullanılmıyor, bu da ilgili bir takım zorlukları ve sorunları mutlu bir şekilde ortadan kaldırıyor.public boolean someDifficultMethod(List<String> XMLAttrList) {
...
int prefix = stringPool.getPrefixForQName(elementType);
int elementURI;
try {
if (prefix == -1) {
...
if (elementURI != -1) {
stringPool.setURIForQName(...);
}
} else {
...
if (elementURI == -1) {
...
}
}
} catch (Exception e) {
return false;
}
if (attrIndex != -1) {
int index = attrList.getFirstAttr(attrIndex);
while (index != -1) {
int attName = attrList.getAttrName(index);
if (!stringPool.equalNames(...)){
...
if (attPrefix != namespacesPrefix) {
if (attPrefix == -1) {
...
} else {
if (uri == -1) {
...
}
stringPool.setURIForQName(attName, uri);
...
}
if (elementDepth >= 0) {
...
}
elementDepth++;
if (elementDepth == fElementTypeStack.length) {
...
}
...
return contentSpecType == fCHILDRENSymbol;
}
}
}
}
}
Korkunç görünüyor, değil mi? Ne yazık ki, bu en yaygın anti-kalıp :( Bu tür bir kodu yazan kişi bile gelecekte onu anlayamayacak. Kodu gören diğer geliştiriciler, "Pekala, işe yararsa, o zaman tamam - ona dokunmamak daha iyidir". Genellikle, bir yöntem başlangıçta basit ve çok şeffaftır, ancak yeni gereksinimler eklendikçe, yöntem giderek daha fazla koşullu ifadelerle yüklenerek onu bunun gibi bir canavarlığa dönüştürür. göründüğünde, ya tamamen ya da en azından en karmaşık kısımlarını yeniden düzenlemeniz gerekir.Tipik olarak, bir proje planlanırken, yeniden düzenleme için zaman ayrılır, örneğin, sprint süresinin %30'u yeniden düzenleme ve testler içindir.Tabii ki bu, acele olmadığını (ama bu ne zaman olur).burada _
11. Sihirli sayılar
Sihirli sayılar, her türlü sabitin amaç veya anlamlarına dair herhangi bir açıklama yapılmadan bir programda kullanıldığı bir anti-kalıptır. Yani, genellikle kötü adlandırılırlar veya aşırı durumlarda, yorumların ne olduğunu veya nedenini açıklayan bir yorum yoktur. Spagetti kodu gibi, bu da en yaygın anti-kalıplardan biridir. Kodu yazmayan birinin sihirli sayılar veya nasıl çalıştıkları hakkında bir fikri olabilir veya olmayabilir (ve zamanla yazarın kendisi bunları açıklayamayacaktır). Sonuç olarak, bir sayıyı değiştirmek veya kaldırmak, kodun sihirli bir şekilde hep birlikte çalışmayı durdurmasına neden olur. Örneğin, 36 ve 73. Bu anti-kalıpla mücadele etmek için bir kod incelemesi öneririm. Kodunuzun, kodun ilgili bölümlerinde yer almayan geliştiriciler tarafından incelenmesi gerekir. Gözleri taze olacak ve soruları olacak: bu nedir ve bunu neden yaptın? Ve tabii ki açıklayıcı isimler kullanmanız veya yorum bırakmanız gerekiyor.12. Kopyala ve yapıştır programlama
Kopyala ve yapıştır programlama, başka birinin kodunun düşüncesizce kopyalanıp yapıştırıldığı ve muhtemelen beklenmedik yan etkilere neden olan bir anti-kalıptır. Örneğin, tam olarak anlamadığımız matematiksel hesaplamalar veya karmaşık algoritmalar içeren kopyalama ve yapıştırma yöntemleri. Bizim özel durumumuz için işe yarayabilir, ancak diğer bazı durumlarda soruna yol açabilir. Bir dizideki maksimum sayıyı belirlemek için bir yönteme ihtiyacım olduğunu varsayalım. İnternette dolaşırken şu çözümü buldum:public static int max(int[] array) {
int max = 0;
for(int i = 0; i < array.length; i++) {
if (Math.abs(array[i]) > max){
max = array[i];
}
}
return max;
}
3, 6, 1, 4 ve 2 numaralı bir dizi elde ediyoruz ve yöntem 6 değerini döndürüyor. Harika, öyle kalsın! Ancak daha sonra 2.5, -7, 2 ve 3'ten oluşan bir dizi elde ederiz ve sonucumuz -7 olur. Ve bu sonuç iyi değil. Buradaki sorun, Math.abs()'ın mutlak değeri döndürmesidir. Bunun cehaleti felakete yol açar, ancak yalnızca belirli durumlarda. Çözümü derinlemesine anlamadan, doğrulayamayacağınız birçok durum vardır. Kopyalanan kod, hem biçimsel olarak hem de daha temel bir mimari düzeyde, uygulamanın iç yapısının ötesine geçebilir. Bu tür kodların okunması ve bakımı daha zor olacaktır. Ve tabii ki, başkasının kodunu doğrudan kopyalamanın özel bir tür intihal olduğunu unutmamalıyız.
13. Tekerleği yeniden icat etmek
Tekerleği yeniden icat etmek , bazen kare tekerleği yeniden icat etmek olarak da bilinen bir anti-kalıptır.. Özünde, bu şablon, yukarıda ele alınan kopyala ve yapıştır anti-kalıpının tersidir. Bu anti-kalıpta geliştirici, çözümleri zaten mevcut olan bir sorun için kendi çözümünü uygular. Bazen bu mevcut çözümler, programcının icat ettiğinden daha iyidir. Çoğu zaman, bu yalnızca zaman kaybına ve daha düşük üretkenliğe yol açar: programcı hiç bir çözüm bulamayabilir veya en iyi olmaktan uzak bir çözüm bulabilir. Bununla birlikte, bağımsız bir çözüm oluşturma olasılığını göz ardı edemeyiz çünkü bunu yapmak, programlamayı kopyalayıp yapıştırmaya giden doğrudan bir yoldur. Programcı, hazır çözümler kullanarak veya özel çözümler yaratarak yetkin bir şekilde çözmek için ortaya çıkan belirli programlama görevleri tarafından yönlendirilmelidir. Çok sık, Bu anti-desen kullanmanın nedeni sadece aceledir. Sonuç, hazır çözümlerin yüzeysel bir analizidir (arama). Kare tekerleği yeniden icat etmek, incelenmekte olan anti-desenin olumsuz bir sonuca sahip olduğu bir durumdur. Yani, proje özel bir çözüm gerektiriyor ve geliştirici bunu kötü bir şekilde yaratıyor. Aynı zamanda, iyi bir seçenek zaten var ve diğerleri bunu başarıyla kullanıyor. Alt satır: çok fazla zaman kaybedilir. İlk olarak, çalışmayan bir şey yaratırız. Sonra onu yeniden düzenlemeye çalışırız ve sonunda zaten var olan bir şeyle değiştiririz. Halihazırda çok sayıda uygulama varken kendi özel önbelleğinizi uygulamak buna bir örnektir. Bir programcı olarak ne kadar yetenekli olursanız olun, kare bir tekerleği yeniden icat etmenin en azından zaman kaybı olduğunu unutmamalısınız. Ve bildiğiniz gibi zaman en değerli kaynaktır.14. Yo-yo sorunu
Yo -yo problemi, uygulamanın yapısının aşırı parçalanma (örneğin, aşırı derecede alt bölümlere ayrılmış bir kalıtım zinciri) nedeniyle aşırı derecede karmaşık olduğu bir anti-kalıptır. "Yo-yo sorunu", kalıtım hiyerarşisi uzun ve karmaşık olan ve derinlemesine iç içe yöntem çağrıları oluşturan bir programı anlamanız gerektiğinde ortaya çıkar. Sonuç olarak, programcıların programın davranışını incelemek için birçok farklı sınıf ve yöntem arasında gezinmesi gerekir. Bu anti-desenin adı oyuncağın adından gelmektedir. Örnek olarak aşağıdaki kalıtım zincirine bakalım: Bir Teknoloji arayüzümüz var:public interface Technology {
void turnOn();
}
Aktarım arabirimi onu devralır:
public interface Transport extends Technology {
boolean fillUp();
}
Ve sonra başka bir arayüzümüz var, GroundTransport:
public interface GroundTransportation extends Transport {
void startMove();
void brake();
}
Ve oradan soyut bir Araba sınıfı türetiyoruz:
public abstract class Car implements GroundTransportation {
@Override
public boolean fillUp() {
/* some implementation */
return true;
}
@Override
public void turnOn() {
/* some implementation */
}
public boolean openTheDoor() {
/* some implementation */
return true;
}
public abstract void fixCar();
}
Sırada soyut Volkswagen sınıfı var:
public abstract class Volkswagen extends Car {
@Override
public void startMove() {
/* some implementation */
}
@Override
public void brake() {
/* some implementation */
}
}
Ve son olarak, belirli bir model:
public class VolkswagenAmarok extends Volkswagen {
@Override
public void fixCar(){
/* some implementation */
}
}
Bu zincir bizi aşağıdaki gibi soruların cevaplarını aramaya zorluyor:
-
Kaç tane yöntemi var
VolkswagenAmarok
? -
Maksimum soyutlamayı elde etmek için soru işareti yerine hangi tür girilmelidir:
? someObj = new VolkswagenAmarok(); someObj.brake();
15. Tesadüfi karmaşıklık
Gereksiz karmaşıklık, bir çözüme gereksiz karmaşıklıkların getirildiği bir anti-kalıptır.public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description)throws Exception {
switch (type){
case CAR:
jdbcTemplate.update(CREATE_RELATION_WITH_CAR, languageId, serviceId, description);
case USER:
jdbcTemplate.update(CREATE_RELATION_WITH_USER, languageId, serviceId, description);
case FILE:
jdbcTemplate.update(CREATE_RELATION_WITH_FILE, languageId, serviceId, description);
case PLAN:
jdbcTemplate.update(CREATE_RELATION_WITH_PLAN, languageId, serviceId, description);
case CUSTOMER:
jdbcTemplate.update(CREATE_RELATION_WITH_CUSTOMER, languageId, serviceId, description);
default:
throw new Exception();
}
}
Ve buna göre, bu numaralandırmaya sahibiz:
public enum ServiceType {
CAR(),
USER(),
FILE(),
PLAN(),
CUSTOMER()
}
Her şey basit ve güzel görünüyor... Peki ya diğer yöntemler? Aslında, hepsinin bir sürü switch
ifadesi ve hemen hemen aynı veritabanı sorguları olacak ve bu da sınıfımızı büyük ölçüde karmaşıklaştıracak ve şişirecektir. Bütün bunlar nasıl daha kolay hale getirilebilir? Enumumuzu biraz yükseltelim:
@Getter
@AllArgsConstructor
public enum ServiceType {
CAR("cars_descriptions", "car_id"),
USER("users_descriptions", "user_id"),
FILE("files_descriptions", "file_id"),
PLAN("plans_descriptions", "plan_id"),
CUSTOMER("customers_descriptions", "customer_id");
private String tableName;
private String columnName;
}
Artık her tür, tablosunun orijinal alanlarının adlarına sahiptir. Sonuç olarak, açıklama oluşturma yöntemi şöyle olur:
private static final String CREATE_RELATION_WITH_SERVICE = "INSERT INTO %s(language_id, %s, description) VALUES (?, ?, ?)";
public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description) {
jdbcTemplate.update(String.format(CREATE_RELATION_WITH_SERVICE, type.getTableName(), type.getColumnName()), languageId, serviceId, description);
}
Kullanışlı, basit ve kompakt, sence de öyle değil mi? İyi bir geliştiricinin göstergesi kalıpları ne sıklıkta kullandığı değil, anti-kalıplardan ne sıklıkla kaçındığıdır. Cehalet en kötü düşmandır, çünkü düşmanlarınızı görerek tanımanız gerekir. Bugünlük benden bu kadar. Herkese teşekkürler! :)