Okunabilirliğe karşı korunma, iç içe geçmiş işlev çağrıları yazma özel vakası


57

İç içe işlev çağrıları için kodlama stilim şudur:

var result_h1 = H1(b1);
var result_h2 = H2(b2);
var result_g1 = G1(result_h1, result_h2);
var result_g2 = G2(c1);
var a = F(result_g1, result_g2);

Kısa süre önce aşağıdaki kodlama tarzının kullanımda olduğu bir bölüme geçtim:

var a = F(G1(H1(b1), H2(b2)), G2(c1));

Kodlama yöntemimin sonucu, çökme işlevi söz konusu olduğunda Visual Studio, ilgili dökümü açabilir ve sorunun gerçekleştiği çizgiyi gösterebilir (özellikle erişim ihlalleriyle ilgili endişeliyim).

Korkarım, ilk programlanan aynı problem nedeniyle bir çarpışma durumunda, hangi fonksiyonun kazaya neden olduğunu bilemeyeceğimden korkuyorum.

Öte yandan, bir satıra ne kadar fazla işlem uygularsanız, bir sayfada o kadar fazla mantık elde edilir ve bu da okunabilirliği artırır.

Korkum doğru mu, yoksa ticari bir ortamda tercih edilen bir şeyi özlüyor muyum? Okunabilirlik veya bakım kolaylığı?

İlgili olup olmadığını bilmiyorum, ancak C ++ (STL) / C # dilinde çalışıyoruz.


17
@gnat: genel bir soruya atıfta bulunuyorsunuz, özellikle bahsettiğim iç içe geçmiş fonksiyon çağrıları ve çarpışma dökümü analizi durumunda ortaya çıkan sonuçlarla ilgileniyorum, ancak bağlantı için teşekkürler, oldukça ilginç bilgiler içeriyor.
Dominique,

9
Bu örnekte C ++ 'a uygulanacak olsaydı (projenizde kullanıldığından bahsettiğiniz gibi) o zaman bu sadece bir tarz meselesi değildir, çünkü değerlendirme sırasıHX ve GXçağrılar tek astarda değişebilir. Fonksiyon argümanlarının değerlendirme sırası belirtilmemiş. Herhangi bir sebepten dolayı, çağrılardaki (bilerek veya bilmeden) yan etkilerin sırasına bağlıysanız, bu “stil yeniden düzenleme” sadece okunabilirlik / bakımdan daha fazlasını etkileyebilir.
dfri

4
Değişken ismi, result_g1gerçekten kullanacağınız şey midir, yoksa bu değer gerçekten de mantıklı bir ismi olan bir şeyi temsil ediyor mu; örn percentageIncreasePerSecond. Bu aslında ikisi arasında karar vermek için benim sınav olurdu
Richard Tingle

3
Kodlama stili konusundaki duygularınız ne olursa olsun, açıkça yanlış olmadığı sürece zaten mevcut olan sözleşmeyi izlemelisiniz (bu durumda görünmüyor).
n00b

4
@ t3chb0t İstediğiniz gibi oy kullanmakta serbestsiniz, ancak lütfen bu sitede iyi, faydalı, konuyla ilgili soruları cesaretlendirmek (ve kötüleri cesaretini kırmak), bir soruyu oylama amacıyla aşağı veya yukarı çekmenin amacına dikkat edin Bir sorunun yararlı ve açık olup olmadığını belirtmek, bu nedenle, bir oylamanın, soru bağlamına yardımcı olmak için gönderilen bazı örnek kodlar üzerinde eleştiri sağlamak için bir araç olarak kullanılması gibi diğer nedenlerden dolayı oy kullanmak, genellikle sitenin kalitesini korumada yardımcı olmaz. : softwareengineering.stackexchange.com/help/privileges/vote-down
Ben Cottrell

Yanıtlar:


111

Gibi tek bir liner genişletmek zorunda kaldıysanız

 a = F(G1(H1(b1), H2(b2)), G2(c1));

Seni suçlamam. Bu sadece okumak zor değil, hata ayıklamak zor.

