Hiçbir şeyi kırmamamı sağlamak için büyük bir yöntemi yeniden düzenlerken ne yardımcı olur?


10

Şu anda hiçbir birim testleri ile büyük bir kod tabanı bir kısmını yeniden düzenleme. Ben kaba bir şekilde kod refactor denedim, yani kodun ne yaptığını ve ne değişiklikler anlamını değiştirmek olmaz tahmin etmeye çalışarak, ama başarı olmadan: rastgele tüm kod tabanı çevresindeki sonları.

Yeniden düzenleme işleminin eski C # kodunu daha işlevsel bir stile taşımayı (eski kodun LINQ dahil .NET Framework 3 ve sonraki sürümlerinin hiçbir özelliğini kullanmadığını) ve kodun bunlardan yararlanabileceği jenerikler eklediğini unutmayın.

Maliyetleri göz önüne alındığında, resmi yöntemleri kullanamıyorum .

Öte yandan, maliyeti ne olursa olsun , en azından "Herhangi bir yeniden düzenlenmiş eski kod birim testleri ile gelecek" kuralına kesinlikle uyulması gerektiğini varsayıyorum. Sorun 500 LOC özel yöntem küçük bir bölümünü refactor zaman, birim testleri eklemek zor bir görev gibi görünüyor.

Belirli bir kod parçası için hangi birim testlerinin alakalı olduğunu bilmemde bana ne yardımcı olabilir? Kod statik analiz bir şekilde yararlı olacağını tahmin ediyorum, ama araç ve teknikler için kullanabilirsiniz:

  • Hangi birim testlerini oluşturmam gerektiğini tam olarak biliyorum,

  • Ve / veya yaptığım değişikliğin orijinal kodu bundan sonra farklı bir şekilde yürüttüğü şekilde etkileyip etkilemediğini biliyor musunuz?


Yazı birimi testlerinin bu projenin süresini uzatacağı gerekçeniz nedir? Birçok destekçi aynı fikirde değil, ama aynı zamanda bunları yazma yeteneğinize bağlı.
JeffO

Projenin toplam süresini artıracağını söylemiyorum. Ne demek istedim kısa vadede (yani kodu yeniden düzenlerken hemen şimdi harcamak zaman) artıracak olmasıdır .
Arseni Mourzenko

1
formal methods in software developmentZaten kullanmak istemezsiniz, çünkü yüklem mantığı kullanarak bir programın doğruluğunu kanıtlamak için kullanılır ve büyük bir kod tabanını yeniden düzenleme için uygulanabilirliği yoktur. Kod kanıtlamak için genellikle kullanılan resmi yöntemler tıbbi uygulamalar gibi alanlarda doğru çalışır. Haklısınız, bu yüzden sık kullanılmaz.
Mushy

ReSharper'daki refactor seçenekleri gibi iyi bir araç , böyle bir görevi çok daha kolay hale getirir. Bu gibi durumlarda o değer para.
billy.bob

1
Tam bir cevap değil, aptal bir teknik Diğer tüm yeniden düzenleme teknikleri beni başarısız olduğunda şaşırtıcı derecede etkili buluyorum: Yeni bir sınıf oluşturun, işlevi tam olarak orada kodla ayrı işlevlere ayırın, sadece 50 satırda bir kırın, üyeler arasında işlevler arasında paylaşılan yerliler, daha sonra bireysel işlevler kafama daha iyi uyuyor ve bana üyelerde hangi parçaların tüm mantık boyunca işlendiğini görme yeteneği veriyor. Bu bir son hedef değil, eski bir karmaşanın güvenle yeniden yapılandırılmaya hazır hale gelmesinin güvenli bir yolu.
Jimmy Hoffa

Yanıtlar:


12

Benzer zorluklar yaşadım. Eski Kod ile Çalışma kitabı büyük bir kaynaktır, ancak birim testlerinde ayakkabı boynuz işinizi desteklemek için olabilir bir varsayım var. Bazen bu mümkün değildir.

Arkeoloji çalışmamda (bunun gibi eski kodların bakımı için kullandığım terim), ana hatlarıyla belirttiğinize benzer bir yaklaşım izliyorum.

  • Rutinin şu anda ne yaptığını sağlam bir şekilde anlayarak başlayın.
  • Aynı zamanda, rutinin ne yapması gerektiğini belirleyin. Birçoğu bu mermi ve öncekinin aynı olduğunu düşünüyor, ancak ince bir fark var. Çoğu zaman, rutin yapması gereken şeyi yapsaydı, bakım değişiklikleri yapmazsınız.
  • Bazı örnekleri rutin olarak çalıştırın ve sınır durumlarına, ilgili hata yollarına ve ana hat yoluna ulaştığınızdan emin olun. Deneyimlerim, teminat hasarının (özellik ihlali) tam olarak aynı şekilde uygulanmayan sınır koşullarından kaynaklanmasıdır.
  • Bu örnek vakalardan sonra, kalıcı olması gerekmeyen, neyin kalıcı olduğunu belirleyin. Yine, bunun başka bir yerde teminat hasarına yol açan yan etkilerinin olduğunu buldum.

