Uzun yöntemler her zaman kötü mü? [kapalı]


64

Daha önce etrafa bakındığımda, uzun yöntemlerin kötü uygulama olduğu konusunda bazı yorumlar gördüm.

Uzun yöntemlerin kötü olduğuna her zaman katılıyorum (ve başkalarından görüş almak istiyorum) emin değilim.

Örneğin, nesneleri görünümüne göndermeden önce biraz işlemden geçiren bazı Django görünümlerine sahibim, uzun bir yöntem 350 satır kodlu. Kodumu yazdım, böylece parametrelerle başa çıkabiliyor - queryset'i sıralama / filtreleme, ardından bit bit sorgumun döndürdüğü nesneler üzerinde biraz işlem yapıyor.

Bu nedenle, işleme esas olarak koşullu toplamadır, veritabanında kolayca yapılamayacak kadar karmaşık kuralları vardır, bu yüzden ana döngü dışında bildirilen bazı değişkenler var, sonra döngü sırasında değiştirilebiliyorum.

variable_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

Bu yüzden teoriye göre, tüm kodu daha küçük yöntemlere ayırmalıyım, böylece görüntüleme yöntemini en fazla bir sayfa uzunluğunda olarak almalıyım.

Bununla birlikte, geçmişte çeşitli kod tabanları üzerinde çalışmış olsam da, bazen, en dıştaki yöntemi kafanızda tutarken sürekli olarak bir yöntemden diğerine atlamanız gerektiğinde, kodu daha az okunabilir kıldığını düşünüyorum.

İyi biçimlendirilmiş uzun bir yönteme sahip olmanın mantığını daha kolay görebiliyorum, çünkü içsel yöntemlerde saklanmıyor.

Kodu daha küçük yöntemlere ayırabilirim, ancak genellikle iki veya üç şey için kullanılan bir iç döngü vardır, bu yüzden daha karmaşık bir kodla sonuçlanır veya bir veya iki veya üç şeyi yapmayan yöntemler (alternatif olarak) Her görev için iç döngüleri tekrarlayabilirdim, ama sonra bir performans düşmesi olacak).

Öyleyse uzun yöntemlerin her zaman kötü olmadığı bir durum var mı? Yazma yöntemleri için, sadece bir yerde kullanılacağı zaman her zaman bir durum var mı?

GÜNCELLEME: Bu soruyu bir yıl önce sormuştum.

Bu yüzden, buradaki (karışık) cevaptan sonra kodu yeniden düzenledik, yöntemlere böldüm. Veritabanından karmaşık ilgili nesne kümelerini alan bir Django uygulamasıdır, bu nedenle test argümanı yok olmuştur (muhtemelen test senaryoları için ilgili nesneler oluşturmak muhtemelen yılın çoğunu almış olacaktır. kimse şikayet etmeden önce çalışma ortamı). Kodun bu bölümündeki hataları düzeltmek artık çok kolay, ancak çok büyük değil.

önce :

#comment 1 
bit of (uncomplicated) code 1a  
bit of code 2a

#comment 2 
bit of code 2a
bit of code 2b
bit of code 2c

#comment 3
bit of code 3

Şimdi:

method_call_1
method_call_2
method_call_3

def method_1 
    bit of (uncomplicated) code 1a  
    bit of code 2a

def method_2 
    bit of code 2a
    bit of code 2b
    bit of code 2c

def method_3
    bit of code 3

156
Bütün mutlaklar kötüdür. Her zaman.
Joachim Sauer

30
"Bunları tekrar kullanabilirseniz yöntemleri ayıkla" argümanını oldukça sık görüyorum (bu formda veya benzer formlarda), ancak satın almıyorum: yöntem birden fazla şey yapıyorsa, okunabilirlik için yöntemden ayıklamanız gerekir / Bu yeni yöntemler kodunuzdaki tek bir noktadan çağrılsa bile bakım kolaylığı.
Joachim Sauer

4
@gnat: wow, yapım aşamasında bir çeşit manuel işlem (önişlemci aracılığıyla) burada daha iyi bir çözüm olmaz mıydı?
Joachim Sauer

11
Bildiğim en iyi programcılardan biri, gerçekten bir ölçü istiyorsanız yerel değişkenlerin sayısının gerçek uzunluktan daha iyi olduğunu belirtti. Bağırsakların birkaç yüz satır uzunluğunda bir yöntem olduğu karmaşık bir yol iyileştirici üzerinde çalışıyordu, ancak tutulan devlet miktarı (yerel değişkenler) çok küçüktü.
Chuu,