Neden?

  1. Yoğun
  2. Bazı hata ayıklayıcılar her şeyi bir kerede yalnızca vurgulayacak
  3. Açıklayıcı isimlerden arınmış

Orta sonuçlarla genişletirseniz,

 var result_h1 = H1(b1);
 var result_h2 = H2(b2);
 var result_g1 = G1(result_h1, result_h2);
 var result_g2 = G2(c1);
 var a = F(result_g1, result_g2);

ve hala okumak zor. Neden? İki problemi çözer ve dördüncüsü sunar:

  1. Yoğun
  2. Bazı hata ayıklayıcılar her şeyi bir kerede yalnızca vurgulayacak
  3. Açıklayıcı isimlerden arınmış
  4. Açıklayıcı olmayan isimlerle darmadağın

Yeni, iyi, anlamsal anlam katan, hatta daha iyi olan isimlerle genişletirseniz İyi bir isim anlamama yardımcı oluyor.

 var temperature = H1(b1);
 var humidity = H2(b2);
 var precipitation = G1(temperature, humidity);
 var dewPoint = G2(c1);
 var forecast = F(precipitation, dewPoint);

Şimdi en azından bu bir hikaye anlatıyor. Sorunları çözer ve burada sunulan her şeyden açıkça daha iyidir, ancak isimleri bulmanızı gerektirir.

Bunu gibi anlamsız isimlerle yaparsanız result_thisve result_thatsadece iyi isimleri düşünemediğiniz için, o zaman bize anlamsız isim dağınıklığından kurtulmanızı ve bazı eski güzel boşlukları kullanarak genişletmenizi tercih ederim:

int a = 
    F(
        G1(
            H1(b1), 
            H2(b2)
        ), 
        G2(c1)
    )
;

Aynı şekilde, eğer öyle olmasa da, anlamsız sonuç isimlerine sahip olandan daha okunur (bu fonksiyon isimlerinin bu kadar iyi olması değil).

  1. Yoğun
  2. Bazı hata ayıklayıcılar her şeyi bir kerede yalnızca vurgulayacak
  3. Açıklayıcı isimlerden arınmış
  4. Açıklayıcı olmayan isimlerle darmadağın

İyi isimleri düşünemediğinizde, elinden geldiğince iyi.

Bazı nedenlerden dolayı, hata ayıklayıcılar yeni satırları sever, bu nedenle bu hata ayıklamanın zor olmadığını bulmalısınız:

görüntü tanımını buraya girin

Bu yeterli değilse, G2()bir yerde birden fazla yerde olduğunu hayal edin ve sonra bu oldu:

Exception in thread "main" java.lang.NullPointerException
    at composition.Example.G2(Example.java:34)
    at composition.Example.main(Example.java:18)

Her G2()arama kendi hattında olacağı için bu tarzın sizi doğrudan ana saldırgan telefona götürmesi hoş bir şey.

Bu yüzden lütfen 1. ve 2. problemleri bize 4. problemle karşı koymak için bir mazeret olarak kullanmayınız. Yapamadığınızda anlamsız isimlerden kaçının.

Orbit'in yorumunda Hafiflik Yarışları, doğru bir şekilde bu fonksiyonların yapay olduğunu ve kendilerinin çok kötü isimlerinin olduğunu gösteriyor. İşte bu tarzı vahşi koddan bazı kodlara uygulamanın bir örneği:

