Temiz kodun gerçek hayatta nasıl göründüğünü kavramada sorun


10

Şu anda Robert C. Martin tarafından yazılan "Clean Code: Agile Software Craftsmanship'in El Kitabı" üzerinden okuyorum ve çalışıyorum. Yazar, bir fonksiyonun sadece bir şeyi nasıl yapması gerektiği ve dolayısıyla nispeten kısa olması gerektiği hakkında konuşur. Özellikle Martin şöyle yazar:

Bu, if ifadeleri, else ifadeleri, while ifadeleri vb. İçindeki blokların bir satır uzunluğunda olması gerektiği anlamına gelir. Muhtemelen bu hat bir işlev çağrısı olmalıdır. Bu sadece çevreleme işlevini küçük tutmakla kalmaz, aynı zamanda blok içinde çağrılan işlev güzel bir açıklayıcı ada sahip olabileceğinden belgesel değer de ekler.

Bu aynı zamanda fonksiyonların iç içe geçmiş yapıları tutacak kadar büyük olmaması gerektiği anlamına gelir. Bu nedenle, bir işlevin girinti seviyesi bir veya ikiden fazla olmamalıdır. Bu, elbette, işlevlerin okunmasını ve anlaşılmasını kolaylaştırır

Bu mantıklı, ancak temiz kod olarak gördüğüm örneklerle çelişiyor gibi görünüyor. Örneğin aşağıdaki yöntemi kullanın:

    public static boolean millerRabinPrimeTest(final int n) {
        final int nMinus1 = n - 1;
        final int s = Integer.numberOfTrailingZeros(nMinus1);
        final int r = nMinus1 >> s;
        //r must be odd, it is not checked here
        int t = 1;
        if (n >= 2047) {
            t = 2;
        }
        if (n >= 1373653) {
            t = 3;
        }
        if (n >= 25326001) {
            t = 4;
        } // works up to 3.2 billion, int range stops at 2.7 so we are safe :-)
        BigInteger br = BigInteger.valueOf(r);
        BigInteger bn = BigInteger.valueOf(n);

        for (int i = 0; i < t; i++) {
            BigInteger a = BigInteger.valueOf(SmallPrimes.PRIMES[i]);
            BigInteger bPow = a.modPow(br, bn);
            int y = bPow.intValue();
            if ((1 != y) && (y != nMinus1)) {
                int j = 1;
                while ((j <= s - 1) && (nMinus1 != y)) {
                    long square = ((long) y) * y;
                    y = (int) (square % n);
                    if (1 == y) {
                        return false;
                    } // definitely composite
                    j++;
                }
                if (nMinus1 != y) {
                    return false;
                } // definitely composite
            }
        }
        return true; // definitely prime
    }
}

Bu kod şu adresteki Apache Commons kaynak kodu deposundan alınmıştır: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/primes/SmallPrimes.java

Yöntem bana çok okunabilir görünüyor. Bunun gibi algoritma uygulamaları için (Miller-Rabin Olasılıksal Öncelik Testi'nin uygulanması), kodu olduğu gibi tutmak ve yine de kitapta tanımlandığı gibi 'temiz' olduğunu düşünmek uygun mudur? Yoksa algoritmayı esasen "sadece tek bir şey" yapan işlevlere bir dizi çağrı yapmak için yöntemlerin çıkarılmasından bu kadar okunabilir bir şey mi? Yöntem çıkarmanın hızlı bir örneği, ilk üç if ifadesini aşağıdaki gibi bir işleve taşımak olabilir:

private static int getTValue(int n)
    {
        int t = 1;
        if (n >= 2047) {
            t = 2;
        }
        if (n >= 1373653) {
            t = 3;
        }
        if (n >= 25326001) {
            t = 4;    
        }
        return t;
    }

Not: Bu soru olası yinelenen (bu soru benim için de yararlı olsa da) farklıdır, çünkü Temiz Kod yazarının niyetini anlayıp anlamadığımı belirlemeye çalışıyorum ve işleri daha fazla yapmak için belirli bir örnek sağlıyorum Somut.


3
görebildiğim kadarıyla bu fonksiyon sadece bir şey yapıyor ... görebildiğim hiçbir yan etkisi yok. Temiz olmadığını düşündüren nedir? Bu fonksiyonun hangi kısmını daha temiz hale getirmek için başka bir fonksiyona koyulmaya değer?
Newtopian

14
Soru başlığınız "gerçek hayat" durumunu sorar ve sonra örneğiniz bana gerçek olmayan bir fonksiyonun mükemmel bir örneği gibi görünür (en azından uygulama veya web geliştiricilerinin% 99,9'u için). Elbette bu alanda çalışan sayı teorisyenleri, matematikçiler veya bilgisayar bilimcileri için gerçek bir işlev olabilir.
Doc Brown


2
Evet, benim için bu şu anda hesaplama cebirsel sayı teorisi alanında geliştirdiğim gibi gerçek bir hayat :)
1west

2
Açıkladığınız gibi getTFactor () muhtemelen refactor olacaktır.
user949300

Yanıtlar:


17

"Temiz kod" kendi içinde bir amaç değildir, bir amaç için bir araçtır. Daha büyük işlevleri daha küçük işlevlere dönüştürmenin ve kodu başka şekillerde temizlemenin temel amacı, kodu evrim geçirebilir ve bakımını sağlamaktır.

Bir ders kitabından "Miller-Rabin" prime testi gibi çok özel bir matematiksel algoritma seçerken, çoğu programcı bunu geliştirmek istemez. Standart hedefleri, kitabı metin kitabının sahte kodundan ortamlarının programlama diline doğru bir şekilde aktarmaktır. Bu amaçla, ders kitabını olabildiğince yakın takip etmenizi tavsiye ederim, bu da genellikle yeniden düzenleme yapmamak anlamına gelir.

Bununla birlikte, o alanda matematikçi olarak çalışan ve bu algoritma üzerinde çalışmaya ve onu değiştirmeye veya geliştirmeye çalışan biri için, IMHO bu işlevi daha küçük, iyi adlandırılmış olanlara böler veya adlandırılmış sabitler ile "sihirli sayılar" grubunu değiştirebilir koddaki değişiklikleri diğer kod türlerinde olduğu gibi kolaylaştırmaya yardımcı olur.


1
Tam da aradığım şey buydu. Geliştirdiğim alanda temiz kod uygulamalarını ne zaman kullanacağımı belirlerken sorun yaşıyordum. Cevabınız aradığım netliği sağlıyor. Teşekkürler!
1west
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.