Hangi durumlarda daha az kod daha iyi değildir? [kapalı]


55

Son zamanlarda işyerinde bazı kodları değiştirdim ve iyi bir iş çıkardığımı düşündüm. 980 kod satırını 450'ye düşürdüm ve ders sayısını yarıya indirdim.

Bunu meslektaşlarıma gösterirken, bazıları bunun bir gelişme olduğu konusunda hemfikir değildi.

Dediler ki - "daha az kod satırı mutlaka daha iyi değil"

İnsanların gerçekten uzun satırlar yazdıkları ve / veya her şeyi birkaç satırdan tasarruf etmek için tek bir yöntemle koydukları aşırı durumlar olabileceğini görebiliyorum, ama yaptığım bu değildi. Kod bence iyi yapılandırılmış ve boyutunun yarısı olduğu için anlamak / sürdürmek daha basit.

Neden bir işin yapılması için gerekli olan kodun iki katına kadar çalışmak istediğini görmek için uğraşıyorum ve birinin meslektaşlarımla aynı hissettiğini ve daha az kod için daha iyi kodlar elde etmek için bazı iyi durumlar yaratabildiğini merak ediyorum. ?


145
Kod boyutu, satırları veya karakter sayısını değil, okumanız ve anlamanız gereken zamanda ölçülür.
Bergi

13
Yazılı olarak sorunuz, kategorik olarak Çok Geniş. Bunun yerine yaptığınız değişikliklerle ilgili yeni bir tane yazmanızı öneririz.
jpmc26

8
Hızlı ters kare kök algoritmasını düşünün . Tam Newton yönteminin değişkenlerin uygun şekilde adlandırılmasıyla uygulanması, daha fazla kod satırı içermesine rağmen okunması çok daha net ve daha kolay olacaktır. (Bu özel durumda akıllı kod kullanarak, perf endişeleriyle haklı olduğunu unutmayın).
Maciej Piechotka

65
Codegolf.stackexchange.com : sorunuzu yanıtlamaya adanmış bir yığın değişim sitesi var . :)
Federico Poloni

Yanıtlar:


124

Zayıf bir kişinin, fazla kilolu bir kişiden daha sağlıklı olması gerekmez.

980 satırlık bir çocuk hikayesinin okunması 450 satırlık bir fizik tezinden daha kolaydır.

Kodunuzun kalitesini belirleyen birçok özellik var. Bazıları Cyclomatic Complexity ve Halstead Complexity gibi basit bir şekilde hesaplanır . Diğerleri, uyum , okunabilirlik, anlaşılabilirlik, genişletilebilirlik, sağlamlık, doğruluk, öz dokümantasyon, temizlik, test edilebilirlik ve daha pek çok şey gibi daha gevşek tanımlanır .

Örneğin, kodun genel uzunluğunu azaltırken - başka bir hatalı karmaşıklık eklediniz ve kodu daha şifreli hale getirdiniz.

Uzun bir kod parçasını küçük yöntemlere bölmek faydalı olabileceği kadar zararlı olabilir .

Meslektaşlarınızdan, yeniden düzenleme çabalarınızın neden istenmeyen bir sonuç ürettiğini düşündükleri konusunda size özel geri bildirimde bulunmalarını isteyin.


1
@PiersyP sadece bir FYI, iyi bir yeniden düzenleme hakkında öğretildiğim kılavuzlardan biri, siklomatik karmaşıklığın başlangıçta olduğu gibi bir kök dizisine indirgenmiş olduğunu görmemiz gerektiğidir .
MA Hanin

4
@PiersyP ayrıca, kodunuzun olduğundan daha kötü veya daha iyi olduğunu söylemiyorum. Bir yabancı olarak gerçekten söyleyemem. Ayrıca meslektaşlarınız aşırı muhafazakar olabilir ve değişiklikten korkuyor olabilirler çünkü yalnızca gözden geçirmek ve onaylamak için gerekli çabayı göstermediler. Bu yüzden onlardan ek geri bildirim istemenizi önerdim.
MA Hanin