2
Uzun yöntemler her zaman kötü değildir; ama onlar her zaman bakmak ve kendinize "bu kötü mü?" diye sormanız gereken bir şey.
Carson63000,

Yanıtlar:


80

Hayır, uzun yöntemler her zaman kötü değildir.

Code Complete kitabında , uzun yöntemlerin bazen daha hızlı ve daha kolay yazıldığı ve bakım sorunlarına yol açmadığı ölçülmektedir.

Aslında, gerçekten önemli olan, KURU kalmak ve endişelerin ayrılığına saygı duymaktır. Bazen, hesaplama yazması çok uzun, ancak gelecekte soruna neden olmayacak.

Bununla birlikte, kişisel deneyimime göre, çoğu uzun yöntem kaygının ayrılmaması yönündeki eğilimindedir. Aslında, uzun yöntemler kodda MAYIN yanlış olduğunu saptamanın kolay bir yoludur ve kod incelemesi yaparken burada özel dikkat gösterilmesi gerekir.

EDIT: Yorum yapılırken cevaba ilginç bir nokta eklerim. Aslında fonksiyon için karmaşıklık ölçümlerini de kontrol ederdim (NPATH, çevrimsel karmaşıklık veya daha iyi CRAP).

Aslında, bu ölçümleri uzun işlevler üzerinde kontrol etmemenizi, ancak bunlara otomatik araçlar (örneğin, java için kontrol stili gibi) üzerinde HERHANGİ FONKSİYON ile uyarı vermenizi öneririm.


41
+1: "Hayır, uzun yöntemler çok kötü değil" ama neredeyse her zaman kötüler
Binary Worrier

67
Uzun yöntem gövdeleri klasik bir kod kokusudur : kendi başına bir sorun değildir, ancak orada muhtemelen bir sorun olduğuna dair bir göstergedir .
Joachim Sauer

6
+1, yine de uzun yöntemin döngüsel karmaşıklığını kontrol etmenizi tavsiye ederim . Yüksek değerler, birim testinde etkili bir şekilde imkansız olan yöntemleri gösterir (ve uzun yöntemler, nadiren kontrol akış mantığından yoksundur).
Daniel B

11
Yorumları azaltmak için yöntem adları kullanıyorum. Bu bazen "getSelectedNodeWithChildren" gibi şeylere yol açar, ancak meslektaşım bana kodumun güzel bir şekilde okunabilir olduğunu söylemeye devam ediyor. Ayrıca kısaltmalardan kaçınmaya çalışıyorum, yazmak güzel, fakat okumak çok hoş değil.
K,

4
@ da_b0uncer Bu da benim takip ettiğim bir politika. Kod yazmak, yazmaktan daha zordur, bu nedenle kodu daha okunaklı hale getirmek için yazarken ekstra çaba harcamak işe yaramaz.
deadalnix

55

Buradaki odağın çoğu her zaman kelimenin etrafında görünüyor . Evet, mutlaklar kötüdür ve yazılım mühendisliği neredeyse bilim kadar sanattır ve hepsi ... ama şunu söylemeliyim ki, verdiğiniz örnek için, yöntem bölünmüş olsaydı daha iyi olurdu yukarı. Bunlar genellikle yönteminizi bölmeyi haklı göstermek için kullanacağım argümanlar:

Okunabilirlik: Diğerlerinden emin değilim, ancak hızlı bir şekilde 350 satırlık kodu okuyamıyorum. Benim ise Evet, kendi kodu ve bu konuda birçok varsayımlar yapabilir, ben olabilir çok hızlı içinden yağsız ama bunun konuyla yanında bulunuyor. Her biri açıklayıcı bir adla yapılan 10 çağrıdan oluşuyorsa, bu yöntemin okunmasının ne kadar kolay olacağını düşünün. Bunu yaparak, kodda bir katman oluşturdunuz ve üst düzey yöntem, okuyucunun olup bitenlerle ilgili kısa, tatlı bir taslak vermesini sağlıyor.

Düzenleme - farklı bir ışığa koymak gerekirse, bunun böyle olduğunu düşünün: bu yöntemi yeni bir ekip üyesine nasıl açıklarsınız? Şüphesiz sahip bazı satırlar boyunca özetleyebiliriz yapıyı "eh, vb A, sonra B, ardından bazen C yapıyor başlar". Kısa bir "genel bakış" yöntemine sahip olmak diğer yöntemleri çağırmak bu yapıyı belirginleştirir. Faydası olmayan 350 kod satırı bulmak son derece nadirdir; İnsan beyninin 100'lerce maddelik listelerle uğraşması kastedilmiyor, onları gruplandırıyoruz.