var user = db.t_ST_User.Where(_user => string.Compare(domain,  
_user.domainName.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
.Where(_user => string.Compare(samAccountName, _user.samAccountName.Trim(), 
StringComparison.OrdinalIgnoreCase) == 0).Where(_user => _user.deleted == false)
.FirstOrDefault();

Kelime sarma gerekmediğinde bile, bu ses akışına bakmaktan nefret ediyorum. İşte bu stilin altında nasıl göründüğü:

var user = db
    .t_ST_User
    .Where(
        _user => string.Compare(
            domain, 
            _user.domainName.Trim(), 
            StringComparison.OrdinalIgnoreCase
        ) == 0
    )
    .Where(
        _user => string.Compare(
            samAccountName, 
            _user.samAccountName.Trim(), 
            StringComparison.OrdinalIgnoreCase
        ) == 0
    )
    .Where(_user => _user.deleted == false)
    .FirstOrDefault()
;

Gördüğünüz gibi, bu stilin nesne yönelimli alana hareket eden işlevsel kodla iyi çalıştığını gördüm. Eğer orta tarzda bunu yapmak için iyi isimler bulursanız, o zaman size daha fazla güç. O zamana kadar bunu kullanıyorum. Ancak, her durumda, anlamsız sonuç adlarından kaçınmanın bir yolunu bulun. Gözlerimi acıtıyorlar.


20
@ Steve ve size yapmamasını söylemiyorum. Anlamlı bir isim için yalvarıyorum. Sık sık ara tarzını akılsızca yaptığımı gördüm. Kötü isimler beynimi, her satırdaki seyrek kodlardan çok daha fazla yakıyor. Daha fazla ayrışmam için beni motive etmelerine izin veriyorum. Eğer iyi isimler olmayacaksa, anlamsız seslerden kaçınmak için bu işi düşünün.
candied_orange

6
Mesajınıza ekliyorum: Küçük bir kuralım var: Eğer adlandıramazsanız, iyi tanımlanmadığının bir işareti olabilir. Varlıklar, özellikler, değişkenler, modüller, menüler, yardımcı sınıflar, yöntemler vb. Üzerinde kullanıyorum. Birçok durumda bu küçük kural tasarımda ciddi bir kusur olduğunu ortaya koydu. Dolayısıyla, iyi bir adlandırma sadece okunabilirliğe ve korunabilirliğe katkıda bulunmakla kalmaz, aynı zamanda tasarımı doğrulamanıza yardımcı olur. Tabii ki her basit kuralın istisnaları var.
Alireza

4
Genişletilmiş sürüm çirkin görünüyor. Orada çok fazla boşluk var, her şeyi vurgulayan şey, her şeyden önce vurgulanan her şeyi yansıtıyor.
Mateen Ulhaq

5
@MateenUlhaq Fazladan boşluk olan tek boşluk, birkaç yeni satır ve bir miktar girinti ve hepsi dikkatlice anlamlı sınırlara yerleştirilmiş . Yorumunuz bunun yerine boşlukları anlamlı olmayan sınırlara yerleştirir. Size biraz daha yakından ve daha açık bir görünüm almanızı öneririm.
jpmc26

3
@MateenUlhaq'in aksine, bu özel örnekte, bu fonksiyon örneğinde bulunan boşluktaki çit üzerindeyim, fakat gerçek fonksiyon isimleriyle (uzunluğu ikiden fazla karakterden daha fazla, doğru?) Ne isterdim.
Monica ile

50

Öte yandan, bir satıra ne kadar fazla işlem uygularsanız, bir sayfada o kadar fazla mantık elde edilir ve bu da okunabilirliği artırır.

Buna tamamen katılmıyorum. Sadece iki kod örneğinize bakmak bunu yanlış olarak adlandırıyor:

var a = F(G1(H1(b1), H2(b2)), G2(c1));

okumak için duyulur. "Okunabilirlik" bilgi yoğunluğu anlamına gelmez; "Okumak, anlamak ve bakımı kolay" demektir.

Bazen, kod basittir ve tek bir satır kullanmak mantıklı olur. Diğer zamanlarda, bunu yapmak sadece bir satırda daha fazla tıkanmanın ötesinde bariz bir fayda sağlaması için okumayı zorlaştırır.

Bununla birlikte, sizi "kazaları kolayca teşhis etmenin" kolaylaştığını, kodun korunmasının kolay olduğunu iddia ederek de çağırırdım. Çökmeyen kodun bakımı çok kolaydır. “Bakımı kolay” öncelikle, iyi bir otomatik test setiyle desteklenen okunması ve anlaşılması kolay olan kodla gerçekleştirilir.

Dolayısıyla, tek bir ifadeyi, kodunuzun sık sık çökmesi ve daha iyi hata ayıklama bilgilerine ihtiyaç duymanız nedeniyle çok değişkenli çok satırlı bir ifadeye dönüştürüyorsanız, bunu yapmayı bırakın ve kodu daha sağlam hale getirin. Hata ayıklaması kolay kod üzerinden hata ayıklama gerektirmeyen kod yazmayı tercih etmelisiniz.


37
Bunu F(G1(H1(b1), H2(b2)), G2(c1))okumak zor olsa da , bunun çok yoğun bir şekilde tıkanmakla alakası yok. (Söylemek istediğinizden emin değilsiniz, ancak bu şekilde yorumlanabilir.) Özellikle tek bir satırda üç ya da dört işlevi yerleştirmek, özellikle işlevlerin bazıları basit infix operatörleri ise, tamamen okunabilir olabilir. Buradaki problem tanımlayıcı olmayan isimlerdir, fakat daha fazla tanımlayıcı olmayan isimlerin sunulduğu çok satırlı versiyonda bu problem daha da kötüdür . Sadece kazan plakası eklemek neredeyse hiçbir zaman okunabilirliğe yardımcı olmaz.
leftaroundabout

23
@leftaroundabout: Bana göre zorluk, G13 parametre mi yoksa sadece 2 mi olduğu ve G2bunun için başka bir parametre olduğu açık değil F. Parantez ve parantez saymak zorundayım.
Matthieu M.,

4
@MatthieuM. Bu bir sorun olabilir, ancak eğer işlevler iyi biliniyorsa, ne kadar argüman alan çoğu zaman açıktır. Spesifik olarak, dediğim gibi, infix fonksiyonları için iki argüman aldıkları hemen bellidir . (Ayrıca, çoğu dil kullanmak parantez-küpe sözdizimi bu sorunu şiddetlendirir; Currying tercih ediyor bir dilde otomatik daha açık: F (G1 (H1 b1) (H2 b2)) (G2 c1).)
leftaroundabout

5
Şahsen, önceki yorumumda olduğu gibi etrafında şekillendirme olduğu sürece, daha kompakt formu tercih ediyorum, çünkü zihinsel olarak izini sürecek daha az devleti garanti ediyor - result_h1mevcut değilse tekrar kullanılamaz ve 4 değişken arasındaki tesisat açık.
Izkata

8
Hata ayıklaması kolay kodun genellikle hata ayıklamaya ihtiyaç duymayan kod olduğunu gördüm.
Rob K,

25

İlk örnek olan tek atama formu okunamıyor çünkü seçilen isimler tamamen anlamsız. Bu, sizin tarafınızdaki dahili bilgileri ifşa etmemeye çalışmanın bir ürünü olabilir, gerçek kodun bu konuda iyi olabileceğini söyleyemeyiz. Her neyse, genel olarak kolay anlaşılması için ödünç vermeyen çok düşük bilgi yoğunluğundan dolayı uzun zamandır.

İkinci örneğiniz saçma bir dereceye kadar yoğunlaştırılmıştır. İşlevlerin yararlı isimleri varsa, bu çok iyi ve okunabilir olabilir çünkü çok fazla bir şey yoktur, fakat diğer yönde kafa karıştırıcıdır.

Anlamlı isimler girdikten sonra, formlardan birinin doğal görünüp görünmediğine veya vurulacak altın bir orta olup olmadığına bakabilirsiniz .

Artık okunabilir kodlara sahip olduğunuza göre, çoğu hata açık olacak ve diğerleri en azından sizden saklanmakta zorlanıyor.


17

Her zaman olduğu gibi, okunabilirlik söz konusu olduğunda, başarısızlık aşırı uçlardadır . Sen alabilir herhangi , iyi programlama tavsiye dini kural haline getirmek ve tamamen okunmaz kodu üretmek için kullanır. Bu konuda bana inanmıyorsanız (bu iki kontrol IOCCC kazananlar borsanyi ve goren ve tamamen okunmaz kodu işlemek için fonksiyonları nasıl kullandıklarını farklı bakmak İpucu:. Borsanyi kullanan tam olarak bir fonksiyonu, Goren çok, çok daha ...)

Sizin durumunuzda, iki uç 1) sadece tek ifadeli ifadeleri kullanmak ve 2) her şeyi büyük, kısa ve karmaşık ifadelere katmak. Her iki uç noktaya da uygulanan yaklaşım kodunuzu okunamaz hale getirir.