6
İyi iş, millet - bir yerde "doğru" bir ağırlık olduğunu belirlediniz (kesin sayı değişebilir). @Neil'in orijinal yayınları bile, sadece "daha ağır olan kişinin" aksine, "AŞIRI ağırlık" diyor ve bunun nedeni programlamada olduğu gibi tatlı bir nokta olması. Bu "doğru boyut" un ötesine kod eklemek sadece karışıklıktır ve bu noktanın altındaki çizgilerin kaldırılması, kısalık uğruna kavrayışı feda eder. Bu noktanın tam olarak nerede olduğunu bilmek ... Bu zor bir şey.
AC,

1
Sadece gerekli olmadığından, değeri olmadığı anlamına gelmez.
Chris Wohlert

1
@Neil Genelde haklısın, ama aldatmaya çalıştığın her zaman zor "denge" objektif olarak konuşan bir efsanedir . Herkesin "iyi bir denge" ne olduğu konusunda farklı bir fikri vardır. Açıkçası, OP iyi bir şey yaptığını düşündü ve arkadaşları yapmadı, ama hepsinin kendilerine kodu yazarken "doğru dengeleri" olduğunu düşündüklerinden eminim.
code_dredd

35

İlginçtir ki, bir meslektaşım ve ben şu anda sınıfların ve işlevlerin sayısını iki katından biraz daha az artıracak bir refaktörün ortasındayız , ancak kod satırları aynı kalacak. Bu yüzden iyi bir örnek var.

Bizim durumumuzda, gerçekten iki olması gereken bir soyutlama katmanı vardı. Her şey kullanıcı arabirimi katmanına tıkıştı. Onu iki katmana bölerek her şey daha uyumlu hale gelir ve ayrı parçaların test edilmesi ve bakımı çok daha kolay hale gelir.

Meslektaşlarınızı rahatsız eden kodun boyutu değil, başka bir şey. Eğer eklemeyi başaramazlarsa, eski uygulamayı hiç görmemişsiniz gibi kendinize koda bakmaya çalışın ve sadece kıyaslama yapmak yerine kendi yararları ile değerlendirmeye çalışın. Bazen uzun bir refactor yaptığım zaman, asıl amacına bakış açımı kaybediyorum ve çok fazla şey alıyorum. Kritik bir "büyük resim" görün ve belki de tavsiyesine değer verdiğiniz bir çift programcısının yardımıyla tekrar yoluna koyun.


1
Evet, kullanıcı arabirimini kesinlikle diğer şeylerden ayırın, bu her zaman faydalıdır. Asıl amacın görüşünü kaybetme noktasında biraz katılıyorum, ama aynı zamanda daha iyisini veya daha iyisini yapmak için bir şeyi yeniden tasarlayabilirsiniz. Evrim hakkındaki eski argüman gibi ("bir kanadın parçası ne işe yarar?"), Onları geliştirmek için asla zaman ayırmazsanız işler iyileşmez. Yolda nereye gidene kadar nereye gittiğini her zaman bilemezsin. İş arkadaşlarının neden huzursuz olduklarını anlamaya çalışmakla aynı fikirdeyim, ama belki de gerçekten onların sorunu, sizin değil.

18

Genellikle Albert Einstein'ın atıfta bulunduğu bir alıntı akla geliyor:

Her şeyi mümkün olduğunca basitleştirin, ancak daha basit hale getirin.

İşleri kısmak için denize düştüğünüzde, kodu okumayı zorlaştırabilir. "Okuması kolay / zor" çok öznel bir terim olabileceğinden, tam olarak bununla ne demek istediğimi açıklayacağım: Yetenekli bir geliştiricinin "bu kodun ne yapacağını" belirlerken yaşayacağı zorluk derecesinin bir ölçüsü. sadece kaynağa bakarak, özel araçların yardımı olmadan.

Java ve Pascal gibi diller ayrıntılarıyla ünlüdür. İnsanlar genellikle bazı sözdizimsel unsurlara işaret eder ve ustaca “derleyicinin işini kolaylaştırmak için orada olduklarını” söyler. Bu "adil" kısım dışında az ya da çok doğru. Açık bilgi ne kadar fazla olursa, sadece derleyici tarafından değil, aynı zamanda bir insan tarafından okunması ve anlaşılması kolaylaşır.

