Soyutlamaların kod okunabilirliğini azaltması gerekiyor mu?


19

Birlikte çalıştığım iyi bir geliştirici, geçtiğimiz günlerde miras aldığımız bazı kodlarda bir özelliği uygulamada yaşadığı zorluklardan bahsetti; sorunun kodun takip edilmesinin zor olduğunu söyledi. Bundan sonra, ürüne daha derinlemesine baktım ve kod yolunu görmenin ne kadar zor olduğunu anladım.

O kadar çok arayüz ve soyut katman kullandı ki, şeylerin nerede başladığını ve bittiğini anlamaya çalışmak oldukça zor oldu. Geçmiş projelere baktığım zamanları düşündüm (temiz kod ilkelerinin farkında olmadan önce) ve projede dolaşmayı son derece zor buldum, çünkü kod navigasyon araçlarım beni her zaman bir arayüze indirecekti. Somut uygulamayı bulmak veya bazı eklenti tipi mimaride bir şeyin kablolandığı yeri bulmak için fazladan çaba sarf eder.

Bazı geliştiricilerin bu nedenle bağımlılık enjeksiyon kaplarını kesinlikle geri çevirdiğini biliyorum. Yazılımın yolunu o kadar karıştırır ki, kod navigasyonu zorluğu katlanarak artar.

Benim sorum şu: Bir çerçeve ya da desen böyle çok fazla yük getirdiğinde buna değer mi? Kötü uygulanmış bir paternin belirtisi mi?

Bir geliştiricinin, soyutlamaların projeye getirdiği şeylerin daha büyük resmine bakarak hayal kırıklığı yaşamasına yardımcı olması gerektiğini düşünüyorum. Yine de, bu büyük resmi görmelerini sağlamak zordur. TDD ile IOC ve DI'nin ihtiyaçlarını karşılayamadığımı biliyorum. Bu geliştiriciler için, bu araçların kullanımı sadece kod okunabilirliğini çok fazla arttırır.

Yanıtlar:


17

Bu, @kevin cline'ın cevabı hakkında gerçekten uzun bir yorum.

Her ne kadar dillerin kendileri buna neden olmasa da, engellemese de, bence bunun dillerle (veya en azından dil topluluklarıyla) bir dereceye kadar ilişkili olduğu fikrinde bir şey var. Özellikle, aynı dilde farklı dillerde karşılaşabilmenize rağmen, genellikle farklı dillerde oldukça farklı biçimler alacaktır.

Örneğin, C ++ ile bu durumla karşılaştığınızda, bunun çok az soyutlamanın ve daha çok çok akıllılığın bir sonucu olması ihtimali vardır. Örneğin, programcı gerçekleşmekte olan (bulamayacağınız) önemli dönüşümü özel bir yineleyicide gizlemiştir, bu yüzden verileri bir yerden diğerine kopyalamak gibi görünen şey, gerçekten hiçbir şeyi olmayan bir dizi yan etkiye sahiptir. verilerin kopyalanmasıyla ilgilidir. Sadece şeyleri ilginç tutmak için, bu, bir tür nesneyi diğerine aktarma sırasında geçici bir nesne yaratmanın bir yan etkisi olarak oluşturulan çıktı ile araya getirilir.

Buna karşılık, Java ile karşılaştığınızda, iyi bilinen "kurumsal merhaba dünyasının" bazı çeşitlerini görme olasılığınız daha yüksektir, burada basit bir şey yapan tek bir önemsiz sınıf yerine soyut bir temel sınıf alırsınız. ve X arabirimini uygulayan ve DI çerçevesinde bir fabrika sınıfı tarafından oluşturulan somut bir türetilmiş sınıf, vb. Gerçek işi yapan 10 kod satırı, 5000 altyapı hattı altına gömülür.