Bir programcı olarak göreviniz dengeyi bozmak . Yazdığınız her ifade için, şu soruyu cevaplamak sizin görevinizdir: "Bu ifadeyi kavramak kolay mı ve fonksiyonumu okunabilir hale getirmeye yarar mı?"


Mesele şu ki, tek bir açıklamada neyin iyi olduğuna karar verebilecek tek bir ölçülebilir ifade karmaşıklığı yoktur. Örneğin çizgiyi alın:

double d = sqrt(square(x1 - x0) + square(y1 - y0));

Bu oldukça karmaşık bir ifadedir, ancak tuzlarına değecek herhangi bir programcı bunun ne yaptığını hemen anlayabilmelidir. Oldukça iyi bilinen bir kalıp. Bu nedenle, eşdeğerinden çok daha okunabilir

double dx = x1 - x0;
double dy = y1 - y0;
double dxSquare = square(dx);
double dySquare = square(dy);
double dSquare = dxSquare + dySquare;
double d = sqrt(dSquare);

bu da iyi bilinen deseni görünüşte anlamsız sayıda basit adımlara böler. Ancak, sorunuzun ifadesi

var a = F(G1(H1(b1), H2(b2)), G2(c1));

Uzaklık hesaplamasından daha az bir operasyon olsa bile , bana çok karmaşık geliyor . Tabii ki, bu konuda hiçbir şey bilmeden bana doğrudan bir sonucudur var F(), G1(), G2(), H1(), veya H2(). Onlar hakkında daha fazla şey bilsem farklı karar verebilirim. Ancak bu tam olarak sorun: Bir ifadenin tavsiye edilebilir karmaşıklığı, içeriğe ve ilgili işlemlere büyük ölçüde bağlıdır. Ve siz, bir programcı olarak, bu içeriğe bakması ve neyin tek bir ifadeye dahil edileceğine karar vermesi gereken kişi sizsiniz. Okunabilirliği önemsiyorsanız, bu sorumluluğu bir statik kurala aktaramazsınız.