Eğer söylersem var x = 2 + 2;, xtamsayı olduğu hemen anlaşılıyor . Ama söylersem var foo = value.Response;, neyi footemsil ettiği ya da özelliklerinin ve yeteneklerinin ne olduğu daha az açıktır . Derleyici kolayca çıkarsa bile, kişi üzerinde daha fazla bilişsel çaba harcar.

Programların insanların okuması için yazılması gerektiğini ve sadece makinelerin çalışması için tesadüfen yazılması gerektiğini unutmayın. (İronik olarak, bu alıntı, okunması son derece zor olduğu için rezil bir dile adanmış bir ders kitabından geliyor!) Yedekli olan şeyleri kaldırmak iyi bir fikirdir, ancak diğer insanların yapmasını kolaylaştıran kodları almayın Programın yazılması için kesinlikle gerekli olmasa bile, neler olduğunu anlayın.


7
Bu varörnek, özellikle basitleştirme için iyi bir örnek değildir, çünkü kodu okuma ve anlama çoğu zaman, belirli bir soyutlama seviyesindeki davranışı belirlemeyi içerir, bu nedenle, belirli değişkenlerin gerçek türlerini bilmek tipik olarak hiçbir şeyi değiştirmez (yalnızca düşük soyutlamaları anlamanıza yardımcı olur). Daha iyi bir örnek, basit ve basit bir ifadeye bölünmüş basit kod satırları olabilir - örneğin if ((x = Foo()) != (y = Bar()) && CheckResult(x, y)) , grok'a zaman ayırır ve türlerini bilmek xveya yen ufak bir şekilde yardımcı olmamak.
Ben Cottrell

15

Daha uzun kodları okumak kolay olabilir. Bu genellikle tam tersidir, ancak çok fazla istisna vardır - bazıları diğer cevaplarda belirtilmiştir.

Ama farklı bir açıdan bakalım. Yeni kodun, şirketin kültürü, kod tabanı veya yol haritası hakkında ek bir bilgiye sahip olmadan, 2 kod parçasını gören çoğu yetenekli programcı tarafından üstün olarak görüleceğini varsayıyoruz. O zaman bile, yeni koda itiraz etmek için birçok neden var. Kısacası "Yeni kodu eleştiren insanlar" diyeceğim Pecritenc :

  • İstikrar. Eski kodun kararlı olduğu biliniyorsa, yeni kodun kararlılığı bilinmiyor. Yeni kodun kullanılabilmesi için hala test edilmesi gerekiyor. Herhangi bir sebepten dolayı uygun testler yapılamıyorsa, değişiklik oldukça büyük bir problemdir. Test olsa bile, Pecritenc bu çabanın kodun (küçük) iyileştirilmesine değmeyeceğini düşünebilir.
  • Performans / ölçekleme. Eski kod daha iyi ölçeklendirilmiş olabilir ve Pecritenc, müşteriler ve özellikler yakında toparlandıkça performansın düşüşte sorun olacağını varsayıyor.
  • Genişletilebilirlik. Eski kod, Pecritenc'in yakında ekleneceğini varsayan bazı özelliklerin kolayca kullanılmasına izin vermiş olabilir *.
  • Aşinalık. Eski kod, şirketin kod tabanının diğer 5 yerinde kullanılan modelleri tekrar kullanabilir. Aynı zamanda, yeni kod, şirketin bu noktada sadece yarısının duyduğu süslü bir kalıp kullanmaktadır.
  • Bir domuzun üzerinde ruj. Pecritenc, hem eski hem de yeni kodun çöp olduğunu ya da alakasız olduğunu düşünerek, aralarında anlamsız karşılaştırmalar yapabilir.
  • Gurur. Pecritenc, kodun asıl yazarı olabilir ve insanların kodunda büyük değişiklikler yapmalarını sevmez. Gelişmeleri hafif bir hakaret olarak bile görebilir, çünkü daha iyisini yapması gerektiğini ima ederler.

4
'Pecritenc' için +1 ve ön hazırlıktan önce önceden göz önünde bulundurulması gereken çok iyi vaaz edilebilir itirazlar özeti.

