Bunları bir sınıfa veya işleve sarmak yerine uzun ancak anlaşılır kodu kopyalayıp yapıştırmak kabul edilebilir mi?


29

İnternete bağlanmak ve bunun gibi bağlantı sonuçlarını göstermek için bir kod parçam olduğunu varsayalım:

HttpRequest* httpRequest=new HttpRequest();
httpRequest->setUrl("(some domain .com)");
httpRequest->setRequestType(HttpRequest::Type::POST);
httpRequest->setRequestData("(something like name=?&age=30&...)");
httpRequest->setResponseCallback([=](HttpClient* client, HttpResponse* response){
    string responseString=response->getResponseDataString();
        if(response->getErrorCode()!=200){
            if(response->getErrorCode()==404){
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setFontColor(255,255,255);
                alert->setPosition(Screen.MIDDLE);
                alert->show("Connection Error","Not Found");
            }else if((some other different cases)){
                (some other alert)
            }else
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setPosition(Screen.MIDDLE);
                alert->setFontColor(255,255,255);
                alert->show("Connection Error","unknown error");
            }
        }else{
            (other handle methods depend on different URL)
        }
}

kod uzundur ve yaygın olarak kullanılır, ancak yukarıdaki kod özel işlev ve sınıf gibi herhangi bir ekstra şey gerektirmez (HttpRequest ve Alert, her ikisi de varsayılan olarak çerçeve tarafından sağlanır) ve kod kesimi uzun olsa da, basit ve karmaşık değil (url, font boyutu ... gibi bir dizi ayar grubu olduğu için uzun sürüyor) ve kod segmentinin sınıf arasında çok az farklılıkları var (örneğin: url, istek verileri, hata kodu tanıtıcı durumları, normal tanıtıcı) vakalar ...)

Sorum şu ki, kodun bağımlılığını azaltacak bir fonksiyona sarmak yerine uzun ama basit kodu kopyalayıp yapıştırmak kabul edilebilir mi?


89
Tahsis ettiğiniz nesneleri serbest bırakmama gibi, bu kodda bir hatanın olduğunu hayal edin. (Çerçevenizdeki Alertnesneler serbest mi?) Şimdi hatayı düzeltmek için bu kodun kopyalanan her örneğini bulmanız gerektiğini hayal edin. Şimdi, bunu yapmak zorunda olanın sen olmadığını hayal et, ama tüm bu kopyaları ilk başta senin yaptığını bilen çılgın bir balta katili.
Sebastian Redl

8
Ve BTW, ağ iletişimi ve hata gösterimini tek bir yerde karıştırmak zaten büyük bir hayır, IMHO'dur.
Ocak'ta

11
Hayır asla. Tamamen kabul edilemez. Benim projemde olsaydınız artık benim projemde olmazdınız ve bir eğitim programında ya da PIP'de olacaktınız.
nhgrif

10
Ve "Süpervizörün ekranımın ortasındaki bu uyarı kutusu mutlak bir terör. Kedi kedileri izliyorum ve pop-up her görünüşte görüşümü engelliyor." ." 3 hafta sonra “Ne halt ettiniz ?! Artık kedi jiflerimi kapatamıyorum çünkü SİZİN açılır penceresi sağ üstteki X'i kaplıyor, düzeltin.”
MonkeyZeus

11
Bence buradaki herkes bunun kötü bir fikir olduğunu düşünüyor. Ancak soruyu tersine çevirmek için neden bu kodu ayrı bir sınıfa ya da işleve koymuyorsunuz?
Karl Gjertsen

Yanıtlar:


87

Değişimin maliyetini göz önünde bulundurmanız gerekir. Bağlantıların nasıl yapıldığını değiştirmek istiyorsanız? Ne kadar kolay olurdu? Çok sayıda yinelenen kodunuz varsa, değiştirilmesi gereken tüm yerleri bulmak oldukça zaman alabilir ve hataya açık olabilir.

Ayrıca netliği göz önünde bulundurmanız gerekir. Büyük olasılıkla, 30 kod satırına bakmak zorunda olmak, "connectToInternet" işlevine yapılan tek bir çağrı kadar kolay anlaşılmaz. Yeni işlevler eklenmesi gerektiğinde kodu anlamaya çalışırken ne kadar zaman kaybedilecek?

Çoğaltmanın problem olmadığı bazı nadir durumlar vardır. Örneğin, bir deney yapıyorsanız ve kod günün sonunda atılacak. Ancak, genel olarak, kopyalamanın maliyeti, kodu ayrı bir işleve sokmak zorunda kalmamaktan kaynaklanan küçük zaman tasarruflarından daha ağır basmaktadır .

Ayrıca bakınız https://softwareengineering.stackexchange.com/a/103235/63172