Bazıları çevreye en az dil kadar - X11 ve MS Windows gibi pencere ortamlarıyla doğrudan çalışmak, önemsiz bir "merhaba dünya" programını neredeyse ayrılmaz çöp 300'den fazla satıra dönüştürmekle meşhurdur. Zamanla, bizi de bundan izole etmek için çeşitli araç takımları geliştirdik - ancak 1) bu araç takımları oldukça önemsiz değil ve 2) sonuç hala daha büyük ve daha karmaşık değil, aynı zamanda genellikle daha az esnek metin modu eşdeğerinden daha fazladır (örneğin, yalnızca bir miktar metin yazdırmasına rağmen, dosyayı bir dosyaya yönlendirmek nadiren mümkündür / desteklenir).

Orijinal soruyu cevaplamak (en azından bir kısmı): en azından onu gördüğümde, bu, eldeki göreve uygun olmayan bir desen uygulamaktan ziyade, bir desenin zayıf bir şekilde uygulanması meselesiydi. çoğu zaman kaçınılmaz olarak çok büyük ve karmaşık bir programda yararlı olabilecek bazı desenleri uygulamaya çalışan, ancak daha küçük bir soruna uygulandığında, bu durumda boyut ve karmaşıklık gerçekten önlenebilir olsa da, büyük ve karmaşık hale gelir. .


7

Bunun genellikle YAGNI yaklaşımını kullanmamasından kaynaklandığını düşünüyorum. Arayüzlerden geçen her şey, tek bir somut uygulama olmasına ve başkalarını tanıtmak için mevcut bir plan olmamasına rağmen, İhtiyacınız olmayacak karmaşıklığı eklemenin en iyi örneğidir. Muhtemelen sapkınlık ama bağımlılık enjeksiyonunun çok kullanımı konusunda aynı şekilde hissediyorum.


YAGNI ve tek referans noktaları olan soyutlamalardan bahsetmek için +1. Bir soyutlama yapmanın birincil rolü, birçok şeyin ortak noktasını dışlamaktır. Bir soyutlamaya sadece bir noktadan atıfta bulunulursa, ortak şeyleri çarpanlara ayırmaktan söz edemeyiz, böyle bir soyutlama sadece yoyo problemine katkıda bulunur. Bunu genişletirim, çünkü bu her türlü soyutlama için geçerlidir: fonksiyonlar, jenerikler, makrolar, her neyse ...
Calmarius

3

Yeterli soyutlama yok ve kodunuzu anlamak zor, çünkü hangi parçaların ne yaptığını izole edemezsiniz.

Çok fazla soyutlama ve soyutlama görüyorsunuz ama kodun kendisini değil ve daha sonra gerçek yürütme iş parçacığını takip etmek zorlaşıyor.

İyi bir soyutlama elde etmek için, KISS: bu tür problemlerden kaçınmak için neyin takip edileceğini bilmek için bu sorulara cevabımı görün .

Derin hiyerarşiden ve isimlendirmekten kaçınmanın, açıkladığınız duruma bakmak için en önemli nokta olduğunu düşünüyorum. Eğer soyutlamalar iyi isimlendirilmiş olsaydı, çok derinlere gitmenize gerek kalmazdı, sadece ne olduğunu anlamanız gereken soyutlama seviyesine gitmeniz gerekmeyecekti. Adlandırma, bu soyutlamanın nerede olduğunu belirlemenizi sağlar.

Sorun, anlaşılması gereken tüm süreçlere gerçekten ihtiyaç duyduğunuzda, düşük seviyeli kodda ortaya çıkar. Daha sonra, açıkça izole edilmiş modüller yoluyla kapsülleme tek yardımcıdır.


3
Yeterli soyutlama yok ve kodunuzu anlamak zor, çünkü hangi parçaların ne yaptığını izole edemezsiniz. Bu kapsülleme, soyutlama değil. Beton sınıflardaki parçaları çok soyutlamadan izole edebilirsiniz.
Bildirimi

Sınıflar kullandığımız tek soyutlama değildir: fonksiyonlar, modüller / kütüphaneler, hizmetler, vb.
Klaim