1
Ve 'genişletilebilirlik' için +1 - Özgün kodun gelecekteki bir projede kullanılması amaçlanan işlevlere veya sınıflara sahip olabileceğini düşünüyordum, bu yüzden soyutlamalar gereksiz veya gereksiz görünüyordu, ancak sadece tek bir program bağlamında görünebilirdi.
Darren Ringer,

Ayrıca, söz konusu kod kritik bir kod olmayabilir, bu nedenle temizlemek için mühendislik kaynaklarının kaybı olarak kabul edilir.
Erik Eidt,

@nocomprende Önceden düşünülebilir, önceden düşünülmüş ve ön hazırlık kullanmanın bir nedeni var mı? Pecritenc'e benzer yöntem olabilir mi?
Milind R

@ MililR Muhtemelen bir önyargı, bir tercih veya kişisel bir tercih mi? Veya, belki de hiçbir neden yok, kofaktif kofaktör kofaktör birliği, komplo edici koşulları karıştırıyor. Hiç bir fikrim yok, gerçekten. Sen nasılsın?

1

Ne tür bir kod daha iyidir, programcıların uzmanlığına ve ayrıca kullandıkları araçlara bağlı olabilir. Örneğin, normalde kötü yazılı olan kodun, bazı durumlarda mirastan tam anlamıyla yararlanan iyi yazılmış nesne yönelimli koddan daha etkili olmasının nedeni budur:

(1) Bazı programcılar, nesne yönelimli programlamanın sezgisel bir kavrayışına sahip değillerdir. Bir yazılım projesi için metaforunuz bir elektrik devresiyse, çok sayıda kod çoğaltması beklersiniz. Birçok derste aynı yöntemleri aşağı yukarı görmek isteyeceksiniz. Sizi evde hissettirecekler. Ve neler olup bittiğini görmek için ebeveyn sınıflarında veya hatta büyükbaba sınıflarında yöntemleri araştırmanız gereken bir proje düşmanca gelebilir. Ebeveyn sınıfının nasıl çalıştığını ve ardından mevcut sınıfın nasıl değiştiğini anlamak istemezsiniz. Doğrudan mevcut sınıfın nasıl çalıştığını anlamak istiyorsunuz ve bilgilerin kafa karıştırıcı birçok dosyaya yayıldığı gerçeğini buluyorsunuz.

Ayrıca, belirli bir sınıfta belirli bir sorunu çözmek istediğinizde, sorunu doğrudan temel sınıfta düzeltmeyi veya mevcut ilgilendiğiniz sınıftaki yöntemin üzerine yazmayı düşünmemeyi istemeyebilirsiniz. (Miras olmadan bilinçli bir karar almak zorunda kalmazsınız. Varsayılan, benzer sınıflardaki benzer sorunları sadece hata olarak bildirilinceye kadar görmezden gelmektir.) Bu son bakış, gerçekten geçerli bir argüman değildir; muhalefet.

(2) Bazı programcılar hata ayıklayıcıyı çok kullanır. Her ne kadar genel olarak kod kalıtımın kendisinde kalıyorum ve çoğaltmayı önlüyor olmama rağmen, nesne yönelimli kodun hatalarını ayıklarken (1) de tarif ettiğim sıkıntıyı paylaşıyorum. Kod çalıştırmayı takip ettiğinizde, bazen aynı nesneyle kalsa bile (ata) sınıfları arasında atlamaya devam eder. Ayrıca, iyi yazılmış bir kodda bir kesme noktası belirlerken, yardımcı olmadığında tetiklenmesi daha olasıdır, bu nedenle koşullu (pratik olduğunda) veya hatta ilgili tetikleyiciden önce birçok kez manuel olarak devam ettirmek için çaba harcamanız gerekebilir.


3
"büyükbaba sınıfları"! ha ha ha! Sadece Adem ve Havva derslerine dikkat edin. (Ve tabii ki Tanrı sınıfı) Ondan önce, formları yoktu ve geçersizdi.

1

Tamamen bağlıdır. Boole değişkenlerine işlev parametreleri olarak izin vermeyen, ancak bunun yerine enumher seçenek için ayrı bir proje gerektiren bir proje üzerinde çalışıyorum .

Yani,