Yeniden kullanılabilirlik: Uzun yöntemler düşük uyum gösterme eğilimindedir - genellikle birden fazla şey yaparlar. Düşük uyum, yeniden kullanım düşmanıdır; Birden fazla görevi tek bir yöntemde birleştirirseniz, olması gerekenden daha az yerde tekrar kullanılmaya başlanır.

Test edilebilirlik ve uyum: Yukarıdaki yorumda siklomatik karmaşıklıktan bahsettim - bu, yönteminizin ne kadar karmaşık olduğu konusunda oldukça iyi bir ölçü. Girişlere bağlı olarak, kodunuzdaki benzersiz yol sayısının alt sınırını temsil eder (düzenleme: MichaelT'nin yorumuna göre düzeltilmiş). Aynı zamanda, yönteminizi doğru bir şekilde test etmek için, en azından döngüsel karmaşıklık numaranız kadar test vakasına sahip olmanız gerektiği anlamına gelir. Ne yazık ki, birbirine gerçekten bağımlı olmayan kod parçalarını bir araya getirdiğinizde, bu bağımlılık eksikliğinden emin olmanın hiçbir yolu yoktur ve karmaşıklık birlikte çoğalabilir. Bu önlemi, yapmaya çalıştığınız farklı şeylerin bir göstergesi olarak düşünebilirsiniz. Çok yüksekse, bölme ve ele geçirme zamanı.

Yeniden düzenleme ve yapı: Uzun yöntemler genellikle bazı yapıların kodda eksik olduğuna işaret eder. Genellikle, geliştirici bu yöntemin farklı bölümleri arasındaki ortak noktaların ne olduğunu ve aralarında bir çizginin nerede çizilebileceğini çözemedi. Uzun bir yöntemin bir sorun olduğunun farkına varmak ve onu daha küçük yöntemlere ayırmaya çalışmak, aslında her şey için daha iyi bir yapı tanımlamak için daha uzun bir yoldaki ilk adımdır. Belki bir veya iki sınıf oluşturmanız gerekir; sonunda daha karmaşık olması gerekmeyecek!

Ayrıca, bu durumda, uzun bir yönteme sahip olmanın bahanesinin "... ana döngü dışında bildirilen bazı değişkenler sonra döngü sırasında değiştirildiğini" düşünüyorum. Python konusunda uzman değilim, ancak bu sorunun referans olarak geçen bir yolla önemsiz olarak çözülebileceğinden oldukça eminim.


13
Sorunun her zaman parçasını reddetmek ve ete odaklanmak için +1: Uzun yöntemlerin kötü olup olmadığı. Bence OP, senaryosu son derece önemli bir durum gibi gözüküyor, ancak genelde insanların alışılmadık senaryo için gerekli kötü uygulamalarını açıkladığını duyduğumda, sadece iyi uygulamaları kullanmak için çok uğraşmadıkları için. Nadir görülen senaryolar gerçekten çok nadirdir, uzun yöntemler ne yazık ki oldukça yaygındır.
Jimmy Hoffa

2
Yukarıdaki listeye bakarak TAMAM: geçmiş deneyimlerden söyleyebildiğim okunabilirlik, yöntem hakkında daha fazla yorum içeren ve iyi biçimlendirilmiş, yöntemden yöntemlere kod atlamak yerine, yöntemden yöntemlere geçerek çoğaltılmış olduğunu söyleyebilirim. Kodun bölümlerinin yeniden kullanılmasını beklemiyorum. Kodun tekrar kullanımının çoğu, şu anda mirastan elde edilir.
wobbily_col

1
@ wobbily_col BTW, daha kısa yöntemlere sahip olma gerekçesinden geçen iyi yazılmış bir metin arıyorsanız , açıklamada oldukça iyi bir iş çıkaran ilk birkaç Temiz Kod bölümünü okuyun .
Daniel B

5
@ wobbily_col Kodun birçok yöntemle anlaşılması için çok fazla zıplamak zorunda kalmanın kafa karıştırıcı olduğunu söylüyorsunuz, buradaki eksik noktanın isimlendirmenin önemi üzerinde olduğunu düşünüyorum. Bir yöntem iyi adlandırılırsa, ne yaptığını bulmak için buna bakmanıza gerek yoktur, çağrı yöntemi, ne tür yöntemler kullandığınızı, örneğin hiç kullandığınızı someVar.toString()ve hissettirdiğinizin hiçbir bilgisi olmadan, tamamen anlaşılabilir olmalıdır. Ne yaptığını bilmek için toString kodunu görmeniz gerekiyordu? İyi bir adlandırma yöntemi yüzünden hemen okudunuz.
Jimmy Hoffa

4
Bir yandan notta, n parametresi gerektiren bir yönteme sahip olmak aynı zamanda bir kod kokusudur ve yöntemin birden fazla şey yapabileceğini gösterir. Aynı adı vermek zor bir yöntem için de geçerli. Ve eğer bütün bu parametrelere gerçekten ihtiyaç duyuyorsa, bunlar genellikle kendi sınıflarına dahil edilebilecek olan ve daha büyük bir konseptin parçası. Elbette, bu kuralı kullanmamaktan daha iyi bir örnek bulabiliriz - demek istediğim, eğer böyle bir yöntem görürseniz, onu derinlemesine araştırmak, muhtemelen bir şekilde kötü olmaktır.
KL

28

Uzun yöntemler her zaman kötüdür, ancak bazen alternatiflerden daha iyidir.


5
bir açıklama yapılmadığında, bir başkasının aksi bir görüş bildirmesi durumunda bu cevap yararsız olabilir. Örneğin, birisi "Uzun yöntemler hiçbir zaman kötü değildir, ancak bazen alternatiflerden daha kötüdür" gibi bir iddia yayınlarsa . , bu cevap okuyucunun iki karşıt görüşü seçmesine nasıl yardımcı olur? Düşünün düzenlemek daha iyi bir şekle ing
tatarcık

9

Uzun yöntemler kod kokusudur . Genellikle bir şeyin yanlış olduğunu gösterirler, ancak bu hızlı ve zor bir kural değildir. Genellikle, haklı oldukları davalar (bulduğunuz gibi) birçok devlet ve oldukça karmaşık iş kurallarını içerir.

Diğer sorunuzla ilgili olarak, yalnızca bir kez çağrılsalar bile, mantık parçalarını ayrı yöntemlere ayırmak sıklıkla yararlı olur. Üst düzey mantığı görmeyi kolaylaştırır ve küçük bir temizleyiciyle istisna yapabilir. İşlem durumunu temsil etmek için yirmi parametreye geçmek zorunda olmadığınız sürece!


7

Uzun yöntemler her zaman kötü değildir. Genellikle bir sorun olabileceğinin bir işaretidir.

Üzerinde çalıştığım sistemde 10,000'den fazla hattan oluşan yarım düzine yöntemimiz var. Biri şu anda 54,830 satır uzunluğunda. Ve tamam.

Gülünç derecede uzun olan bu fonksiyonlar çok basit ve otomatikleştirilmiş. Bu büyük 54.830 uzunluğundaki canavar, 1 Ocak 1962 - 10 Ocak 2012 tarihleri ​​arasında günlük kutup hareketi verilerini içerir (son sürümümüz). Ayrıca, kullanıcıların otomatik oluşturulmuş dosyayı güncelleyebilecekleri bir prosedür yayınlarız. Bu kaynak dosya, http://data.iers.org/products/214/14443/orig/eopc04_08_IAU2000.62-now adresindeki kutupsal hareket verilerini içerir , otomatik olarak C ++ 'a çevrilir.

Bu siteyi anında okumak güvenli bir kurulumda mümkün değildir. Dış dünyayla bağlantısı yok. Web sitesini yerel bir kopya olarak indirmek ve C ++ 'da ayrıştırmak da bir seçenek değildir; ayrıştırma yavaş ve bu hızlı olmalı. İndirme, C ++ 'a otomatik çeviri ve derleme: Şimdi hızlı olan bir şeye sahipsiniz. (En iyi duruma getirilmiş derleme yapmayın. En iyi duruma getirilmiş bir derleyicinin 50.000 satırlık son derece basit bir düz satır kodunu derlemesi ne kadar uzun sürer. Bilgisayarımın en iyi duruma getirilmiş bir dosyayı derlemesi yarım saatten fazla sürer. En iyi duruma getirecek bir şey yok.


6
"birbiri ardına bir atama ifadesi" ... Ben buna "veri dosyası" derdim. Neden kod?
Joachim Sauer

3
@ JoachimSauer - Bir Monte Carlo kurulumunda çalışma zamanında büyük bir veri dosyasını ayrıştırmak kötü bir fikirdir. Çok, çok kötü bir fikir.
David Hammen

4
@DavidHammen: O zaman ilk çalıştırma sırasında yapın, tıpkı bağlayıcı / yükleyicinizi yapmaya zorladığınız gibi. Veya veri dosyasını C kodu yerine bir başlık dosyasına C yapısı olarak yazınız. En azından yükleyici bir veri bloğu olarak yüklenir.
Javier,

3
@Javier: Başlatma zamanında bile, en azından bir Monte Carlo kurulumunda çok kötü bir fikir olabilir. Başlaması dakikalar süren, ancak koşması sadece birkaç saniye süren bir simülasyon, gecede onbinlerce koşuya ulaşma tanesine karşı çıkıyor. Zaman başlatma görevlerini derlemek için anahtar başlatma zamanı görevlerini değiştirmek bu sorunu düzeltir. Derlenmiş veri yapısı yaklaşımı dahil olmak üzere birkaç teknik denedik. Sadece işe yaramıyor veya bazı durumlarda iş yapmak çok zor olacak (örneğin, büyük bir yerçekimi modeli). Düz hat kodu yaklaşımının otomatik olarak oluşturulması, doğrulanması kolaydır. Sadece çirkin kod.
David Hammen

7
+1 ilginç hikaye. Oluşturulan kod gerçekten kaynak kod değil elbette bu kuralın 'ihlal edilmediğini' iddia edebilir. bunlardan biri kod oluşturucunun kendisinin hoş kısa yöntemleri olduğunu varsayar
jk.

7

Diyelim ki uzun bir yöntemi kırmanın iyi ve kötü yolları var. “Kafanızdaki en dış metodu [[]] saklamak”, en uygun şekilde ayırmadığınız ya da alt metotlarınızın kötü adlandırıldığının bir işaretidir. Teoride, uzun bir yöntemin daha iyi olduğu durumlar vardır. Uygulamada, oldukça nadirdir. Daha kısa bir yöntemi nasıl okunaklı hale getireceğinizi bulamıyorsanız, kodunuzu gözden geçirmesini isteyin ve onlardan özellikle yöntemleri kısaltma hakkında fikirlerini isteyin.

Bir performans düşüşüne neden olan çoklu döngülere gelince, bunu ölçmeden bilmenin yolu yoktur. Birden fazla küçük döngü, ihtiyaç duyduğu her şeyin önbellekte kalabileceği anlamına geldiğinde, çok daha hızlı olabilir. Performans hit olsa bile, okunabilirlik lehine genellikle ihmal edilebilir.

Okumak daha zor olsa bile , genellikle uzun yöntemlerin yazmanın daha kolay olduğunu söyleyeceğim . Bu yüzden kimse onlardan hoşlanmasa da çoğalırlar. Kontrol etmeden önce yeniden baştan başa planlama konusunda yanlış bir şey yoktur.


1
“Kontrol etmeden önce baştan başa refactor'a planlamada yanlış bir şey yoktur.” Bunun için +1. Günümüzde çoğu IDE, bunu son derece kolaylaştıran yeniden düzenleyici araçlara sahiptir. Fakat bir şeyleri var olmayan işlevlere devrettiğiniz ve daha sonra yöntemleri doldurduğunuzda tersine bir yöntem var, ama denedim kadar kodlama yapmadım.
Tjaart

'' En uçtaki yöntemi '' sahip olmak '' için +1 ', onu en uygun şekilde
Michael Shaw,

4

Uzun yöntemler daha hesaplamalı ve alan açısından verimli olabilir, mantığı görmek ve hata ayıklamak daha kolay olabilir. Ancak bu kurallar, yalnızca bir programcının bu koda dokunduğunda gerçekten geçerlidir. Kod, eğer atomik değilse, bir sonraki kişinin sıfırdan başlaması ve ardından hata ayıklaması ve test edilmesi, bilinen herhangi bir iyi kodu kullanmadığı için alacağı test olacak şekilde genişletmek için bir acı olacak.


34
Her zaman en az iki programcı vardır: "siz" ve "siz, bundan üç hafta sonra".
Joachim Sauer

3

İşlevsel Ayrıştırma dediğimiz bir şey var, mümkün olduğunca uzun yöntemlerinizi daha küçük yöntemlere bölmek. Yönteminizin sıralama / filtreleme içerdiğinden bahsettiğiniz gibi, o zaman bu görevler için ayrı yöntem veya işlevlere sahip olmalısınız.

Tam olarak, yönteminiz yalnızca 1 görevi yerine getirmeye odaklanmalıdır.

Ve eğer başka bir yöntemi dor olarak çağırmak gerekirse, o zaman bunu başka türlü zaten yazdığınızla devam edin. Ayrıca okunabilirlik bataklıkları için yorum ekleyebilirsiniz. Geleneksel olarak, programcılar yöntem açıklamaları için çok satırlı yorumlar (/ ** / C, C ++, C # ve Java) kullanır ve tek satırlı yorumlar kullanır (//, C, C ++, C # ve Java). Daha fazla kod okunabilmesi için de iyi dokümantasyon araçları mevcuttur (örn. JavaDoc ). Bir .NET geliştiricisiyseniz , XML tabanlı yorumlara da bakabilirsiniz .

Döngüler program performansını etkiler ve düzgün kullanılmazsa uygulama ek yüküne neden olabilir. Fikir, algoritmanızı iç içe döngüleri mümkün olduğunca az kullanacak şekilde tasarlamaktır.


"Bir işlev BİR ŞEY yapmalı" olarak da bilinir.
Lorddev

3

Uzun fonksiyonlar yazmak tamamen sorun değil. Ancak, gerçekten ihtiyacınız olup olmadığına bağlı olarak değişir. Örneğin, en iyi algoritmalardan bazıları bir dilim olduğunda en iyi şekilde ifade edilir. Öte yandan, nesne yönelimli programlardaki rutinlerin büyük bir yüzdesi erişimci rutinleri olacak ve bu da çok kısa olacaktır. Koşullar tablo tabanlı yöntemlerle optimize edilebilirse, uzun anahtarlama durumlarına sahip olan uzun işleme rutinlerinden bazıları.

Code Complete 2'de rutinlerin uzunluğu hakkında mükemmel bir kısa tartışma var.

Teorik olarak en iyi 497 maksimum uzunluk, genellikle 66 ila 132 satırlık bir veya iki program listesi sayfası olarak tanımlanmaktadır. Modern programlar, birkaç uzun rutinde karıştığı hacimli aşırı kısa rutinlere sahip olma eğilimindedir.

Onlarca yıllık kanıtlar, bu tür rutinlerin kısa rutinler yerine hataya meyilli olmadığını söylüyor. Yuvalama derinliği, değişken sayısı ve diğer karmaşıklıkla ilgili hususlar gibi sorunların, uzunluk uygulamak yerine, rutin uzunluğu 535'i belirlemesine izin verin.

Yaklaşık 200 satırdan daha uzun rutinler yazmak istiyorsanız, dikkatli olun. Maliyetin düşürüldüğü, hata oranlarının azaldığı veya her ikisinin de 200 satırdan daha büyük boyutlar arasında ayrım yapan daha büyük rutinleri olduğunu bildiren çalışmaların hiçbiri ve 200 satırlık kodu geçerken daha fazla anlaşılabilirlik sınırına girme zorunluluğunuz var. 536 kısıtlama başına.


2

Neredeyse her zaman yanlış olduğu bir başka oy. Yine de doğru cevabın verildiği iki temel durum buldum:

1) Temel olarak, sadece bir sürü başka yöntem çağıran ve gerçek bir iş yapmayan bir yöntem. 50 adım atması gereken bir işleminiz var, içinde 50 çağrı bulunan bir yöntem elde edersiniz. Bunu parçalamaya çalışmakla kazanılacak hiçbir şey yoktur.

2) Dağıtım şirketleri. OOP tasarımı bu tür yöntemlerin çoğundan kurtuldu, ancak gelen veri kaynakları, doğası gereği sadece veri ve dolayısıyla OOP ilkelerini izleyemiyor. Verileri işleyen kodda bir çeşit dağıtım programı yordamına sahip olmak sıra dışı bir durum değildir.

Ayrıca, otomatik olarak üretilen şeylerle uğraşırken soruyu dikkate almamamız gerektiğini de söyleyebilirim. Kimse otomatikleştirilmiş kodun ne yaptığını anlamaya çalışmıyor, bir insanın anlaması kolay olup olmadığı tek bir önemli değil.


1
50 aşamalı işlem muhtemelen birkaç kovaya özetlenebilir. Adım 1 - 9 parametre kontrolleridir, bu nedenle parametre kontrolü olarak adlandırılan yeni bir yöntem oluşturun. (Bunun mümkün olmadığı bazı örnekler olduğuna eminim. Birini görmek isterdim).
altmış ayak parmakları

@sixtyfootersdude: Tabii ki, onu parçalayabilirsin. İmkansız olduğunu söylemedim, ayrılarak kazanılacak bir şey olmadığını söyledim. 50 adım olmasa da böyle bir şeye çarptım: Bir oyun dünyası yaratmak. # 1 boş dünyayı yarattı, # 2 araziyi yarattı ve daha sonra bir şekilde ya da başka şekilde masaj yaptıktan sonra bir sürü adım attı.
Loren Pechtel

& sixtyfootersdude: Hiç görmediğiniz kodları bilmeniz ve onu nasıl iyileştireceğiniz şaşırtıcı.
gnasher729

2

Verdiğiniz örneği ele almak istedim:

Örneğin, nesneleri görünümüne göndermeden önce biraz işlemden geçiren bazı Django görünümlerine sahibim, uzun bir yöntem 350 satır kodlu. Kodumu paramaterlerle ilgilenecek şekilde yazdım - queryset'i sıralama / filtreleme, daha sonra bit bit sorgumun döndürdüğü nesneler üzerinde biraz işlem yapıyor.

Şirketimde en büyük projemiz Django'da yapıldı ve uzun görüş fonksiyonlarımız da var (çoğu 350 çizgiden fazla). Bizimkinin o kadar uzun olması gerekmediğini ve bizi incittiğini savunuyorum.

Bu görünüm işlevleri, modele, yardımcı sınıflara veya yardımcı işlevlere ayıklanması gereken çok sayıda gevşek ilişkili iş yapıyor. Ayrıca, farklı şeyler yapmak için görüşleri yeniden kullanmaktayız, bunun yerine daha uyumlu görüşlere bölünmesi gerekir.

Görüşlerinin benzer özelliklere sahip olduğundan şüpheleniyorum. Benim durumumda bunun sorunlara neden olduğunu biliyorum ve değişiklik yapmaya çalışıyorum. Sorun yarattığı konusunda hemfikir değilseniz, düzeltmenize gerek yoktur.


2

Biri bundan daha önce bahsetti mi bilmiyorum ama uzun yöntemlerin kötü olmasının sebeplerinden biri, genellikle birkaç farklı soyutlama seviyesi içermeleridir. Döngü değişkenleriniz ve oluyor her türlü şeyiniz var. Hayali işlevi göz önünde bulundurun:

function nextSlide() {
  var content = getNextSlideContent();
  hideCurrentSlide();
  var newSlide = createSlide(content);
  setNextSlide(newSlide);
  showNextSlide();
}

Bu fonksiyondaki tüm animasyonu, hesaplamayı, veri erişimini vb. Yapıyor olsaydınız, bir karışıklık olurdu. NextSlide () işlevi tutarlı bir soyutlama katmanını (slayt durum sistemi) tutar ve diğerlerini yok sayar. Bu kodu okunabilir hale getirir.

Ne yaptıklarını görmek için sürekli olarak daha küçük yöntemlere adım atmanız gerekiyorsa, işlevi bölme alıştırması başarısız olmuştur. Okuduğunuz kodun çocuk yöntemlerinde açık şeyler yapmaması, çocuk yöntemlerinin kötü bir fikir olduğu anlamına gelmez, sadece yanlış yapıldığı anlamına gelmez.

Yöntemler yarattığımda, genellikle onları bir çeşit bölme ve fethetme stratejisi olarak daha küçük yöntemlere böldüm. Gibi bir yöntem

   if (hasMoreRecords()) { ... }

kesinlikle daha okunabilir

if (file.isOpen() && i < recordLimit && currentRecord != null) { ... } 

Sağ?

Mutlak ifadelerin kötü olduğu konusunda hemfikirim, hem de genellikle uzun bir yöntemin kötü olduğu konusunda hemfikirim.


1

Gerçek hikaye. Bir zamanlar iki binin üzerinde bir yöntemle karşılaştım. Yöntem, bu bölgelerde ne yaptığını tanımlayan bölgelere sahipti. Bir bölgeyi okuduktan sonra, bölge adına göre adlandırarak otomatik bir çıkartma yöntemi yapmaya karar verdim. Yaptığım zaman, yöntem hiçbir şey değildi, ancak her biri yaklaşık elli satırlık 40 yöntem çağrısı vardı ve hepsi aynı şekilde çalıştı.

Çok büyük olan özneldir. Bazen, bir yöntem şu anda olduğundan daha fazla bozulmayabilir. Bir kitap yazmak gibi. Çoğu insan uzun paragrafların genellikle bölünmesi gerektiği konusunda hemfikirdir. Ancak bazen, yalnızca bir fikir vardır ve bunu bölmek, bu paragrafın uzunluğunun neden olacağından daha fazla karışıklığa neden olur.


0

Bir yöntemin amacı kod yetersizliğini azaltmaya yardımcı olmaktır. Bir yöntemin sorumlu olduğu belirli bir işlevi olmalıdır. Kodun birçok yerinde yeniden şekillendirilmesi durumunda, yazılımın adreslenmesi için tasarlanan teknik özellikler değişirse, beklenmeyen sonuçlara sahip olma riskiyle karşı karşıya kalırsınız.

Bir 350 hattın olması bir yöntemin, gerçekleştirdiği görevlerin çoğunun başka bir yerde çoğaltıldığını, çünkü özel bir görevi yürütmek için bu kadar büyük miktarda kod gerektirmesinin olağandışı olduğunu gösteriyor.


Kodu azaltmaya yardımcı olun ne ?
Avner Shahar-Kashtan

@ AvnerShahar-Kashtan, muhtemelen "çoğaltma" :-) anlamı
Péter Török