19
... ve bu 30 hattın gerçekten daha önce incelediklerinizle aynı olup olmadığını veya birinin herhangi bir nedenle kopyasında farklı bir bağlantı noktasına veya IP adresine geçip geçmediğini kim bilir. “ Varlıkla başlayan 30 satırdan herhangi birinin HttpRequestaynı olduğu ” anlamına geldiği açık bir varsayım yanıltmaca yapmak için kolaydır.
boş,

@null Mükemmel nokta. Bir keresinde, veritabanı bağlantılarının kopyalanıp yapıştırıldığı kod üzerinde çalıştım, ancak bazılarının kurulumda ince farklılıkları vardı. Bunların önemli, kasıtlı değişiklikler veya rastgele farklar olup olmadığına dair hiçbir fikrim yoktu
user949300 21

54

Yok hayır.

Aslında, "basit" kodunuz bile daha küçük parçalara bölünmelidir. En az iki.

Bağlantı kurmak ve normal 200 yanıtı işlemek için Örneğin, bazı durumlarda bir POST'tan PUT'a geçerseniz ne olur? Ya bu bağlantılarda zillionlar yapıyorsanız ve çok parçacıklı veya bağlantı biriktirmeye ihtiyacınız varsa? Kodu tek bir yerde, yöntem için bir argümanla kullanmak, bunu çok daha kolay hale getirecektir

Benzer şekilde, hataları işlemek için başka. Örneğin, uyarının rengini veya yazı tipi boyutunu değiştirirseniz. Veya zaman zaman bağlantılarla ilgili sorunlarınız var ve hataları günlüğe kaydetmek istiyorsunuz.



SRP'den de alıntı yapabilirsiniz: tek bir amacı olan bir kod bloğuna sahip olmak, anlaşılmasını ve bakımını çok daha kolay hale getirir ..
Roland Tepp

Bu, DRY ve SRP'nin gerçekte hizalandığı bir durumdur. Bazen yapmazlar.
user949300,

18

kopyalayıp yapıştırmak kabul edilebilir mi ...

Yok hayır.

Benim için karar verme argümanı şudur:

... yaygın olarak kullanılır ...

