Belirgin bir soyutlama olmadan kod çoğaltma


14

Kod satırlarına baktığınızda, mantıktaki rolünü sadakatle tanımlayan tematik bir soyutlamaya uymayacağınız bir kod çoğaltma vakasıyla hiç karşılaştınız mı? Ve bunu ele almak için ne yaptın?

Kod çoğaltmadır, bu yüzden ideal olarak, örneğin kendi işlevini yapmak gibi bazı refrakterleme yapmamız gerekir. Ancak kodun onu tanımlamak için iyi bir soyutlaması olmadığından, sonuç, iyi bir isim bile bulamadığımız ve mantıktaki rolü sadece ona bakmaktan belirgin olmayan garip bir işlev olacaktır. Bu, bana göre, kodun netliğini incitiyor. Açıklığı koruyabilir ve olduğu gibi bırakabiliriz, ancak daha sonra sürdürülebilirliğe zarar veririz.

Böyle bir şeye hitap etmenin en iyi yolunun ne olduğunu düşünüyorsunuz?

Yanıtlar:


18

Bazen kod çoğaltma bir "pun" in sonucudur: İki şey aynı görünüyor, ama değil.

Aşırı soyutlamanın sisteminizin gerçek modülerliğini bozması mümkündür. Modülerlik rejimi altında, "neyin değişmesi muhtemel?" ve "kararlı olan nedir?". Kararlı olan her şey arabirime konulurken, kararsız olan her şey modülün uygulamasında kapsüllenir. Sonra, işler değiştiğinde, yapmanız gereken değişiklik o modüle izole edilir.

Yeniden düzenleme, sabit olduğunu düşündüğünüz şeyin (örneğin, bu API çağrısı her zaman iki argüman alacaktır) değiştirilmesi gerektiğinde gereklidir.

Yani, bu iki yinelenen kod parçaları için sormak istiyorum: biri için gerekli bir değişiklik mutlaka diğerinin de değiştirilmesi gerektiği anlamına mı geliyor?

Bu soruya nasıl cevap verdiğiniz, size iyi bir soyutlamanın ne olabileceği hakkında daha iyi bir fikir verebilir.

Tasarım desenleri de faydalı araçlardır. Belki çoğaltılan kodunuz belirli bir formda geçiş yapıyor ve yineleyici deseni uygulanmalıdır.

Çoğaltılan kodunuzda birden fazla dönüş değeri varsa (ve bu nedenle basit bir ayıklama yöntemi yapamazsınız), belki de döndürülen değerleri tutan bir sınıf oluşturmanız gerekir. Sınıf, iki kod parçası arasında değişen her nokta için soyut bir yöntem çağırabilir. Daha sonra sınıfın iki somut uygulamasını yaparsınız: her parça için bir tane. [Bu, etkili bir şekilde Şablon Yöntemi tasarım modelidir, C ++ 'da şablon kavramı ile karıştırılmamalıdır. Alternatif olarak, baktığınız şey Strateji modeliyle daha iyi çözülebilir.]

Bunu düşünmenin bir başka doğal ve kullanışlı yolu, üst düzey işlevlerdir. Örneğin, lambda yapmak veya kodun soyutlamaya geçmesi için anonim iç sınıflar kullanmak. Genellikle, çoğaltmayı kaldırabilirsiniz, ancak aralarında gerçekten bir ilişki yoksa (biri değişirse, diğeri de değişmelidir), o zaman ona yardım etmemek, modülerliğe zarar verebilirsiniz.


4

Böyle bir durumla karşılaştığınızda, "geleneksel olmayan" soyutlamaları düşünmek en iyisidir. Belki bir fonksiyon içinde çok fazla çoğalmanız var ve düz eski bir fonksiyonu çarpanlara ayırmak çok iyi değil çünkü çok fazla değişken geçirmeniz gerekiyor. Burada, D / Python tarzı iç içe fonksiyon (dış kapsama erişimi olan) harika çalışır. (Evet, tüm bu durumu tutmak için bir sınıf yapabilirsiniz, ancak yalnızca iki işlevde kullanıyorsanız, bu, iç içe geçmiş işlevlere sahip olmamanız için çirkin ve ayrıntılı bir çözümdür.) Belki miras tam olarak uymuyor, ancak mixin iyi çalışır. Belki de gerçekten ihtiyacınız olan şey bir makrodur. Belki bazı şablon meta programlaması veya yansıma / içgözlem, hatta üretken programlama düşünmelisiniz.

Tabii ki, pragmatik bir bakış açısından, diliniz onları desteklemiyorsa ve bunları dil içinde temiz bir şekilde uygulamak için yeterli metaprogramlama yeteneğine sahip değilse, bunların yapılması imkansız değilse bile, hepsi zordur. Bu durumda, size "daha iyi bir dil edinin" dışında ne söyleyeceğimi bilmiyorum. Ayrıca, çok sayıda soyutlama yeteneğine sahip (Ruby, Python, Lisp veya D gibi) üst düzey bir dil öğrenmek, bazı tekniklerin hala kullanılabilir, ancak daha az belirgin olduğu alt düzey dillerde daha iyi programlamanıza yardımcı olabilir.


Sıkı bir alanda sıkıştırılmış çok sayıda mükemmel teknik için +1. (Peki, açıklanan teknikler için de +1 olurdu.)
Macneil

3

Şahsen ben görmezden geliyorum ve devam ediyorum. Şansı, çoğaltılması daha iyi bir durumsa, yaşları yeniden düzenleyerek geçirebilir ve bir sonraki geliştirici bir kez bakacak ve değişikliğinizi geri alacak!


2

Bir kod örneği olmadan, kodunuzun neden kolayca tanımlanabilen bir soyutlaması olmadığını söylemek zor. Bu uyarı ile birkaç fikir:

  • ortak kodu tutmak için yeni bir işlev oluşturmak yerine, işlevselliği birkaç farklı parçaya ayırın;
  • küçük parçaları ortak veri türlerine veya soyut davranışlara göre gruplandırmak;
  • yeni parçalar verilen yinelenen kodu yeniden yazın;
  • yeni kod hala açık bir soyutlamaya meydan okuyorsa, kodu da küçük parçalara ayırın ve işlemi tekrarlayın.

Bu egzersizdeki en büyük zorluk, işlevinizin muhtemelen belirli bir soyutlama düzeyinde çok fazla ilgisiz davranış içermesi ve bazılarını daha düşük seviyelerde ele almanızdır. Netliğin, kodun korunmasında kilit önem taşıdığını doğru bir şekilde tahmin edersiniz, ancak kodun davranışını netleştirmek (mevcut durumu), kodun amacını netleştirmekten çok farklıdır.

İşlev imzalarının neyi tanımladığını belirterek daha küçük kod parçalarının özetini yapın ve daha büyük parçaların sınıflandırılması daha kolay olmalıdır.

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.