enum OPTION1 { OPTION1_OFF, OPTION1_ON };
enum OPTION2 { OPTION2_OFF, OPTION2_ON };

void doSomething(OPTION1, OPTION2);

çok daha ayrıntılı

void doSomething(bool, bool);

Ancak,

doSomething(OPTION1_ON, OPTION2_OFF);

çok daha okunaklı

doSomething(true, false);

Derleyici her ikisi için de aynı kodu üretmelidir, bu nedenle kısa formu kullanarak elde edilecek hiçbir şey yoktur.


0

Uyumun bir sorun olabileceğini söyleyebilirim.

Örneğin, bir web uygulamasında, tüm ürünleri indekslediğiniz bir Yönetici sayfanız olduğunu, ana sayfa durumunda kullandığınızla aynı kodla (indeks), sadece ürünleri indekslemenizi sağlar.

Her şeyi kısmi bir hale getirmeye karar verirseniz, KURU ve şık kalabilmeniz için, kullanıcının göz atmasının bir yönetici olup olmadığına ilişkin bir çok koşul eklemek zorundasınız ve kodu söylenmeyen son derece okunaksız hale getirecek gereksiz şeylerle karıştırmanız gerekir. bir tasarımcı!

Dolayısıyla, böyle bir durumda, kod hemen hemen aynı olsa bile, başka bir şeye ölçeklenebildiğinden ve kullanım durumları biraz değişebildiğinden, her birinin peşinden koşulu ve ifadesiyle gitmek kötü olacaktır. Bu nedenle, iyi bir strateji, DRY kavramını sonlandırmak ve kodu bakım yapılabilir parçalara bölmek olacaktır.


0
  • Daha az kod, daha fazla kodla aynı işi yapmıyorsa. Basitlik için yeniden yapılanma iyidir, ancak bu çözümün karşıladığı sorun alanını fazlalaştırmamaya özen göstermelisiniz. 980 kod satırı, 450'den fazla köşe örneğini taşıyabilir.
  • Daha az kod, daha fazla kod kadar zarif bir şekilde başarısız olmazsa. "Gereksiz" deneme-yakalama ve diğer hata durumlarını kaldırmak için kod üzerinde yapılan birkaç "ref *** toring" işi gördüm. Kaçınılmaz sonuç, hataya ve kullanıcının yapabileceklerine ilişkin güzel bir mesaj içeren bir iletişim kutusu göstermek yerine, uygulama çöktü veya YSODed oldu.
  • Daha az kod, daha fazla koddan daha az bakım gerektirebilir / genişletilebilir olduğunda. Kodun özlü olması için yeniden yapılanma genellikle, LoC'nin çıkarına olan "gereksiz" kod yapılarını kaldırır. Sorun şu ki, bu kod yapıları, paralel arabirim bildirimleri, ayıklanan yöntemler / alt sınıflar vb. Gerekliyse, bu kodun şu anda yaptığından daha fazlasını yapması veya farklı şekilde yapması gerekiyorsa gereklidir. Aşırı, belirli bir soruna özel olarak uyarlanmış belirli çözümler, eğer sorun tanımı biraz değişirse hiç çalışmayabilir.

    Bir örnek; tamsayıların bir listesi var. Bu tam sayıların her biri, biri hariç listedeki yinelenen bir değere sahiptir. Algoritmanız bu eşlenmemiş değeri bulmalı. Genel durum çözümü, listede N = 2 zamanlı bir işlem olan, hiçbir dupe olmayan numara bulana kadar her numarayı diğer numaralarla karşılaştırmaktır. Ayrıca bir karma tablo kullanarak bir histogram da oluşturabilirsiniz, ancak bu çok fazla alan kullanmaz. Ancak, bitsel XOR işlemi kullanarak onu doğrusal zaman ve sabit alan yapabilirsiniz; XOR, çalışan bir "toplam" a (sıfırdan başlayarak) karşı her tamsayıya karşılık gelir ve sonunda, toplam toplam, eşlenmemiş tamsayılarınızın değeri olur. Çok zarif. Gereksinimler değişene kadar ve listedeki birden fazla sayı eşleştirilmemiş olabilir veya tamsayılar sıfır içerebilir. Şimdi programınız ya çöpleri ya da belirsiz sonuçları döndürür (sıfıra dönerse, bu tüm öğelerin eşleştirildiği veya eşleşmeyen öğenin sıfır olduğu anlamına mı gelir?). Gerçek dünyadaki programlamada "akıllı" uygulamaların sorunu budur.

  • Daha az kod, daha fazla koddan daha az kendi kendine belgelendirme olduğunda. Kodun kendisini okuyabilmek ve ne yaptığını tespit edebilmek ekip gelişimi için kritik öneme sahiptir. Küçük bir geliştiriciye güzel bir performans sergileyen yazdığınız beyin-f *** algoritmasını vermek ve çıktısını biraz değiştirmek için onu ince ayar yapmasını istemek sizi çok uzağa götürmez. Bir çok kıdemli dev de bu durumla ilgili sorun yaşar. Herhangi bir zamanda, kodun ne yaptığını ve neyin yanlış gidebileceğini anlayabilmeniz, çalışan bir ekip geliştirme ortamının anahtarıdır (ve hatta solo; size, 5 yaşındayken yazdığınız bir deha flaşının olduğunu garanti ederim. Kanseri tedavi etmek için kullanılan lineer yöntem, uzun süredir, Parkinson hastalığını da tedavi etmek isteyen bir işleve geri döndüğünüzde gitmiş olacak.)