1
@Durum: Kapsüllenen veriler elbette bir soyutlamadır.
Ed S.

Ad alanı hiyerarşileri gerçekten güzel.
JAB

2

Benim için bu bir bağlantı sorunu ve tasarımın ayrıntı düzeyi ile ilgili. En gevşek bağlantı şekli bile bir şeyden diğerine bağımlılıklar getirir. Bu yüzlerce ila binlerce nesne için yapılıyorsa, hepsi nispeten basit olsa bile, SRP'ye bağlı kalın ve tüm bağımlılıklar istikrarlı soyutlamalara doğru akıyor olsa bile, birbiriyle ilişkili bir bütün olarak akıl yürütmesi çok zor olan bir kod tabanı verir.

Teorik SE'de sıkça tartışılmayan bir kod tabanının karmaşıklığını ölçmenize yardımcı olan pratik şeyler vardır, tıpkı sona ulaşmadan önce çağrı yığınına ne kadar derin girebileceğiniz ve yapabileceğinizden önce ne kadar derine gitmeniz gerektiği gibi büyük bir güven, bir istisna durumu da dahil olmak üzere, çağrı yığınının bu düzeyinde oluşabilecek tüm olası yan etkileri anlayın.

Ve sadece tecrübelerime göre, daha sığ çağrı yığınlarına sahip düz sistemlerin akıl yürütmenin çok daha kolay olduğunu gördüm. Aşırı bir örnek, bileşenlerin sadece ham veri olduğu bir varlık bileşeni sistemidir. Sadece sistemlerin işlevselliği vardır ve bir ECS'nin uygulanması ve kullanılması sürecinde, yüz binlerce kod satırını kapsayan karmaşık kod tabanlarının temelde birkaç düzine sisteme kaynadığına dair şimdiye kadarki en kolay sistemi buldum. tüm işlevselliği içerir.

İşlevselliği Sağlayan Çok Fazla Şey

Önceki kod tabanlarında çalıştığım zamanki alternatif, yüzlerce ila binlerce çoğunlukla küçük nesneye sahip bir sistemdi, birkaç düzine hantal sistemin aksine, sadece bir nesneden diğerine mesaj iletmek için kullanılan bazı nesneler Messagevardı ( örneğin, kendi genel arayüzü). Temel olarak, ECS'yi bileşenlerin işlevselliğe sahip olduğu bir noktaya geri döndürdüğünüzde analog olarak elde ettiğiniz şeydir ve bir varlıktaki her benzersiz bileşen kombinasyonu kendi nesne türünü verir. Ve bu, ufacık fikirleri modelleyen sonsuz nesne kombinasyonları ( Particlenesne vs.Physics System, Örneğin). Bununla birlikte, kod tabanında aslında bir şeyler yapabilen ve bu nedenle yanlış bir şeyler yapabilen çok fazla şey olduğu için, geniş düzeyden ne olduğu hakkında mantık yürütmeyi zorlaştıran karmaşık bir bağımlılıklar grafiği sunma eğilimindedir. - "veri" tipi olmayan, ancak ilişkili işlevlere sahip "nesne" tipi olan türler. İlişkili işlevselliği olmayan saf veri işlevi gören türler, kendi başlarına hiçbir şey yapamayacakları için yanlış gidemezler.

Saf arayüzler bu anlaşılabilirlik problemine o kadar yardımcı olmaz çünkü "derleme zamanı bağımlılıkları" daha az karmaşık hale gelse ve değişim ve genişleme için daha fazla nefes alanı sağlıyor olsa bile, "çalışma zamanı bağımlılıkları" ve etkileşimleri daha az karmaşık hale getirmez. İstemci nesnesi, çağrılsa bile somut bir hesap nesnesindeki işlevleri çağırmaya devam eder IAccount. Çok biçimlilik ve soyut arabirimlerin kullanımları vardır, ancak herhangi bir noktada devam edebilecek tüm yan etkiler hakkında gerçekten mantıklı olmanıza yardımcı olacak şekilde şeyleri ayırmazlar. Bu tür etkili ayrıştırmayı başarmak için, işlevsellik içeren çok daha az şey içeren bir kod tabanına ihtiyacınız vardır.