Birden fazla yerde bir kod parçası kullanırsanız , o zaman değiştiğinde, onu birden fazla yerde değiştirmeniz gerekir veya tutarsızlıklar yaşamaya başlarsınız - "tuhaf şeyler" olmaya başlar (yani, Hatalar'ı tanıtırsınız).

basit ve karmaşık değil ...

Ve böylece bir fonksiyonunda yeniden kırmak daha kolay olmalı.

... url, font boyutu gibi ayar paketleri var ...

Ve kullanıcılar neleri değiştirmeyi seviyor ? Yazı tipleri, yazı tipi boyutları, renkler vb.

Şimdi; kaç yerde tekrar aynı renk / yazı tipi / boyutu elde etmek için aynı kod parçasını değiştirmek zorunda kalacaksınız? (Önerilen cevap: sadece bir tane ).

... kod segmentinin sınıflar arasında çok az farklılıkları vardır (örneğin: url, istek verileri, hata kodu işleci durumları, normal işleci halleri ...)

Varyasyon => fonksiyon parametreleri.


"Peki, kullanıcılar neyi değiştirmeyi seviyor? Yazı tipleri, yazı tipi boyutları, renkler, vb." Gerçekten onlarca yerde bunu değiştirmek istiyor musunuz?
Dan

8

Bunun kopyala ve yapıştır ile ilgisi yok. Eğer başka bir yerden kodu alırsak, saniyede Ürünün var kodu almak için kod ve sizin o kopyalanan veya bir fark yaratmaz başınıza tamamen yazıldığı yüzden olsun, sorumluluk.

Uyarılarınızda bazı tasarım kararları alırsınız. Tüm uyarılar için büyük olasılıkla benzer tasarım kararları verilmelidir. Bu nedenle, "ShowAlertInAStyleSuitableForMyApplication" veya belki biraz daha kısa bir yerde bir yönteme sahip olmanız ve muhtemelen biraz daha kısa olması gerekir.

Benzer hata işleme ile bir sürü http isteğiniz olacak. Muhtemelen hata işleme tekrar tekrar ve tekrar tekrar değil, ortak hata işleme ayıklamak gerekir. Özellikle, hata işlemeniz biraz daha karmaşık hale gelirse (zaman aşımı hataları, 401 vb. Gibi).


6

Çoğaltma bazı durumlarda tamamdır. Ama bu değil. Bu yöntem çok karmaşık. Çoğaltmanın bir yöntemi "faktoring" yapmaktan daha kolay olduğu durumlarda daha düşük bir sınır vardır.

Örneğin:

def add(a, b)
    return a + b
end

aptalca, sadece bir + b yap.

Ama biraz, küçücük bir parça daha karmaşık hale geldiğinde, genellikle çizgiyi aşarsınız.

foo.a + foo.b

olmalı

foo.total
def foo
    ...
    def total
        return self.a + self.b
    end
end

Senin durumunda dört tane "yöntem" görüyorum. Muhtemelen farklı sınıflarda. Biri talepte bulunacak, biri yanıt alacak, biri hatalar gösterecek, yanıt yanıt verildikten sonra geri aranacak bir tür geri arama yapılacak. Şahsen aramaları kolaylaştırmak için üstüne bir çeşit "sarmalayıcı" eklerdim.

Sonunda, bir web isteği yapmak için bir şeye benzer bir şey aramak isterim:

Web.Post(URI, Params, ResponseHandler);

Bu satır kodumun her yerine sahip olacağım şeydi. Sonra "nasıl bir şeyler elde ettiğimde" değişiklikler yapmam gerektiğinde, daha az çabayla çabucak yapabilirdim.

Bu aynı zamanda kod tutar KURU ve yardımcı olur SRP .


0

Her boyutta / karmaşıklıktaki bir projede, aşağıdaki amaçlar için ihtiyaç duyduğumda kodu bulabilmek istiyorum:

  1. Beş parasız olduğunda düzelt
  2. İşlevselliği değiştirin
  3. Tekrar kullan.

Güzel olmaz mıydı, devam eden bir projeye katılmak ya da birkaç yıl boyunca bir proje üzerinde çalışmaya devam etmek ve "internete bağlanmak ve bağlantı sonuçlarını göstermek" için yeni bir istek olması nedeniyle bir yere gitmek kolaydı. httprequest için kod boyunca bir arama yapmaya güvenmek yerine iyi bir tasarım mı? Zaten Google ile bulmak muhtemelen daha kolay.

Endişelenme, ben yeni çocuğum ve bu kod bloğunu yeniden gözden geçireceğim, çünkü bu ipucu ekibine korkunç kod tabanına katıldığım için çok üzgünüm ya da şimdi geri kalanı gibi çok fazla baskı altındayım. sen ve sadece kopyalayıp yapıştırın. En azından patronu arkamdan uzak tutacak. O zaman proje gerçekten bir felaket olarak tanımlandığında, hiç kimsenin anlamadığı en son ve en büyük çerçeveye sürümü kopyalayıp yapıştırarak yeniden yazmamızı öneren ilk kişi olacağım.


0

Bir sınıf ve / veya fonksiyon, en azından benim görüşüme göre, daha iyidir. Bir kereliğine, daha küçük depolama alanı olan cihazlar (IoT, eski telefonlar vb.) İçin web uygulamaları veya uygulamaları ile ilgileniyorsanız, dosyayı daha küçük hale getirir.

Ve açıkçası en iyi nokta, yeni protokoller vb. Nedeniyle değiştirilecek bir şeyiniz varsa, vb. Sadece işlevin içeriğini değiştirirsiniz ve bu işlevi, farklı dosyalarda bile bulunabilecek bir yere koyarsanız, onları daha da zorlaştırabilir. bul ve değiştir.

Bütün bir SQL tercümanı yazdım, böylelikle PHP'deki MySQL'den daha iyi bir şekilde PHP'deki MySQLi'ye geçebildim , çünkü tercümanımı değiştirmek zorunda kaldım ve her şey çalışıyor ama bu biraz zor bir örnek.


-1

Bir kodun çoğaltılması veya iki kez çağrılan bir işleve taşınması gerekip gerekmediğine karar vermek için hangisinin daha muhtemel olduğunu belirlemeye çalışın:

  1. Kodun her iki kullanımını da aynı şekilde değiştirmek gerekecek.

  2. Kodun en az bir kullanımını değiştirerek değişiklik göstermeleri gerekir.

İlk durumda, her iki kullanımda da bir işlevin kullanılması daha iyi olacaktır; İkinci durumda, iki kullanım için ayrı bir kodun olması daha iyi olacaktır.

Bir kez kullanılacak olan bir kod parçasının aynı satırda mı yoksa başka bir fonksiyona mı çekilmesi gerektiğine karar verirken, bir fonksiyonun gerekli davranışını tam olarak nasıl tanımlayacağını anlayın. İşlevin gerekli davranışının tam ve doğru bir açıklaması kodun kendisinden daha uzun veya daha uzunsa, kodu ayrı bir işleve taşımak, işlerin daha kolay anlaşılmasının zorlaşmasına neden olabilir. İkinci bir arayanın aynı işlevi kullanması gerektiğine dair yüksek bir olasılık varsa ve işlevdeki gelecekteki herhangi bir değişikliğin her iki arayanı da etkilemesi gerekecekse yine de yapmaya değer olabilir, ancak böyle bir dikkate alınmadığında, okunabilirliğin işleri bölmek lehine olur Kodun ve gerekli davranış tanımının eşit derecede uzun olacağı seviyeye kadar.

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.