14

@Dominique, sorunuzun analizinde "okunabilirlik" ve "sürdürülebilirliğin" iki ayrı şey olduğu yanılgısını yapıyorsunuz.

Korunabilen ancak okunamayan bir kod olması mümkün mü? Tersine, eğer kod son derece okunaklıysa, neden okunaklı olması nedeniyle neden anlaşılmaz hale gelsin? Bu faktörleri birbirlerine karşı oynayan, birini seçmek zorunda olan herhangi bir programcı duymadım!

İç değişkenli işlev çağrıları için ara değişkenlerin kullanılıp kullanılmayacağına karar verirken, verilen 3 değişken durumunda, 5 ayrı işlev çağrısı ve 3 derinlemesine iç içe geçmiş bazı çağrılar, bunu kesmek için en azından bazı ara değişkenleri kullanma eğilimindedir. senin yaptığın gibi.

Ama kesinlikle fonksiyon çağrıları hiçbir zaman iç içe geçmiş olmamalı diyecek kadar ileri gitmiyorum. Bu şartlarda bir yargı meselesi.

Aşağıdaki hususların karara vardığını söyleyebilirim:

  1. Çağrılan işlevler standart matematiksel işlemleri temsil ediyorsa, sonuçları öngörülemeyen ve zorunlu olarak okuyucu tarafından zihinsel olarak değerlendirilemeyen bazı belirsiz etki alanı mantığını temsil eden işlevlerden daha fazla iç içe geçebilirler.

  2. Tek parametreli bir fonksiyon, bir yuvaya (iç veya dış fonksiyon olarak) birden fazla parametreli fonksiyondan daha fazla katılabilir. Farklı aritelerin fonksiyonlarını farklı yuva seviyelerinde karıştırma, domuz kulağı gibi görünen bir kod bırakmaya eğilimlidir.

  3. Programcıların belirli bir şekilde ifade edildiğini görmeye alışkın olduğu bir işlevler yuvası - belki de standart bir uygulaması olan standart bir matematiksel tekniği veya denklemi temsil ettiğinden - orta değişkenlere ayrılıp ayrılmadığını okumak ve doğrulamak zor olabilir.

  4. Basit işlevselliği gerçekleştirir ve okunması zaten açıktır ve işlev çağrılarının küçük bir yuva sonra aşırı bozuldu ve atomize edilir, olma yeteneğine sahiptir hiç bozulmayan olandan okunması daha zordur.