Bu noktada, o rutin tarafından neyin maruz kaldığı ve / veya manipüle edildiğinin bir aday listesine sahip olmalısınız. Bu manipülasyonların bazılarının yanlışlıkla olması muhtemeldir. Şimdi findstrve IDE'yi aday listesindeki öğelere hangi alanların başvurabileceğini anlamak için kullanıyorum . Bu referansların nasıl çalıştığını ve doğasının ne olduğunu anlamak için biraz zaman harcayacağım.

Son olarak, orijinal rutinin etkilerini anladığımı düşündüğümde kendimi kandırdığımda, değişiklikleri birer birer yapacağım ve değişikliğin beklediğim gibi çalıştığını doğrulamak için yukarıda özetlediğim analiz adımlarını tekrar çalıştıracağım çalışmak için. Özellikle, etkiyi doğrulamaya çalıştığımda bu benim üzerime patladığını fark ettiğim için birden fazla şeyi değiştirmekten kaçınmaya çalışıyorum. Bazen birden fazla değişiklikten kurtulabilirsiniz, ancak bir kerede bir rota izleyebilirsem, bu benim tercihimdir.

Kısacası benim yaklaşımım ortaya koyduğunuz şeye benziyor. Çok fazla hazırlık çalışması var; sonra ihtiyatlı, bireysel değişiklikler yapın; ve sonra doğrulayın, doğrulayın, doğrulayın.


2
Sadece "arkeoloji" nin kullanımı için +1. Bu etkinliği tanımlamak için kullandığım aynı terim ve bence bunu koymak için harika bir yol (ayrıca cevabın iyi olduğunu düşündüm - gerçekten o kadar sığ değilim)
Erik Dietrich

10

Hiçbir şeyi kırmamamı sağlamak için büyük bir yöntemi yeniden düzenlerken ne yardımcı olur?

Kısa cevap: küçük adımlar.

Sorun 500 LOC özel yöntem küçük bir bölümünü refactor zaman, birim testleri eklemek zor bir görev gibi görünüyor.

Şu adımları düşünün:

  1. Uygulamayı farklı (özel) bir işleve taşıyın ve çağrıyı devredin.

    // old:
    private int ugly500loc(int parameters) {
        // 500 LOC here
    }
    
    // new:    
    private int ugly500loc_old(int parameters) {
        // 500 LOC here
    }
    
    private void ugly500loc(int parameters) {
        return ugly500loc_old(parameters);
    }
    
  2. Tüm giriş ve çıkışlar için orijinal işlevinize günlük kodu ekleyin (günlük işleminin başarısız olmadığından emin olun).

    private void ugly500loc(int parameters) {
        static int call_count = 0;
        int current = ++call_count;
        save_to_file(current, parameters);
        int result = ugly500loc_old(parameters);
        save_to_file(current, result); // result, any exceptions, etc.
        return result;
    }
    

    Uygulamanızı çalıştırın ve bununla mümkün olan her şeyi yapın (geçerli kullanım, geçersiz kullanım, tipik kullanım, atipik kullanım, vb.).

  3. Artık max(call_count)testlerinizi yazmak için giriş ve çıkış setleriniz var ; Sahip olduğunuz tüm parametreleriniz / sonuç kümelerinizi yineleyen ve bunları bir döngü içinde yürüten tek bir test yazabilirsiniz . Ayrıca belirli bir kombinasyon çalıştıran bir adlandırma testi de yazabilirsiniz (belirli bir g / Ç kümesinden hızlı bir şekilde geçişi kontrol etmek için kullanılır).

  4. Taşı // 500 LOC heresenin geri ugly500locfonksiyonu (ve giriş işlevselliği çıkarın).

  5. Büyük işlevden işlevleri çıkarmaya başlayın (başka bir şey yapmayın, sadece işlevleri çıkarın) ve testleri çalıştırın. Bundan sonra, 500LOC yerine refactor için daha az fonksiyona sahip olmalısınız.

  6. Sonsuza dek mutlu yaşa.


3

Genellikle Birim Testleri gitmenin yoludur.

Akımın beklendiği gibi çalıştığını kanıtlayan gerekli testleri yapın. Acele etmeyin ve son test çıktıdan emin olmanızı sağlar.

Belirli bir kod parçası için hangi birim testlerinin alakalı olduğunu bilmemde bana ne yardımcı olabilir?

Bir kodu yeniden düzenleme sürecindesiniz, tam olarak ne yaptığını ve neyi etkilediğini bilmelisiniz. Yani temel olarak etkilenen tüm bölgeleri test etmeniz gerekiyor. Bu çok zaman alacaktır ... ancak bu herhangi bir yeniden düzenleme işleminin beklenen bir sonucudur.

O zaman herhangi bir sorun yaşamadan hepsini parçalayabilirsiniz.

AFAIK, bunun için kurşun geçirmez bir teknik yok ... sadece metodik (kendinizi rahat hissettiğiniz herhangi bir yöntemde), çok zaman ve çok sabırlı olmanız gerekiyor! :)

Şerefe ve iyi şanslar!

Alex


Kod kapsamı araçları burada önemlidir. Muayene yoluyla her yolu geniş ve karmaşık bir yöntemle kapsadığınızı doğrulamak zordur. KitchenSinkMethodTest01 () ... topluluğunu gösteren bir araç KitchenSinkMethodTest17 () 1-45, 48-220, 245-399 ve 488-500 satırlarını kapsar ancak arasındaki koda dokunmaz; yazmanız gereken ek testleri daha basit hale getirecektir.
Dan Is Fiddling Firelight tarafından
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.