0

Kötü bir uygulama olan uzun yöntemler aslında onları daha da kötü yapmaz.

Demek istediğim, örneğini yeniden yapılandırma fiili:

varaible_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

için

Status status = new Status();
status.variable1 = 0;
status.variable2 = 0;
for object in queryset :
     if object.condition_condition_a and status.variable2 > 0 :
     status.variable1 += 1
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

ve sonra

class Status {
    variable1 = 0;
    variable2 = 0;

    void update(object) {
        if object.condition_condition_a and variable2 > 0 {
            variable1 += 1
        }
    }
};

Status status = new Status();
for object in queryset :
     status.update(object);
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

Artık sadece çok daha kısa bir metoda değil, daha kullanışlı ve anlaşılabilir bir yola çıkma yolundasınız.


0

Metodun çok uzun olduğu gerçeğinin kontrol edilmesi gereken bir şey olduğunu düşünüyorum, ancak kesinlikle anlık bir anti-patern değil. Büyük yöntemlerde aranacak en büyük şey çok fazla yuvalamadır. Eğer varsa

foreach(var x in y)
{
    //do ALL the things
    //....
}

ve döngünün gövdesi aşırı derecede lokalize değildir (yani 4 parametreden daha azını gönderebilirsiniz), o zaman dönüştürmek daha iyi olur:

foreach(var x in y)
{
    DoAllTheThings(x);
}
...
void DoAllTheThings(object x)
{
    //do ALL the things
    //....
}

Bu da, bir işlevin uzunluğunu büyük ölçüde azaltabilir. Ayrıca, işlevde yinelenen kodu aradığınızdan ve bunu ayrı bir işleve taşıdığınızdan emin olun.

Sonunda, bazı yöntemler sadece uzun ve karmaşık ve yapabileceğiniz hiçbir şey yok. Bazı sorunların, kodlaması kolay olmayan, kendilerini ödünç vermeyen çözümlere ihtiyacı vardır. Örneğin, çok karmaşık bir dilbilgisine göre ayrıştırmak, daha da kötüleşmeden yapamayacağınız çok uzun yöntemler yapabilir.


0

Gerçek şu ki, bağlı. Belirtildiği gibi, kod kaygıları ayırmaz ve her şeyi tek bir yöntemle yapmaya çalışırsa, sorun olur. Kodu birden fazla modüle ayırmak, kod okumayı ve ayrıca kod yazmayı (birden fazla programcı tarafından) kolaylaştırır. Kaynak dosya başına bir modüle (sınıf) bağlı kalmak, başlamak için iyi bir fikirdir.

İkincisi, işlevler / prosedürler söz konusu olduğunda:

void setDataValueAndCheckForRange(Data *data) {/*code*/} 

yalnızca "Veri" aralığını denetlerse iyi bir yöntemdir. Aynı aralık birden fazla fonksiyon için geçerli olduğunda bir BAD yöntemidir (hatalı kod örneği):

void setDataValueAndCheckForRange(Data *data){ /*code */}
void addDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void subDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void mulDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}

Bu, aşağıdakilere göre düzeltilmelidir:

bool isWithinRange(Data *d){ /*code*/ }
void setDataValue(Data *d) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void addDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void subDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void mulDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 

Kodu mümkün olduğu kadar yeniden kullanın. Programınızın her bir işlevi de BASİT (mümkün olması kolay değil) olduğunda bu mümkün.

QUOTE: MOUNTAIN, küçük toprak taneciklerinden oluşur. Okyanus minik su damlalarından oluşuyor .. (- Sivananda)


0

Uzun yöntemler, zorunlu dillerdeki ifadeleri, yan etkileri ve değişkenliği destekleyen "kötü" olma eğilimindedir, çünkü bu özellikler karmaşıklığı ve dolayısıyla hataları arttırır.

İfadeleri, saflığı ve değişmezliği destekleyen işlevsel programlama dillerinde, endişelenmek için daha az neden vardır.

Hem işlevsel hem de zorunlu dillerde, yeniden kullanılabilir kod parçalarını ortak en üst düzey yordamlara ayırmak her zaman en iyisidir, ancak iç içe işlevlerle vb. Sözcüksel kapsamlamayı destekleyen işlevsel dillerde, aslında en üstteki alt yordamları gizlemek daha iyidir. Seviye işlevi (yöntem) onları diğer üst düzey işlevlere bölmekten çok.


İşlevsel dillerde ise, uzun yöntemler çok daha az yaygındır.
Ocak’ta
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.