0

Bilgisayar kodunun birkaç şey yapması gerekir. Bunları yapmayan bir "minimalist" kod iyi bir kod değildir.

Örneğin, bir bilgisayar programı mümkün olan her şeyi kapsamalıdır (ya da en azından bütün olası durumları çıplak olarak). Bir kod parçası yalnızca bir "temel durumu" kapsar ve diğerlerini yoksayarsa, kısa olsa bile iyi bir kod değildir.

Bilgisayar kodu "ölçeklenebilir" olmalıdır. Şifreli bir kod yalnızca bir özel uygulama için çalışabilirken, daha uzun ancak daha açık uçlu bir program yeni uygulamaların eklenmesini kolaylaştırabilir.

Bilgisayar kodu açık olmalı. Başka bir cevaplayıcının gösterdiği gibi, sert çekirdekli bir kodlayıcının işi yapan bir satırlık "algoritmik" tür işlev üretmesi mümkündür. Ancak, bir liner ortalama programcıya açıklanmadan önce beş farklı "cümleyle" bölünmek zorunda kaldı.


Görev, sahibinin gözündedir.

-2

Hesaplamalı performans Boru hattınızı optimize ederken ya da çalıştığınız parçaları paralel olarak kodlarken, örneğin 1 - 400 arasında değil, 1 - 50 arasında döngü ve her döngüye benzer kodların 8 örneğini koymanız faydalı olabilir. Bunun sizin durumunuzda böyle olduğunu sanmıyorum, ancak daha fazla satırın daha iyi olduğu bir örnek (performans açısından).


4
İyi bir derleyici, ortalama bir programlayıcıdan, belirli bir bilgisayar mimarisi için döngüleri nasıl açacağını daha iyi bilmelidir, ancak genel nokta geçerlidir. Bir keresinde bir Cray yüksek performans kitaplığındaki matris çarpma yordamının kaynak koduna baktım. Matris çarpımı üç iç içe döngü ve toplamda yaklaşık 6 satırlık koddur, değil mi? Yanlış - bu kütüphane rutini yaklaşık 1100 kod satırına ve bunun neden bu kadar uzun olduğunu açıklayan benzer sayıda yorum satırına koştu!
alephzero

1
@ alephzero vay, ben bu kodu görmek isterdim, sadece Cray Cray olmalı.

@ alephzero, iyi derleyiciler çok şey yapabilir, ama ne yazık ki her şey değil. Parlak tarafı, programlamayı ilginç kılan şeyler!
Hans Janssen

2
@alephzero Nitekim, iyi matris çarpma kodu sadece biraz zaman kaybetmez (yani sabit bir faktörle azaltır), farklı asimptotik karmaşıklığa sahip tamamen farklı bir algoritma kullanır, örneğin Strassen algoritması kabaca O (n ^ 2.8) O (n ^ 3) yerine.
Arthur Tacca
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.