3
+1 ila "Korunabilen ancak okunamayan bir kodun olması mümkün mü?". Benim de ilk fikrim buydu.
RonJohn,

4

Her ikisi de yetersizdir. Yorumlar düşünün.

// Calculating torque according to Newton/Dominique, 4th ed. pg 235
var a = F(G1(H1(b1), H2(b2)), G2(c1));

Veya genel olanlardan ziyade belirli fonksiyonlar:

var a = Torque_NewtonDominique(b1,b2,c1);

Hangi sonuçları heceleyeceğine karar verirken, her bir ifade için ayrı ayrı maliyet (referans - l-değeri - r-değeri), okunabilirlik ve riski göz önünde bulundurun.

Örneğin, basit birim / tür dönüşümleri kendi satırlarına taşımanın hiçbir katkısı yoktur, çünkü bunların okunması kolaydır ve başarısız olmaları olası değildir:

var radians = ExtractAngle(c1.Normalize())
var a = Torque(b1.ToNewton(),b2.ToMeters(),radians);

Çarpma dökümlerini analiz etme endişenizle ilgili olarak, giriş doğrulama genellikle çok daha önemlidir - gerçek çarpışma bu fonksiyonların içinde onları çağıran hattan ziyade gerçekleşmesi muhtemeldir ve olmasa bile, genellikle tam olarak nerede olduğunu söylemeniz gerekmez. işler patladı. İşlerin nerede parçalanmaya başladığını bilmek, nihayet nerede havaya uçtıklarını bilmekten daha önemlidir, bu da girdi geçerliliğinin ne yakaladığıdır.


Bir argüman geçmenin maliyeti: İki optimizasyon kuralı vardır. 1) Yapma. 2) (yalnızca uzmanlar için) Henüz yapma .
RubberDuck

1

Okunabilirlik, bakımın ana kısmıdır. Beni şüphe mi ediyorsun? Bilmediğiniz bir dilde (tercihen hem programlama dili hem de programcıların dili) büyük bir proje seçin ve nasıl yeniden düzenlemeye devam edeceğinizi görün ...

Okunabilirliği, 80 ile 90 arasında bir sürdürülebilirliğe sahip bir yere koyardım. Diğer yüzde 10-20 ise yeniden yapılanmaya ne kadar uygun olduğu.

Bununla birlikte, 2 fonksiyonda etkin bir şekilde son fonksiyonunuza (F) geçersiniz. Bu 2 değişken, diğer 3 değişken kullanılarak oluşturulur. B1, b2 ve c1'i F'ye geçirmekten daha iyi olurdu, eğer F zaten varsa, o zaman F için kompozisyonu yapan ve sonucu döndüren D'yi yarat. Bu noktada, D'ye iyi bir ad vermek meselesi ve hangi tarzı kullandığın önemli değil.

İlgili olmayan bir durumda, sayfadaki daha fazla mantığın okunabilirliğe yardımcı olduğunu söylüyorsunuz. Bu yanlış, metrik sayfa değil, yöntem ve LESS mantığı bir yöntem içeriyorsa, o kadar okunur.

Okunabilir, programcının kafasında mantığı (giriş, çıkış ve algoritma) tutabileceği anlamına gelir. Ne kadar fazla yaparsa, LESS bir programcının onu anlayabilmesine olanak sağlar. Siklomatik karmaşıklık üzerine okuyun.