Daha Fazla Veri, Daha Az İşlev

Bu yüzden, ECS yaklaşımını, tamamen uygulamadığınız halde bile, son derece yardımcı olmak için buldum, çünkü yüzlerce nesnenin ne olacağını, daha kaba tasarlanmış, daha kaba tasarlanmış, işlevsellik. "Veri" türlerinin sayısını en üst düzeye çıkarır ve "nesne" türlerinin sayısını en aza indirir ve bu nedenle sisteminizde gerçekten yanlış gidebilecek yer sayısını kesinlikle en aza indirir. Sonuç, karmaşık bir bağımlılık grafiği olmayan, sadece bileşenlere sistem, asla tersine ve asla diğer bileşenlere bileşen olmayan çok "düz" bir sistemdir. Temelde çok daha ham veri ve kod tabanının işlevselliğini anahtar alanlara, anahtar soyutlamalara merkezileştirme ve düzleştirme etkisine sahip çok daha az soyutlama.

Karmaşık şey kendi başına dururken bu 30 basit şeyin birbiriyle ilişkili olması durumunda, 30 basit şeyin akıl yürütmesi mutlaka 1'den daha karmaşık olan şeyden daha kolay değildir. Bu yüzden benim önerim aslında karmaşıklığı nesneler arasındaki etkileşimlerden ve daha fazlasını kitlesel ayrıştırmayı elde etmek için başka herhangi bir şeyle etkileşime girmek zorunda olmayan daha hantal nesnelere (monolitlere ve tanrı nesnelerine değil, aklınıza gelen ve 200 yöntemli sınıflar değil, minimalist bir arayüze sahip olmasına rağmen a Messageveya a'dan oldukça yüksek bir şey Particle). Ve daha sade eski veri türlerini tercih edin. Bunlara ne kadar bağımlı olursanız, o kadar az bağlantı elde edersiniz. Bu bazı SE fikirleriyle çelişse bile, gerçekten çok yardımcı olduğunu buldum.


0

Sorum şu ki, bir çerçeve ya da desen bu kadar fazla yük getirdiğinde buna değer mi? Kötü uygulanmış bir paternin belirtisi mi?

Belki de yanlış programlama dilini seçmenin bir belirtisidir.


1
Bunun tercih edilen dil ile nasıl bir ilgisi olduğunu anlamıyorum. Soyutlamalar yüksek düzeyde dilden bağımsız bir kavramdır.
Ed S.

@Ed: Bazı soyutlamalar bazı dillerde diğerlerinden daha basit bir şekilde gerçekleştirilebilir.
kevin cline

Evet, ancak bu, bu dillerde mükemmel bakım yapılabilir ve kolayca anlaşılabilir bir soyutlama yazamayacağınız anlamına gelmez. Demek istediğim, cevabınızın soruyu cevaplamaması veya OP'ye hiçbir şekilde yardımcı olmamasıydı.
Ed S.

0

Tasarım kalıplarının yetersiz anlaşılması, bu sorunun önemli bir sebebi olma eğilimindedir. Arada çok fazla somut veri olmadan arayüzden arayüze sıçrayan en kötü şeylerden biri Oracle'ın Izgara Kontrolü için bir uzantıydı.
Dürüst olmak gerekirse birisi Java kodumu tümüyle soyut bir fabrika yöntemi ve dekoratör desen orgazm vardı benziyordu. Ve bu beni boş ve yalnız hissettirdi.


-1

Ayrıca soyut şeyleri kolaylaştıran IDE özelliklerini kullanmaya karşı da dikkatli olurum.

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.