1
Okunabilirlik hakkında söylediklerinize katılıyorum. Ama ayrı yöntemlerle içine mantıksal işlemi çatlama, kabul etmiyoruz mutlaka ayrı satırlara içine çatlama olmadığı kadar daha okunabilir hale getirir (her iki teknikleri edebilir , gereksiz, basit mantık az okunabilir hale ve tüm programın daha karmaşık hale) - şeyleri yöntemlerin içine çok fazla sokarsanız, assembly dili makrolarına öykünür ve bir bütün olarak nasıl bütünleştiklerini göremezsiniz. Ayrıca, bu ayrı yöntemde hala aynı sorunla karşılaşırsınız: çağrıları yuvalamak veya ara değişkenlere bölmek.
Steve

@Steve: Her zaman yapmak istemedim ama tek bir değer elde etmek için 5 satır kullanmayı düşünüyorsanız, bir fonksiyonun daha iyi olması için iyi bir şans var. Çok satırlı satırlar - karmaşık satırlar için: iyi bir isme sahip bir işlev ise her ikisi de eşit derecede işe yarar.
jmoreno

1

Ne olursa olsun C # veya C ++ kullanıyorsanız, hata ayıklama yapısında olduğunuz sürece, olası bir çözüm işlevleri kaplıyor

var a = F(G1(H1(b1), H2(b2)), G2(c1));

Oneline ifadesi yazabilir ve sorunun yalnızca yığın izlemesine bakarak sorunun nerede olduğuna dikkat çekebilirsiniz.

returnType F( params)
{
    returnType RealF( params);
}

Elbette, aynı işlevi aynı satırda birden çok defa çağırırsanız, hangi işlevi bilmezsiniz, ancak yine de tanımlayabilirsiniz:

  • İşlev parametrelerine bakmak
  • Parametreler aynıysa ve fonksiyonun yan etkileri yoksa, iki aynı çağrı 2 aynı çağrı vb. Olur.

Bu bir gümüş kurşun değil, yarı yolda bir o kadar da kötü değil.

Kaydırma işlev grubunun, kodun okunabilirliği için daha yararlı olabileceğinden bahsetmiyorum bile:

type CallingGBecauseFTheorem( T b1, C b2)
{
     return G1( H1( b1), H2( b2));
}

var a = F( CallingGBecauseFTheorem( b1,b2), G2( c1));

1

Bence, kendi kendini belgeleyen kod, dilden bağımsız olarak hem sürdürülebilirlik hem de okunabilirlik açısından daha iyidir.

Yukarıda verilen ifade yoğundur, ancak “öz dokümantasyon”:

double d = sqrt(square(x1 - x0) + square(y1 - y0));

Aşamalara bölündüğünde (test için daha kolay, kesinlikle) yukarıda belirtilen tüm bağlamı kaybeder:

double dx = x1 - x0;
double dy = y1 - y0;
double dxSquare = square(dx);
double dySquare = square(dy);
double dSquare = dxSquare + dySquare;
double d = sqrt(dSquare);

Ve tabii ki amaçlarını açıkça ifade eden değişken ve fonksiyon isimlerinin kullanılması paha biçilmezdir.

Kendini belgelemede bile "if" blokları iyi veya kötü olabilir. Bu kötü, çünkü ilk 2 koşulu kolayca üçüncüleri test etmeye zorlayamazsınız ... hepsi ilgisiz:

if (Bill is the boss) && (i == 3) && (the carnival is next weekend)

Bu, daha “toplu” bir anlam ifade ediyor ve test koşulları oluşturmak daha kolay:

if (iRowCount == 2) || (iRowCount == 50) || (iRowCount > 100)

Ve bu ifade, kendi kendini belgeleyen bir bakış açısıyla bakıldığında rastgele bir karakter dizisidir:

var a = F(G1(H1(b1), H2(b2)), G2(c1));

Yukarıdaki açıklamaya bakıldığında, eğer H1 ve H2 fonksiyonları hem tek bir "H" fonksiyonunda birleştirilmek yerine aynı "sistem durumu değişkenlerini" değiştirirse, sürdürülebilirlik hala büyük bir zorluktur, çünkü birisi sonunda H1'i değiştireceklerini bile düşünmeyecektir. H2 işlevi, H2'ye bakmak ve onu kırabilmek için işlev görür.

İyi kod tasarımının çok zor olduğuna inanıyorum, çünkü sistematik olarak tespit edilip uygulanabilecek zor ve hızlı kurallar yok.

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.