Bilimsel kod yazarken temiz programlama


169

Gerçekten büyük projeler yazmıyorum. Büyük bir veri tabanı tutmuyorum ya da milyonlarca satır kodla uğraşıyorum.

Kodum öncelikle "betikleme" türünde şeyler - matematiksel fonksiyonları test etmek veya bir şeyi simüle etmek için şeyler - "bilimsel programlama" dır. Bu noktaya kadar çalıştığım en uzun programlar birkaç yüz satırlık bir kod ve üzerinde çalıştığım programların çoğu 150 civarında.

Benim kodum da saçmalık. Geçen gün bunu, bir süre önce yazdığım bir dosyayı bulmaya çalışırken fark ettim, ancak muhtemelen üzerine yazdım ve muhtemelen aptallığımla uğraşırken sık sık acı çekmenize neden olan sürüm kontrolü kullanmıyordum.

Kodumun tarzı kıvrımlıdır ve bir şeyi yapmanın alternatif yollarını veya üzerine kopyalanan kod satırlarını belirten eski yorumlarla doludur. Değişken isimleri her zaman çok güzel ve açıklayıcı olsa da, örneğin bir şeyi eklemek veya değiştirmek gibi, birinin test etmek istediği yeni bir şey var, kod üste ve üstüne yazılıyor ve bu şeyin şimdi hızlı bir şekilde test edilmesi gerektiğini düşündüğüm için crappy değişken isimleri kullanmaya başladım ve dosya potu kullanmaya başladı.

Şu an üzerinde çalıştığım projede, beni büyük bir şekilde ısırmak için tüm bunların geri döneceği aşamadayım. Ancak sorun şu ki (sürüm kontrolünü kullanmak ve her yeni yineleme için yeni bir dosya oluşturmak ve hepsini bir yerde bir metin dosyasına kaydetmek, muhtemelen durumu dramatik bir şekilde yardımcı olacak) geliştirmeye devam etmeyi gerçekten bilmiyorum. benim gerçek kodlama tarzım.

Daha küçük kod parçaları yazmak için birim testi gerekli midir? Peki ya OOP? Daha büyük projeler üzerinde çalışmak yerine "bilimsel programlama" yaparken hızlı ve iyi bir kod yazmak için ne tür yaklaşımlar iyidir?

Bu soruları soruyorum çünkü sıklıkla programlamanın kendisi süper karmaşık değildir. Bu, programlama ile test ettiğim veya araştırdığım matematik veya bilim hakkında daha fazla. Örneğin, iki değişken ve bir fonksiyon muhtemelen ilgilenebileceği zaman bir sınıf gerekli midir? (Bunları da genellikle programın hızının daha hızlı olması tercih edilen durumlar olduğunu göz önünde bulundurun - bir simülasyonun 25.000.000'den fazla zaman adımını çalıştırırken, olmasını istersiniz.)

Belki de bu çok geniş ve öyleyse, özür dilerim, ancak programlama kitaplarına bakarken, genellikle daha büyük projelerde ele alındıkları görülüyor. Kodumun OOP'ye ihtiyacı yok ve zaten oldukça kısa, bu yüzden "ah, ama bunu yaparsak dosya bin satır azalacak!" Gibi değil. Nasıl daha yeni başlayacağımı ve bu daha küçük, daha hızlı projelere nasıl temiz bir şekilde programlanacağını bilmek istiyorum.

Daha ayrıntılı bilgi vermekten memnuniyet duyarım, ancak tavsiye ne kadar genelse, daha faydalı olur. Python 3'te programlama yapıyorum.


Birisi bir kopya önerdi. Açıkça söyleyeyim, standart programlama standartlarını tamamen görmezden gelmekten bahsetmiyorum. Açıkçası, bu standartların var olmasının bir nedeni var. Ancak, diğer taraftan, bazı standart şeyler yapıldığında, yazmak çok daha hızlı olacak ve kısa bir süre için benzer bir okunabilirlik seviyesi olacaktı, OOP diyen bir kod yazmak gerçekten mantıklı geliyor mu? Program?

İstisnalar var. Ayrıca, bilimsel programlama için sadece standartların ötesinde standartlar vardır. Bunları da soruyorum. Bu, bilimsel kod yazarken normal kodlama standartlarının göz ardı edilmesi gerekip gerekmediğiyle ilgilidir, temiz bilimsel kod yazmakla ilgilidir!


Güncelleme

"Bir hafta sonra değil" şeklinde bir güncelleme ekleyeceğimi düşündüm. Tavsiyelerin hepsi son derece yardımcı oldu. Şimdi sürüm kontrolü kullanıyorum - git, grafik arayüz için git kraken. Kullanımı çok kolay ve dosyalarımı büyük ölçüde temizledi - eski dosyalara ya da eski kod sürümlerine artık "tam olarak" yorum yapmadı.

Ayrıca pylint'i kurdum ve kodumun tamamına koştum. Bir dosya başlangıçta olumsuz bir puan aldı; Bunun nasıl mümkün olduğundan bile emin değilim. Ana dosyam ~ 1.83 / 10 puanla başladı ve şimdi ~ 9.1 / 10'da. Tüm kod şimdi standartlara oldukça uygun. Ben de kendi gözlerimle koştum ... uhm ... korkunç değişken isimleri güncelleme ve refactor bölümleri arıyorum.

Özellikle, bu sitede ana işlevlerimden birini yeniden düzenleme hakkında yeni bir soru sordum ve şimdi çok daha temiz ve çok daha kısa: uzun, şişirilmiş yerine, eğer / başka bir işlev doluysa, şimdi yarıdan daha az boyut ve ne olup bittiğini bulmak çok daha kolay.

Bir sonraki adımım, türlerin "birim testini" uygulamak. Ana dosyamda çalıştırabildiğim ve assert ifadeleriyle çalıştığım bir dosyayı kastediyorum, muhtemelen bunu yapmanın en iyi yolu olmayan deney / istisnalar ve yinelenen birçok kodla sonuçlanıyor. ama okumaya devam edeceğim ve nasıl daha iyi yapılacağını bulmaya çalışacağım.

Ayrıca, önceden yazmış olduğum belgeleri de önemli ölçüde güncelledim ve excel elektronik tablosu, belgeler ve ilgili bir makale gibi ek dosyaları github deposuna ekledim. Şimdi gerçek bir programlama projesi gibi görünüyor.

Yani ... Sanırım bunların hepsi şöyle: teşekkür ederim .




8
Kodunuzu aktif olarak geliştirmek istiyorsanız, Kod İncelemeye bir miktar yazı göndermeyi düşünebilirsiniz . Oradaki topluluk size memnuniyetle yardımcı olacaktır.
hoffmale

7
"Sürüm kontrolünü kullanmaktan yana, her yeni yineleme için yeni bir dosya yapmak ve hepsini bir metin dosyasına" by "ve" yani "veya" demek istiyorsun "derken, sürüm kontrolünü kullanıyorsanız kopya yapıştırma sürümleri olma. Mesele şu ki, sürüm kontrolü sizin için tüm eski sürümleri tutar
Richard Tingle

2
@ mathreadler Tam olarak anladığını sanmıyorum. Evet, sadece her biri muhtemelen kodu okuyacak ve bozacak (muhtemelen hiç bilmeseniz de, farklı bir dilde olsa programlayabilen biriyle çalışıyorum) ... ama kod hala pislik, ıvır zıvır, çerçöp. Daha sonra okumak ve ne halt ettiğimi tekrar bulmak zorunda kalacağım. Bu ise bir sorun ve şimdi etkilerini yaşıyorum çünkü ben buna tanıklık edebilir, ve ben versiyon kontrol ve burada önerilen diğer teknikleri uyguladık olarak şeyler daha kolay hale gelmiştir.
heather

Yanıtlar:


163

Bu bilim adamları için oldukça yaygın bir sorundur. Bunu çok gördüm ve her zaman programlamanın, işinizi yapmak için bir araç olarak seçeceğiniz bir şey olduğu gerçeğinden kaynaklanıyor.

Yani senaryolarınız berbat. Sağduyuya karşı çıkacağım ve şunu söyleyeceğim, yalnız programlama yaptığınızı varsayarsak, bu o kadar da kötü değil! Bir daha asla yazdıklarınızın çoğuna dokunmayacaksınız, bu yüzden "değer" (yani komut dosyanızın sonucu) yerine güzel kod yazmak için çok fazla zaman harcamak size fazla bir şey yapmayacak.

Ancak, yaptığınız bir şeye geri dönmeniz ve tam olarak bir şeyin nasıl çalıştığını görmeniz gereken bir zaman olacak. Ek olarak, diğer bilim adamlarının kodunuzu incelemesi gerekecekse, herkesin anlayabilmesi için olabildiğince açık ve net olması gerçekten önemlidir.

Asıl probleminiz okunabilirlik olacak, işte geliştirmek için birkaç ipucu:

Değişken isimleri:

Bilim adamları özlü açıklamalar kullanmaya bayılırlar. Tüm matematiksel denklemler genellikle değişkenler olarak tek harf kullanır ve kodunuzda çok ve çok kısa değişkenler gördüğüme şaşırmam. Bu okunabilirliği çok acıtıyor. Kodunuza geri döndüğünüzde, y, i ve x2'nin neyi temsil ettiğini hatırlamayacaksınız ve anlamaya çalışmak için çok zaman harcayacaksınız. Bunun yerine değişkenlerinizi tam olarak ne olduklarını temsil eden isimler kullanarak adlandırmayı deneyin.

Kodunuzu işlevlere ayırın:

Artık tüm değişkenlerinizi yeniden adlandırdığınıza göre, denklemleriniz berbat görünüyor ve çok satırlı.

Ana programınızda bırakmak yerine, bu denklemi farklı bir işleve taşıyın ve buna göre adlandırın. Şimdi çok büyük ve karışık bir kod satırına sahip olmak yerine, tam olarak neler olduğunu ve hangi denklemi kullandığınızı anlatan kısa bir talimatınız olacak. Bu, hem ana programınızı geliştirir, hem de ne yaptığınızı bilmek için gerçek denkleme bakmak zorunda değilsiniz ve denklem kodunun kendisi, ayrı bir fonksiyonda olduğu gibi değişkenlerinizi istediğiniz şekilde isimlendirebilir ve geri dönebilirsiniz. daha tanıdık tekil harfler.

Bu düşünce biçiminde, bir şeyi temsil eden tüm kod parçalarını bulmaya çalışın, özellikle de bir şey kodunuzda birden çok kez yapmanız gereken bir şeyse ve onları işlevlere ayırın. Kodunuzun hızlıca okunmasının kolay olacağını ve daha fazla kod yazmadan aynı işlevleri kullanabileceğinizi öğreneceksiniz.

Pasta üzerine krema yapma, eğer bu fonksiyonlara daha fazla programda ihtiyaç duyulursa, onlar için bir kütüphane oluşturabilirsin ve onları her zaman hazır tutabilirsin.

Global değişkenler:

Başlangıçta döndüğümde, bunun programımın birçok noktasında ihtiyaç duyduğum verileri dolaşmanın harika bir yolu olduğunu düşündüm. Maddelerin etrafından dolaşmanın başka birçok yolu vardır ve küresel değişkenlerin yaptığı tek şey insanlara sıkıntı vermek, çünkü programınızın rastgele bir noktasına giderseniz bu değerin en son ne zaman kullanıldığını veya düzenlendiğini asla bilemezsiniz. onu takip etmek bir acı olacak. Mümkün olduğunda onlardan kaçınmaya çalışın.

İşlevlerinizin birden fazla değeri döndürmesi veya değiştirmesi gerekiyorsa, ya bu değerlere sahip bir sınıf yapın ve bunları parametre olarak iletin ya da işlevin birden çok değer döndürmesini (adlandırılmış tuples ile) yapın ve bu değerleri arayan kodunda atayın.

Sürüm Kontrolü

Bu doğrudan okunabilirliği arttırmaz, ancak yukarıdakilerin hepsini yapmanıza yardımcı olur. Ne zaman bir değişiklik yaparsanız, sürüm kontrolüne karar verin (yerel bir Git deposu yeterince iyi olacaktır) ve eğer bir şey işe yaramazsa ne değiştiğinize bakın ya da geri dönün! Bu, kodunuzu yeniden düzenlemeyi kolaylaştıracak ve yanlışlıkla bir şeyleri kıracağınız bir güvenlik ağı olacaktır.

Tüm bunları aklınızda tutmak, daha net ve daha etkili bir kod yazmanıza izin verecek ve devasa fonksiyonlar ve dağınık değişkenler arasında gezinmek zorunda kalmayacağınız için olası hataları daha hızlı bulmanıza yardımcı olacaktır.


56
Mükemmel tavsiye Ancak "o kadar da fena değil" yorumuna oy veremem. Çok kötü. Düşük kaliteli bilimsel senaryolar, veri analizinde tekrarlanabilirlik ve analizde sık sık hata kaynağı için büyük bir konudur. İyi kod yazmak yalnızca daha sonra anlayabilmeniz için değil, aynı zamanda ilk etapta hataları önlemek için de değerlidir.
Jack Aidley

22
Kod, iyi bilinen bir formülün bir uygulamasıysa, tek harfli değişken adları ve böyle yapılması doğru olan şey olabilir. Seyirciye ... ve daha fazlası, okuyucunun adlarının ne anlama geldiğini bilmesinin beklenip beklenmediğine bağlıdır.
cHao

11
@cHao'da sorun, bu değişkenlerin formüle takılı olması değil (bu nedenle "işlev içinde onları yeniden adlandır" tavsiyesi) değil, bunun dışında okunduğunda ve manipüle edildiğinde ve satırdaki diğer değişkenlerle çelişmeye başladığında (örneğin, üç "x" değişkenine ihtiyaç duyan insanlar için onları x1, x2, x3 olarak adlandırdım)
BgrWorker

4
“Ben sağduyuya karşı gidiyorum ...” Hayır değilsin. Sağduyuya karşı olan hakim dogmaya karşı çıkıyorsunuz. ;) Bu tamamen mükemmel bir tavsiye.
jpmc26

3
(Eski) bir bilimsel programcı olarak, genellikle üç kuralını kabul ediyorum. Üç kez benzer kod yazmayı bırakırsam, işlevsellik bozuluyor ve belgelerle birlikte ayrı bir modülde yazılıyor (genellikle sadece yorumlar, ancak bu yeterli). Bu, geçici programlamanın karmaşasını sınırlandırıyor ve gelecekte genişletebileceğim bir kitaplık oluşturmamı sağlıyor.
rcollyer

141

Burada fizikçi. Orada bulunmak.

Sorununuzun araç seçimi veya programlama paradigmaları (ünite testi, OOP, her neyse) ile ilgili olmadığını iddia ediyorum . Yaklaşık var tutum , zihniyet. Değişken isimlerinizin ilk başta iyi seçilmesi ve sonuçta saçmalık olması yeterince açıklayıcıdır. Kodunuzu “bir kez koş, sonra fırlat” olarak düşünürseniz, kaçınılmaz olarak bir karışıklık olacaktır. Zanaat ve sevginin ürünü olarak düşünürseniz, güzel olacak.

Temiz kod yazmak için tek bir tarif olduğuna inanıyorum : onu okuyacak olan tercüman için değil, okuyacak olan insana yaz. Kodunuzu bir karışıklık ise tercüman umursamıyor, ama insan okuyucu yapar bakımı.

Sen bir bilim adamısın. Bilimsel bir makaleyi parlatmak için muhtemelen çok zaman harcayabilirsiniz. Eğer ilk taslağınız kıvrılmış gözüküyorsa, mantık en doğal şekilde akıncaya kadar onu yeniden etkileyeceksiniz. Meslektaşlarınızın onu okumasını ve argümanları net bir şekilde bulmasını istiyorsunuz. Öğrencilerinizin bundan öğrenebilecekleri bir şey olmasını istiyorsunuz.

Temiz kod yazmak tamamen aynıdır. Kodunuzu yalnızca tesadüfen makinede okunabilen bir algoritmanın ayrıntılı bir açıklaması olarak düşünün. İnsanların okuyacağı bir makale olarak yayınlayacağınızı hayal edin. Hatta bir konferansta gösterip izleyiciyi sırayla izleyeceksiniz. Şimdi sunumunu prova et . Evet, satır satır ! Utanç verici, değil mi? Bu yüzden slaytlarınızı temizleyin (hata ... Yani kodunuzu) ve tekrar prova yapın. Sonuçtan memnun kalana kadar tekrarlayın.

Provalardan sonra, kodunuzu yalnızca hayali insanlardan ziyade kendi kendinize değil gerçek insanlara gösterebiliyorsanız, bu daha iyi olacaktır. Bu satır satır satır geçerek "kod yürüyüşü" olarak adlandırılır ve saçma bir uygulama değildir.

Tabii ki, bunların hepsi bir bedeli var. Temiz kod yazmak, basit kod yazmaktan çok daha fazla zaman alır . Yararların, özel kullanım durumunuzun maliyetinden ağır basıp basmadığını yalnızca siz değerlendirebilirsiniz.

Araçlar gelince, o kadar önemli olmadıklarını söyledim . Ancak, birini seçmek zorunda kalsaydım, sürüm kontrolünün en kullanışlı olduğunu söyleyebilirim.


32
«Temiz kod yazmak tam olarak aynıdır (net bir makale yazmak gibi).» Tamamen onaylıyorum, tamam!
juandesant

43
Bu, çoğu profesyonel programcının söylemeyi unuttuğu bir şey çünkü çok açık. Başka bir programlayıcı tarafından okunabilir ve değiştirilebilir olduğunda kodunuz biter. Çalıştığında ve doğru çıktı ürettiğinde olmaz. OP, insan tarafından okunabilir hale getirmek için kodunu yeniden gözden geçirerek ve yorum yaparak senaryo başına ilave bir saat harcamalı ve ekstra harcama yapmalıdır.
UEFI

31
Temiz kod yazmadan ıskarta kod yazarken çok daha fazla zaman alıyor olsa da, çok daha önemli olduğunu okuduktan ıskarta kodunu temiz kod okuma çok daha fazla zaman alır.
user949300,

3
@UEFI Hayır, çoğu profesyonel programcının bile anlamadığı bir şey. Veya umursamıyorum.
jpmc26

2
% 100 kabul edin. İstatistikçi programcı oldu, bu yüzden işyerinde adil miktarda 'bilimsel' programlama yapıyorum. Kodu temizle, anlamlı yorumlarla, 1, 4 veya 12 ay sonra bu koda geri dönmen gerektiğinde hayat kurtarıcı olur. Kodu okumak, kodun ne yaptığını gösterir. Yorumları okumak, kodun ne yapması gerektiğini söyler.
railsdog

82

Sürüm kontrolü muhtemelen paranızın karşılığını en çok kazandıracak. Yalnızca uzun süreli depolama için değil, kısa vadeli denemelerinizi takip etmek ve en son kullanılan sürüme geri dönüp not almak için mükemmeldir.

Bir sonraki en faydalı birim testleridir. Birim testlerle ilgili olan şey, milyonlarca kod satırı bulunan kod tabanları bile, her seferinde bir birim test edilir. Birim testi, en düşük soyutlama düzeyinde, küçük olarak yapılır. Bu, küçük kod tabanları için yazılmış birim testleri ile büyükler için kullanılanlar arasında temelde bir fark olmadığı anlamına gelir. Onlardan daha fazlası var.

Birim testleri, başka bir şeyi düzeltirken zaten çalışmakta olan bir şeyi kırmamanın veya en azından yaptığınız zaman size en hızlı şekilde söylemenin en iyi yoludur. Bunlar aslında bir programcı kadar yetenekli olmadığınız ya da hataları daha az veya daha belirgin hale getirmek için yapılandırılmış daha ayrıntılı kodları nasıl yazacağınızı veya bilmek istemediğiniz zaman daha faydalıdır.

Sürüm kontrolü ile yazdığınız testlerin yazılması arasında kod size doğal olarak daha temiz bir hal alacaktır. Bir platoya çarptığınızda daha temiz kodlamanın diğer teknikleri de öğrenilebilir.


78
Kodumun çoğunu dini olarak birim testine tabi tutuyorum ama birim testinde keşfedici, bilimsel kodu yararsızdan daha az buldum . Metodoloji temelde burada işe yaramadı. Alanımda analiz kodlarını test eden hiçbir bilgisayarlı bilim adamı tanımıyorum. Bu uyumsuzluğu nedeni ama ne olduğundan emin değilim biri nedenlerinden kesinlikle olmasıdır önemsiz birimleri hariç, iyi test durumları kurmak zor veya imkansız.
Konrad Rudolph

22
@KonradRudolph Bu gibi durumlarda hile, kodunuzun açıkça tanımlanabilen davranışları (bu girişi okumak, bu değeri hesaplamak) açıkça tanımlayıcı davranışa sahip olan veya örneğin uyarlama yapan bölümlerinden bölümler arasındaki endişelerin net bir şekilde ayrılması olabilir. bazı insan tarafından okunabilir çıktı veya görselleştirme. Buradaki problem, kaygıların zayıf bir şekilde ayrılmasının, bu çizgilerin bulanıklaşmasına yol açması muhtemeldir, bu, bu bağlamda birim testinin imkansız olduğuna dair bir algıya yol açar, bu da sizi tekrar eden bir döngüde başlangıcına götürür.
Ant P,

18
Bir yandan, sürüm kontrolü aynı zamanda LaTeX belgeleri için oldukça iyi çalışır, çünkü format metin farklılığına uygundur. Bu şekilde, hem yazılarınız hem de onları destekleyen kodlar için bir depoya sahip olabilirsiniz. Git gibi dağıtılmış sürüm kontrolüne bakmanızı öneririm. Biraz öğrenme eğrisi var, ancak bir kez anladığınızda, gelişiminizi yinelemenin güzel ve temiz bir yoluna sahipsiniz ve akademisyenler için ücretsiz ekip hesapları sunan Github gibi bir platform kullanmak için ilginç seçenekleriniz var .
Dan Bryant,

12
@AntP İyi tanımlanmış test edilebilir birimlere anlamlı bir şekilde yeniden yerleştirilebilecek çok fazla kod olmaması mümkündür. Birçok bilimsel kod, temel olarak bir grup kütüphaneyi bir araya getiriyor. Bu kütüphaneler zaten iyi bir şekilde test edilmiş ve temiz bir şekilde yapılandırılmış, yani yazarın sadece "yapıştırıcı" yazması gerekiyor ve benim tecrübeme göre, tautolojik olmayan tutkal için ünite testleri yazmak neredeyse imkansız.
James_pic

7
"Sürüm kontrolü ve gittiğiniz birim testleri yazarken, kod doğal olarak daha temiz hale gelecektir." Bu doğru değil . Bunu şahsen doğrulayabilirim. Bu araçların hiçbiri durur bok kod yazarken sizi, ve özellikle de berbat kodun üstüne bok testler yazılı sadece daha da zor temizlemek mümkün kılar. Testler sihirli bir gümüş mermi değildir ve onlar gibi konuşmak hala öğrenen herhangi bir geliştiriciye (ki herkes) yapmak için korkunç bir şeydir. Sürüm kontrolü genellikle kötü testlerde olduğu gibi kodun kendisine asla zarar vermez.
jpmc26

29

(sürüm kontrolünü kullanmak ve her yeni yineleme için yeni bir dosya oluşturmak ve hepsini bir yerde bir metin dosyasına kaydetmek dışında, muhtemelen duruma önemli ölçüde yardımcı olacak)

Muhtemelen bunu kendin çözebilirdin, ancak " hepsini bir yerden bir metin dosyasına kaydetmen gerekiyorsa " sürüm kontrol sistemini tam potansiyel olarak kullanmıyorsun. Subversion, git veya Mercurial gibi bir şey kullanın ve her işlemle iyi bir taahhüt mesajı yazın; metin dosyasının amacına hizmet eden ancak depodan ayrılamayan bir günlük edin.

Bunun yanında, sürüm kontrolünü kullanmak, mevcut cevapların hiçbirinin bahsetmediği bir nedenden ötürü yapabileceğiniz en önemli şeydir: sonuçların tekrarlanabilirliği . Günlük mesajlarınızı kullanabilir veya revizyon numarasıyla sonuçlara bir not ekleyebilirseniz, sonuçları yeniden oluşturabildiğinizden emin olabilirsiniz ve kodu kağıtla birlikte yayınlamanız daha iyi olacaktır.

Daha küçük kod parçaları yazmak için birim testi gerekli midir? Peki ya OOP? Daha büyük projeler üzerinde çalışmak yerine "bilimsel programlama" yaparken hızlı ve iyi bir kod yazmak için ne tür yaklaşımlar iyidir?

Birim testi hiçbir zaman gerekli değildir, ancak (a) kodun her şeyden çok birimleri test edebilmeniz için yeterince modüler olması yararlıdır; (b) testler oluşturabilirsiniz. İdeal olarak, beklenen çıktıyı kodla üretmek yerine el ile yazabilirsiniz, ancak kodla üretmek en azından bir şeyin davranışını değiştirip değiştirmediğini size söyleyen regresyon testleri verebilir . Sadece testlerin, test ettikleri koddan daha fazla sorunlu olup olmadığını düşünün.

OOP bir araçtır. Yardımcı olursa kullanın, ancak tek paradigma değil. Sadece prosedürel programlamayı gerçekten bildiğinizi varsayıyorum: bu durumda, o zaman açıklanan bağlamda, işlevsel programlamayı okumaktan OOP'dan ve özellikle de mümkün olduğunda yan etkilerden kaçınma disiplininden daha fazla yararlanacağınızı düşünüyorum. Python çok işlevsel bir tarzda yazılabilir.


4
Taahhüt mesajları için +1; Aslında uygulanamadıkları zaman kod sürümüne bağlı olduklarından, modası geçemeyen yorumlar gibidirler. Eski kodunuzu anlamak için, projenin geçmişine bakmak (değişiklikler makul bir ayrıntı düzeyinde yapılırsa) eski yorumları okumaktan daha kolaydır.
Silly Freak

Yıkılma, git ve Mercurial uygun değil. Git'i (veya Mercurial'ı) Subversion üzerindeki yerel bir depo ile kullanmayı şiddetle savunurum. Yalnız bir kodlayıcıyla Subversion'un kusurları daha az sorun
yaratır,

2
@mcottle, ben şahsen git'i tercih ederim, ancak seçimin aktif dini savaşlardan biri olması nedeniyle, farklılıklarla ilgili detaylara girmenin doğru yer olduğunu düşünmedim. OP'yi alandan uzak tutmaktan başka bir şey kullanmaya teşvik etmek daha iyidir ve karar her durumda kalıcı değildir.
Peter Taylor

21

Yüksek lisans okulunda algoritma ağırlıklı bir kod yazdım. Kırılması zor bir parça. Kaba bir şekilde ifade etmek için, bir veri tabanına bilgi koyma, doğru zamanda alma ve daha sonra tipik olarak herhangi bir matematik için bir kütüphane kullanarak bir kullanıcıya sunmak için veri toplama fikri etrafında birçok programlama sözleşmesi oluşturulmuştur. bu işlemin algoritma ağırlıklı kısımları. Bu programlar için, OOP hakkında duyduğunuz her şey, kısa fonksiyonlara kod kırmak ve mümkün olduğunda bir bakışta her şeyin kolayca anlaşılabilir hale getirilmesi mükemmel bir tavsiyedir. Ancak, algoritma ağırlıklı kod veya karmaşık matematiksel hesaplamaları uygulayan kod ve çok az şey için pek işe yaramaz.

Bilimsel hesaplamalar yapmak için senaryolar yazıyorsanız, muhtemelen içinde kullandığınız denklemler veya algoritmalar ile ilgili makalelere sahipsiniz. Kendi kendinize keşfettiğiniz yeni fikirleri kullanıyorsanız, umarım bunları kendi belgelerinizde yayınlayacaksınız. Bu durumda, kural şudur: Kodunuzun, yayınlanan denklemlerin mümkün olduğunca okumasını istiyorsunuz. İşte Yazılım Mühendisliği ile ilgili bir cevap. Bu yaklaşımı savunan ve neye benzediğini açıklayan 200'den fazla yükseltme içeren bir soru: Kısa değişken isimleri için bir bahane var mı?

Başka bir örnek olarak, fizik araştırma ve mühendisliği için kullanılan bir fizik simülasyon aracı olan Simbody'de bazı harika kod parçacıkları var . Bu snippet'lerin hesaplama için kullanılan bir denklemi gösteren bir yorumu var, ardından mümkün olduğunca uygulanan denklemleri yakından okuyan bir kod var.

ContactGeometry.cpp:

// t = (-b +/- sqrt(b^2-4ac)) / 2a
// Discriminant must be nonnegative for real surfaces
// but could be slightly negative due to numerical noise.
Real sqrtd = std::sqrt(std::max(B*B - 4*A*C, Real(0)));
Vec2 t = Vec2(sqrtd - B, -sqrtd - B) / (2*A);

ContactGeometry_Sphere.cpp:

// Solve the scalar Jacobi equation
//
//        j''(s) + K(s)*j(s) = 0 ,                                     (1)
//
// where K is the Gaussian curvature and (.)' := d(.)/ds denotes differentiation
// with respect to the arc length s. Then, j is the directional sensitivity and
// we obtain the corresponding variational vector field by multiplying b*j. For
// a sphere, K = R^(-2) and the solution of equation (1) becomes
//
//        j  = R * sin(1/R * s)                                        (2)
//          j' =     cos(1/R * s) ,                                      (3)
//
// where equation (2) is the standard solution of a non-damped oscillator. Its
// period is 2*pi*R and its amplitude is R.

// Forward directional sensitivity from P to Q
Vec2 jPQ(R*sin(k * s), cos(k * s));
geod.addDirectionalSensitivityPtoQ(jPQ);

// Backwards directional sensitivity from Q to P
Vec2 jQP(R*sin(k * (L-s)), cos(k * (L-s)));
geod.addDirectionalSensitivityQtoP(jQP);

9
Ayrıca bir tanesini "kodun mümkün olduğunca yayınlanan denklemler gibi okumasını" sağladığı için. Üzgünüz, uzun, anlamlı değişken isimlerinin savunucuları. Bilimsel kodlardaki en anlamlı isimler, zaman zaman kötü, kısa ve kesindir çünkü tam olarak bu, kodun uygulamaya çalıştığı bir bilimsel dergi makalesinde kullanılan kuraldır. Bir dergi makalesinde bulunan denklemleri uygulayan denklem ağırlıklı bir kod parçası için, çoğu zaman gazetede isimlendirmeye olabildiğince yakın olmak en iyisidir ve eğer bu iyi kodlama standartlarına dayanıyorsa, sertleşir.
David Hammen

@DavidHammen: Yüksek lisans öğrencisi olarak buna saygı duyuyorum. Bir programcı olarak, daha sonra , geçici bir yer tutucu bile olsa, her bir değişkenin neyi temsil ettiğini açık bir şekilde İngilizce (veya seçtiğiniz bir dilde) açıklayan her bir işlevin başında dev bir yorum bloğuna sahip olduğunuz konusunda ısrar ediyorum . Bu şekilde en azından geriye bakacak bir referansım var.
tonysdg

1
@DavidHammen Ayrıca, kaynak dosyalarda UTF-8 desteği ve değişken isimler için basit kurallar , çirkin ya λda φyerine çirkin lambda_ya da bunun yerine bildirmeyi ya da phy...
Mathias Ettinger,

1
@ tonysdg Zaten bir referansınız var; "Hammen ve diğerleri (2018)" (veya her neyse) olarak adlandırılır. Değişkenlerin anlamlarını, herhangi bir yorum bloğundan çok daha ayrıntılı olarak açıklayacaktır. Değişken adlarını kağıttaki gösterime yakın tutmanın nedeni, kağıttakileri koddakilere bağlamayı daha kolay hale getirmek için kesindir.
Kimse

17

Bu yüzden, günlük işim California Üniversitesi sistemi için araştırma verilerinin yayınlanması ve korunması. Birkaç kişi yeniden üretilebilirlikten bahsetti ve bence buradaki asıl mesele bu: kodunuzu, bir başkasının denemenizi yeniden oluşturmak için ihtiyaç duyduğunuz herhangi bir şeyi belgeleme şeklini belgelemek ve ideal olarak, her ikisi için de kolaylaştıran bir kod yazmak. Denemenizi yeniden oluşturmak ve sonuçlarınızı hata kaynakları açısından kontrol etmek için.

Ancak daha önce bahsetmediğim, önemli olduğunu düşündüğüm bir şey, fon sağlayan kuruluşların giderek daha fazla veri yayınlamanın bir parçası olarak yazılım yayınlarına baktığını ve yazılım yayıncılığını açık bilim için bir gereksinim haline getirdiği yönünde.

Bu amaçla, genel yazılım geliştiriciler yerine araştırmacıları hedef alan belirli bir şey istiyorsanız, Yazılım Marangozluğu organizasyonunu yeterince tavsiye edemiyorum . Atölyelerinden birine katılabilirseniz , harika; Yapmanız gereken tek şey zamanınız / erişiminiz varsa, bilimsel hesaplama en iyi uygulamalarıyla ilgili makalelerinin bir kısmını okumak ise , bu da iyidir. İkincisi:

Bilim adamları bu amaçlar için tipik olarak kendi yazılımlarını geliştirirler, çünkü bunu yapmak için etki alanına özgü bilgiler gereklidir. Sonuç olarak, son araştırmalar bilim insanlarının genellikle zamanlarının% 30'unu veya daha fazlasını yazılım geliştirmek için harcadıklarını bulmuşlardır. Bununla birlikte, bunların% 90'ı veya daha fazlası birincil olarak kendi kendini eğitmektedir ve bu nedenle, bakım yapılabilir kod yazma, sürüm kontrolü ve sorun izleyiciyi kullanma, kod incelemeleri, birim testi ve görev otomasyonu gibi temel yazılım geliştirme uygulamalarına maruz kalmamaktadır.

Yazılımın başka bir deneysel aygıt olduğuna ve herhangi bir fiziksel aygıt kadar dikkatli bir şekilde yapılması, kontrol edilmesi ve kullanılması gerektiğine inanıyoruz. Bununla birlikte, çoğu bilim adamı laboratuar ve saha ekipmanlarını doğrulamak için dikkatli olsa da, çoğu yazılımlarının ne kadar güvenilir olduğunu bilmiyor. Bu, yayınlanan araştırmanın merkezi sonuçlarını etkileyen ciddi hatalara yol açabilir. ...

Ek olarak, yazılım genellikle tek bir projeden daha fazla kullanıldığından ve sıklıkla diğer bilim adamları tarafından kullanıldığından, hesaplama hatalarının bilimsel süreç üzerinde orantısız etkileri olabilir. Bu basamaklı etki türü, başka bir grubun kodundaki bir hatanın yayınlanıncaya kadar keşfedilmemesi durumunda, bazı belirgin gerilemelere neden oldu.

Önerdikleri uygulamaların üst düzey bir taslağını:

  1. Bilgisayarlar için değil, insanlar için programlar yazın
  2. Bilgisayar işi yapsın
  3. Artımlı değişiklikler yapın
  4. Kendini tekrar etme (veya başkalarını)
  5. Hatalar için plan yap
  6. Yazılımı yalnızca doğru çalıştıktan sonra optimize edin
  7. Mekanik değil, belge tasarımı ve amacı
  8. işbirliği yapmak

Kağıt, bu noktaların her biri üzerinde önemli bir ayrıntıya girer.


16

Bazı standart işler yapıldığında, yazmak çok daha hızlı olacak ve programın azlığı nedeniyle benzer bir okunabilirlik seviyesi olacaktı, OOP diyen bir kod yazmak gerçekten mantıklı geliyor mu?

Kişisel cevap:
Bilimsel amaçlar için çok fazla kod yazarım. Daha küçük komut dosyaları için, genel iyi programlama uygulamalarını izlemeye çalışıyorum (örn. Sürüm kontrolünü kullanmak, değişken isimleri ile kendi kendini kontrol etmeyi uygulamak). Veri kümesini hızlıca açmak veya görselleştirmek için bir şeyler yazıyorsam, OOP ile uğraşmıyorum.

Genel Cevap:
"Bu değişir." Ancak, bir programlama kavramı veya paradigmaların ne zaman kullanılacağını anlamakta zorlanıyorsanız, işte düşünmeniz gereken birkaç şey:

  • Ölçeklenebilirlik: Senaryo tek başına mı olacak yoksa sonunda daha büyük bir programda mı kullanılacak? Eğer öyleyse, OOP kullanan daha büyük programlama mı? Komut dosyanızdaki kod, büyük programa kolayca entegre edilebilir mi?
  • Modülerlik: Genel olarak kodunuz modüler olmalıdır. Ancak, OOP kodları çok özel bir şekilde parçalara böler. Bu tür modülerlik (yani senaryoyu sınıflara bölmek) yaptığınız şey için bir anlam ifade ediyor mu?

Nasıl daha yeni başlayacağımı ve bu daha küçük, daha hızlı projelere nasıl temiz bir şekilde programlanacağını bilmek istiyorum.

# 1: Dışarıdakileri tanıyın:
"Sadece" komut dosyası yazmanıza rağmen (ve sadece bilim bileşenini önemsiyorsanız), farklı programlama kavramları ve paradigmaları hakkında bilgi edinmek için biraz zaman ayırmalısınız. Bu şekilde ne kullanmak ve ne zaman kullanmak istemediğinizi daha iyi anlayabilirsiniz. Bu biraz korkutucu gelebilir. Ve hala, “Nereden başlarım / neye bakmaya başlarım?” Sorusu olabilir. Sonraki iki mermi noktasında iyi bir başlangıç ​​noktası açıklamaya çalışıyorum.

# 2: Yanlış olduğunu bildiğin şeyi düzeltmeye başla:
Şahsen, yanlış olduğunu bildiğim şeylerle başlardım. Bazı sürüm kontrolleri alın ve bu değişken isimlerle daha iyi olmak için kendinizi disipline etmeye başlayın (bu ciddi bir mücadeledir). Bildiğiniz şeyi düzeltmek yanlış olabilir. Ancak deneyimlerime göre, bir şeyi tamir etmenin beni başka bir şeye vb. Götürdüğünü gördüm. Bilmeden önce, yanlış yaptığım 10 farklı şeyi açıkladım ve nasıl düzelteceğimi ya da nasıl temiz bir şekilde uygulayacağımı öğrendim.

# 3: Bir programlama partneri edinin:
Sizin için "yeniden başlamak" resmi sınıflara girmeyi içermiyorsa, bir geliştirici ile ekip kurmayı ve kodunuzu gözden geçirmelerini istemeyi düşünün. Yaptıklarınızın bilim bölümünü anlamadılar bile, kodunuzu daha zarif hale getirmek için neler yapabileceğinizi size söyleyebilirler.

# 4: Konsorsiyumları
araştırın : Hangi bilimsel alanda bulunduğunuzu bilmiyorum. Ama bilim dünyasında yaptıklarınıza bağlı olarak, konsorsiyumları, çalışma gruplarını veya konferans katılımcılarını aramayı deneyin. O zaman üzerinde çalıştıkları herhangi bir standart olup olmadığını görün. Bu sizi bazı kodlama standartlarına götürebilir. Mesela ben çok fazla mekansal çalışma yapıyorum. Konferanslara ve çalışma gruplarına bakmak beni Açık Alan Mekansal Konsorsiyumu'na yönlendirdi . Yaptıklarından biri, mekansal gelişim için standartlar üzerinde çalışmak.

Umarım bu yardımcı olur!


Yan not: Örnek olarak OOP kullandığını biliyorum. Sadece OOP kullanarak kod yazmanın nasıl yapıldığını saptadığımı düşünmenizi istemedim. Bu örnekle devam eden bir cevap yazmak daha kolaydı.


Bence # 3 en önemli konudur - deneyimli bir programcı OP'ye ihtiyaç duyduğu kavramları (# 1), komut dosyalarını nasıl daha iyi düzenleyebileceğini ve sürüm kontrolünü (# 2) nasıl kullanabileceğini söyleyebilir.
Doc Brown,

16

Unix prensibine sadık kalmayı tavsiye ederim: Basit Tut, Aptal! (ÖPMEK)

Veya başka bir yolla: Bir seferde bir şey yapın ve iyi yapın.

Bu ne anlama geliyor? Her şeyden önce, bu işlevlerinizin kısa olması gerektiği anlamına gelir. Birkaç saniye içerisinde amaç, kullanım ve uygulamada tam olarak anlaşılamayan fonksiyonlar kesinlikle çok uzun. Her birinin kendi işlevi olması gereken, aynı anda birkaç şey yapması muhtemeldir. Öyleyse bölün.

Kod satırları bağlamında benim sezgiselim, 10 satırın iyi bir işlev olduğu ve 20'nin ötesindeki herhangi bir şeyin büyük olasılıkla berbat olduğu yönünde. Diğer insanların başka sezgisel özellikleri var. Önemli olan kısım, uzunluğu anında kavradığınız bir şeye indirmektir.

Uzun bir işlevi nasıl bölersiniz? İlk önce, tekrar eden kod kalıplarını ararsınız. Sonra bu kod kalıplarını hesaba katar, onlara açıklayıcı bir ad verir ve kod küçülmesini izlersiniz . Gerçekten, en iyi yeniden düzenleme, kod boyutunu azaltan yeniden düzenlemedir.

Bu, özellikle söz konusu fonksiyon kopyala-yapıştır ile programlandığında geçerlidir. Ne zaman böyle bir tekrarlanan desen görüyorsanız, bunun muhtemelen kendi işlevine dönüştürülmesi gerektiğini anında bilirsiniz. Bu, Kendinizi Tekrarlama (KURU) ilkesidir . Ne zaman kopyala-yapıştır'a bas, yanlış bir şey yapıyorsun! Bunun yerine bir işlev oluşturun.

Fıkra
Bir keresinde, her biri yaklaşık 500 satırlık fonksiyonları olan kodu yeniden gözden geçirmek için birkaç ay harcadım. Yaptıktan sonra, toplam kod yaklaşık bin satır daha kısadı; Kod satırları açısından negatif çıktı üretmiştim. Şirkete borçluyum ( http://www.geekherocomic.com/2008/10/09/programmers-salary-policy/index.html ). Yine de, bunun yaptığım en değerli işlerimden biri olduğuna kesinlikle inanıyorum ...

Bazı işlevler uzun olabilir çünkü birbiri ardına birkaç farklı şey yapıyorlar. Bunlar KURU ihlali değildir, ancak bölünebilirler. Sonuç, sık sık, orijinal fonksiyonların ayrı adımlarını uygulayan bir çok işlevsellik çağrısı yapan yüksek seviyeli bir fonksiyondur. Bu genellikle kod boyutunu artırır, ancak eklenen işlev adları, kodu daha okunaklı hale getirmede harikalar yaratır. Çünkü şimdi, tüm adımlarının açıkça isimlendirildiği bir üst düzey işleve sahipsiniz. Ayrıca, bu bölünmeden sonra, hangi adımın hangi veriler üzerinde çalıştığı açıktır. (İşlev değişkenleri. Genel değişkenleri kullanmazsınız, değil mi?)

Bu tür bir seksiyonel fonksiyon bölünmesi için iyi bir buluşsal yöntem, bir bölüm yorumu yazmaya istekli olduğunuzda veya kodunuzda bir bölüm yorumu bulduğunuzda olur. Bu, büyük olasılıkla, fonksiyonunuzun bölünmesi gereken noktalardan biri. Bölüm yorumu ayrıca yeni işlev için bir ad ilham verebilir.

KISS ve DRY prensipleri sizi uzun sürebilir. Derhal OOP vb. İle başlamak zorunda değilsiniz, çoğu zaman sadece bu ikisini uygulayarak büyük basitleştirmeler elde edebilirsiniz. Ancak, uzun vadede OOP ve diğer paradigmalar hakkında bilgi sahibi olmanızı sağlar çünkü program kodunuzu daha net hale getirmek için kullanabileceğiniz ek araçlar sunar.

Son olarak, her işlemi bir taahhütle kaydedin. Bir şeyi yeni bir işleve çarpar , bu bir taahhüt . İki işlevi birer birime ayırıyorsunuz çünkü gerçekten aynı şeyi yapıyorlar, bu bir taahhüt . Bir değişkeni yeniden adlandırırsanız, bu bir taahhüt olur . Sık sık taahhüt. Eğer bir gün geçerse ve sen taahhüt etmediysen, muhtemelen yanlış bir şeyler yapmışsın demektir.


2
Uzun yöntemleri bölme konusunda harika noktalar. Fıkradan sonraki ilk paragrafa ilişkin bir başka sezgisel buluş: yönteminiz mantıksal olarak bölümlere ayrılabilir ve eğer her bölümün ne yaptığını açıklayan bir yorum yazmanız istenirse, yorumlarda ayrılmaları gerekir. İyi haber, bu yorumlar muhtemelen size yeni yöntemlerin ne olacağı konusunda iyi bir fikir verecektir.
Jaquez

@ Jaquez Ah, bunu tamamen unuttum. Bana hatırlattığın için teşekkürler. Bunu eklemek için cevabımı güncelledim :-)
cmaster

1
Harika noktalar, "DRY" nin en önemli tek faktör olduğunu söylemek için bunu basitleştirmek istiyorum. “Tekrarları” tanımlamak ve bunları kaldırmak, diğer tüm programlama yapılarının temel taşıdır. Başka bir deyişle, tüm programlama yapıları, en azından kısmen, DRY kodunu oluşturmanıza yardımcı olmak için oradadır. "Hiçbir Çoğaltma Yok" diyerek başlayın ve ardından tanımlama ve yok etme alıştırması yapın. Neyin yinelenebileceği konusunda çok açık olun - benzer bir kod olmasa bile, yinelenen işlevsellik olabilir ...
Bill K

11

Sürüm kontrolünün birçok probleminizi hemen çözeceği konusunda diğerleriyle aynı fikirdeyim. özellikle:

  • Hangi değişikliklerin yapıldığına ya da bir dosyanın çok sayıda kopyasına sahip olduğuna dair bir liste tutmanıza gerek yok, çünkü sürüm kontrolünün ilgilendiği şey bu.
  • Üzerine yazma, vb. Nedeniyle kaybolan hiçbir dosya yok (yalnızca temel hususlara sadık kaldığınız sürece; örneğin, "geçmişi yeniden yazmaktan kaçının")
  • Eski yorumlara, kodlara vb. İhtiyaç duyulmasına gerek yok; Sürüm kontrolüne karar verdiklerinde, onları kaçırmaktan çekinmeyin. Bu çok özgürleştirici hissedebilir!

Düşünmeyin derim ki: sadece git git. Basit komutlara bağlı kalın (örneğin sadece tek bir masterdal), belki bir GUI kullanın ve iyi olmalısınız. Bonus olarak ücretsiz yayınlama ve yedekleme için gitlab, github, vb. Kullanabilirsiniz;)

Bu cevabı yazmamın sebebi yukarıda bahsetmediğim iki şeyi ele almaktı. Birincisi, iddiaları birim testine hafif bir alternatif olarak kullanmaktır . Ünite testleri, fonksiyon / modül / dışarısı test edilme eğiliminde olan her ne olursa olsun: genellikle bir işleve bazı veriler gönderir, bir sonucu geri alır, sonra bu sonucun bazı özelliklerini kontrol eder. Bu genellikle iyi bir fikirdir, ancak birkaç nedenden dolayı uygunsuz olabilir (özellikle “atma” kodu için):

  • Ünite testleri, işleve hangi verileri vereceklerine karar vermelidir. Bu veriler gerçekçi olmalı (aksi takdirde test edilecek küçük bir nokta yoktur), doğru biçime sahip olmalı vs.
  • Birim testlerinin iddia etmek istediklerine "erişimi" olması gerekir. Özellikle, birim testleri, bir fonksiyon içindeki ara verilerin hiçbirini kontrol edemez; bu işlevi daha küçük parçalara ayırmamız, bu parçaları test etmemiz ve bunları başka bir yere bağlamamız gerekir.
  • Birim testlerinin de programla ilgili olduğu varsayılmaktadır. Örneğin, son süitlerden bu yana büyük değişiklikler olmuşsa ve testler artık kullanılmayan kod için bile bir sürü test olabilirse test paketleri "bayat" olabilir.

Bir programın normal çalışması sırasında kontrol edildiklerinden, iddiaların bu sakıncaları yoktur. Özellikle:

  • Normal program yürütmenin bir parçası olarak çalıştırıldıklarından, oynayacak gerçek dünya verilerimiz var. Bu, ayrı bir işlem gerektirmez ve (tanım gereği) gerçekçidir ve doğru biçime sahiptir.
  • Beyanlar kodun herhangi bir yerine yazılabilir, bu nedenle kontrol etmek istediğimiz verilere erişimi olan her yere koyabiliriz. Bir fonksiyondaki bazı ara değerleri test etmek istiyorsak, bu fonksiyonun ortasına bazı iddialar koyabiliriz!
  • Satır içi yazılmış olduklarından, iddialar kodun yapısıyla "senkronizasyondan çıkarılamaz". Eğer iddiaların varsayılan olarak kontrol edildiğinden emin olursak, programın bir sonraki çalıştırışında başarılı olup olmadıklarını hemen göreceklerinden hemen göreceğimiz için “bayat” olmalarından endişe etmemize gerek yoktur!

Hızı bir faktör olarak belirtirsiniz; bu durumda iddia kontrolünün bu döngüde istenmeyebilir (ancak kurulum ve sonraki işlemleri kontrol etmek için yine de yararlı olabilir). Ancak, iddiaların hemen hemen bütün uygulamaları onları kapatmak için bir yol sağlar; örneğin , Python'da-O seçenekle çalıştırılarak devre dışı bırakılabilirler (bunu bilmiyordum, çünkü daha önce iddialarımı hiçbir zaman devre dışı bırakma gereği duymadım). Onları açık bırakmanı tavsiye ederim .varsayılan olarak; Kodlama / hata ayıklama / test etme döngüsünüz yavaşlarsa, verilerinizin daha küçük bir alt kümesiyle test yapmaktan veya test sırasında bazı simülasyonlarda daha az yineleme yapmak veya daha fazla işlem yapmak daha iyi olabilir. Test dışı çalışmalarda iddiaları devre dışı bırakmakla performans nedenleriyle sonuçlanırsanız, ilk önerdiğim şey , gerçekte yavaşlamanın kaynağı olup olmadıklarını ölçmektir ! (Performans darboğazları söz konusu olduğunda kendimizi kandırmak çok kolaydır)

Son tavsiyem, bağımlılıklarınızı yöneten bir inşa sistemi kullanmak olacaktır. Kişisel olarak Nix'i bunun için kullanıyorum , ancak Guix hakkında da iyi şeyler duydum . Docker gibi, bilimsel bir bakış açısına göre çok daha az kullanışlı fakat belki biraz daha tanıdık alternatifler de var.

Nix gibi sistemler daha yeni popüler hale geldi (bazıları) ve bazıları sizin tanımladığınız gibi "atmak" için onları fazladan öldürdüğünü düşünüyor olabilir, ancak bilimsel hesaplamaların tekrarlanabilirliğine olan faydaları çok büyük. Bir deneme çalıştırmak için şöyle bir kabuk betiği düşünün, örneğin run.sh:

#!/usr/bin/env bash
set -e
make all
./analyse < ./dataset > output.csv

Bunun yerine, bunun yerine bir Nix "türevine" yeniden yazabiliriz (örn. run.nix):

with import <nixpkgs> {};
runCommand "output.csv" {} ''
  cp -a ${./.} src
  cd src
  make all
  ./analyse < ./dataset > $out
''

Arasındaki şeyler ''...''dışında biz önce sahip aynıdır, bash kodudur ${...}(bu durumda diğer dizeleri içeriğinde "ek yeri" için kullanılabilir ./.içeren dizinin yoluna genişleyecektir, run.nix). with import ...Hat Nix en ithal standart kütüphane sağlar, runCommandbash kodu çalıştırmak için. Deneyimizi, nix-build run.nixgibi bir yol verecek olan kullanarak deneyebiliriz /nix/store/1wv437qdjg6j171gjanj5fvg5kxc828p-output.csv.

Peki bu bizi ne satın alıyor? Nix, yalnızca açıkça talep ettiğimiz şeylere erişebilen "temiz" bir ortam kurar. Özellikle $HOMEkurduğumuz sistem yazılımı gibi herhangi bir değişkene erişimi yoktur . Bu, sonucu, kurduğumuz ~/.configprogramların içeriği veya içerikleri gibi mevcut makinemizin ayrıntılarından bağımsız kılar ; AKA, diğer insanların sonuçlarımızı çoğaltmasını engelleyen şeyler! Bu yüzden onu ekledim.cpkomut, çünkü projeye varsayılan olarak erişilemez. Sistemin yazılımının bir Nix komut dosyasında mevcut olmaması sinir bozucu görünebilir, ancak diğer yoldan da gider: Sistemimizde (Nix dışında) bir komut dosyasında faydalanmak için yüklü hiçbir şeye ihtiyacımız yoktur; biz sadece bunu istiyoruz ve Nix kapanacak ve ne gerekiyorsa alacak / derleyecektir (çoğu şey ikili dosya olarak indirilecek; standart kütüphane de çok büyük!). Örneğin, bu dillerin bazı sürümleri için bir grup belirli Python ve Haskell paketi, artı başka bir çöplük istiyorsak (çünkü neden olmasın?):

with import <nixpkgs> {};
runCommand "output.csv"
  {
    buildInputs = [
      gcc49 libjson zlib
      haskell.packages.ghc802.pandoc
      (python34.withPackages (pyPkgs: [
        pyPkgs.beautifulsoup4 pyPkgs.numpy pyPkgs.scipy
        pyPkgs.tensorflowWithoutCuda
      ]))
    ];
  }
  ''
    cp -a ${./.} src
    cd src
    make all
    ./analyse < ./dataset > $out
  ''

Aynı nix-build run.nixşey, ilk önce istediğimiz her şeyi alarak (ve daha sonra istersek hepsini önbelleğe almakla) bunu gerçekleştirir. Çıktı (çağrılan herhangi bir dosya / dizin $out), tükürme yolu olan Nix tarafından saklanacaktır. İstediğimiz tüm girdilerin (kod içeriği, diğer paketler, adlar, derleyici bayrakları vb.) Şifreli karması ile tanımlanır; bu diğer paketler sağlamalarının tanımlanır onların girişlerine ve bu yüzden sağ arka benzeri bash derlenmiş ve GCC sürümü derlenmiş GCC sürümüne, her şey için ili ve tam bir zinciri var öyle üzerinde!

Umarım, bunun bize bilimsel kod için çok şey satın aldığını ve başlaması oldukça kolay olduğunu gösterdim. Aynı zamanda bilim insanları tarafından çok ciddiye alınmaya başlıyor, örneğin (en iyi Google hit) https://dl.acm.org/citation.cfm?id=2830172 bu yüzden geliştirmek için değerli bir beceri olabilir (programlama gibi)


2
Çok detaylı yararlı cevap - Diğer cevapları gerçekten seviyorum, ancak iddialar çok yararlı bir ilk adım gibi görünüyor.
heather

9

Tam teşekküllü versiyon kontrolü olmadan + ambalaj + ünite bir tür zihniyet testi yapar (ki bu bir noktada başarmaya çalışmanız gereken iyi programlama uygulamalarıdır), uygun olacağını düşündüğüm bir ara çözüm Jüpiter Notebook'u kullanmak . Bu, bilimsel hesaplama ile daha iyi entegre görünüyor.

Düşüncelerinizi kodla karıştırabilmeniz avantajına sahiptir; Bir yaklaşımın neden diğerinden daha iyi olduğunu açıklamak ve geçici olarak eski kodu olduğu gibi bırakmak. Hücreleri doğru kullanmanın yanı sıra, doğal olarak kodunuzu parçalamaya ve anlamaya yardımcı olabilecek işlevler halinde düzenlemenize yönlendirir.


1
Üstelik bu, tekrarlanabilirliğe gerçekten yardımcı oluyor - örneğin bir yayın figürü oluşturmak için aynı kodu çalıştırabilir veya aylar önce bıraktığınız bir şeye geri dönüp belki de yorumcu yorumlarını da dahil edebilirsiniz.
afaulconbridge

Daha fazla okumak isteyen biri için bu aynı zamanda okuryazar programlama olarak da bilinir.
saat

6

En iyi cevaplar zaten iyi, ancak bazı sorularınızı doğrudan ele almak istedim.

Daha küçük kod parçaları yazmak için birim testi gerekli midir?

Kodun boyutu, birim testlerine duyulan ihtiyaçla doğrudan ilişkili değildir. Dolaylı olarak ilgilidir: ünite testleri karmaşık kod tabanlarında daha değerlidir ve küçük kod tabanları genellikle daha büyük olanlar kadar karmaşık değildir.

Birim testleri, hata yapmanın kolay olduğu yerlerde veya bu kodun birçok uygulamasına sahip olduğunuzda parlar. Ünite testleri, mevcut gelişmelerde size yardımcı olmak için çok az şey yapar, ancak gelecekte mevcut kodun aniden hatalı davranmasına neden olan hatalar yapmanıza engel olmak için çok şey yaparlar (o şeye dokunmasanız bile).

Diyelim ki Kütüphane A'nın sayıların karesini yaptığı bir uygulama var ve Kütüphane B Pisagor teoremini uygular. Açıkçası, B, A'ya bağlı. A kütüphanesinde bir şeyi düzeltmeniz gerekiyor ve diyelim ki, onları kareler yerine sayıları küpleyen bir hatayı tanıtıyorsunuz.

Kütüphane birdenbire kötü çalışmaya, muhtemelen istisnalar atmaya veya sadece yanlış çıktılar vermeye başlayacaktır. Ve K kütüphanesinin sürüm tarihine baktığınızda, dokunulmadığını görürsünüz. Sorunlu sonuç, neyin yanlış olabileceğine dair hiçbir fikriniz olmadığı ve sorunun A'da olduğunu fark etmeden önce B'nin davranışını ayıklamanız gerekeceğidir.

Birim testlerine girin. Bu testler, A kütüphanesinin amaçlandığı gibi çalıştığını onaylar. Kitaplık A'da hatalı sonuçlara neden olan bir hata ortaya çıkarırsanız, birim testleriniz bunu yakalar. Bu nedenle, B kütüphanesinde hata ayıklamaya çalışırken sıkışıp kalmazsınız.
Bu sizin kapsamınızın dışındadır, ancak sürekli bir entegrasyon geliştirmede, birileri bir kod girdiğinde birim testleri gerçekleştirilir, bu da en kısa zamanda bir şeyi kırdığınızı bildiğiniz anlamına gelir.

Özellikle karmaşık matematiksel işlemler için birim testleri bir nimet olabilir. Birkaç örnek hesaplama yaparsınız ve sonra hesaplanan çıktınızı ve gerçek çıktınızı karşılaştıran birim testlerini yazarsınız (aynı giriş parametrelerine dayanarak).

Bununla birlikte, birim testlerinin iyi kod oluşturmanıza yardımcı olmayacağına , ancak bunun yerine devam etmenize yardımcı olacağını unutmayın . Genellikle bir kez kod yazarsanız ve asla tekrar ziyaret etmezseniz, birim testleri daha az faydalı olacaktır.

Peki ya OOP?

OOP, farklı varlıklar hakkında düşünmenin bir yoludur, örneğin:

Bir zaman Customerbir satın almak istiyor Product, o konuşur Vendorbir alacak Order. Accountantİrade ardından ödeme Vendor.

Bunu, işlevsel bir programcının şeyler hakkında nasıl düşündüğünü karşılaştırın:

Bir müşteri istediğinde purchaseProduct(), o talktoVendor()yüzden olacak sendOrder()ona. Muhasebeci daha sonra olacak payVendor().

Elmalar ve Portakallar. İkisi de nesnel olarak diğerinden daha iyi değil. Dikkat edilmesi gereken ilginç bir şey, OOP için Vendoriki kez bahsedilmesidir ancak aynı şeyi ifade eder. Ancak, işlevsel programlama için talktoVendor()ve payVendor()iki ayrı şeydir.
Bu yaklaşımlar arasındaki farkı gösterir. Bu iki eylem arasında çok sayıda paylaşılan satıcıya özgü mantık varsa, OOP kod çoğaltmanın azaltılmasına yardımcı olur. Bununla birlikte, ikisi arasında paylaşılan bir mantık yoksa, bunları bir tek Vendorolarak birleştirmek bir işin boşa gitmesidir (ve dolayısıyla işlevsel programlama daha etkilidir).

Çoğu zaman, matematiksel ve bilimsel hesaplamalar, örtük paylaşılan mantık / formüllere dayanmayan farklı işlemlerdir. Bu nedenle, işlevsel programlama OOP'dan daha sık kullanılır.

Daha büyük projeler üzerinde çalışmak yerine "bilimsel programlama" yaparken hızlı ve iyi bir kod yazmak için ne tür yaklaşımlar iyidir?

Sorunuz, "iyi, temiz kod" tanımının, bilimsel programlama yapıp yapmamanız veya daha büyük (daha fazla işletme demek olduğunu sanıyorum) projelerinizi değiştirip değiştirmeyeceği anlamına gelir.

İyi kodun tanımı değişmez. Ancak karmaşıklıktan kaçınma ihtiyacı (temiz kod yazılarak yapılabilir) değişiyor.

Aynı argüman buraya geri dönüyor.

  • Eski kodu asla tekrar ziyaret etmez ve bölümlendirmeye gerek duymadan mantığı tam olarak anlarsanız, işleri sürdürmek için fazla çaba harcamayın.
  • Eski kodu tekrar ziyaret ederseniz veya gerekli mantık, hepsini bir kerede çözmeniz için çok karmaşıksa (bu nedenle çözümleri bölümlendirmenizi gerektirir), daha sonra temiz ve tekrar kullanılabilir bir şekilde yazmaya odaklanın.

Bu soruları soruyorum çünkü sıklıkla, programlamanın kendisi süper karmaşık değildir. Bu, programlama ile test ettiğim veya araştırdığım matematik veya bilim hakkında daha fazla.

Burada yaptığınız ayrımı anlıyorum, ancak mevcut koda tekrar baktığınızda, hem matematiğe hem de programlamaya bakıyorsunuz. Eğer ikisinden biri yapmacık veya karmaşık, o zaman okumak için mücadele edeceğiz.

Örneğin, iki değişken ve bir fonksiyonun muhtemelen üstesinden gelebileceği bir sınıf gerekli midir?

OOP prensipleri bir yana, bazı veri değerlerini barındırmak için sınıfları yazmamın asıl nedeni, yöntem parametrelerini ve dönüş değerlerini bildirmeyi basitleştirmesidir . Örneğin, bir konum kullanan (lat / lon çifti) çok fazla yönteme sahipsem, hızlı bir şekilde float latitude, float longitudeyazmak zorunda kalmadan yorulurum ve yazmayı tercih ederim Location loc.

Bu, yöntemlerin genellikle bir değer döndürdüğünü (daha fazla değer döndürmek için dile özgü özellikler olmadığı sürece) ve bir konum gibi şeyler, iki değer (lat + lon) döndürmenizi isteyeceği zaman daha da karmaşıklaşır. Bu Location, kodunuzu basitleştirmek için bir sınıf oluşturmaya teşvik eder .

Örneğin, iki değişken ve bir fonksiyonun muhtemelen üstesinden gelebileceği bir sınıf gerekli midir?

Unutulmaması gereken diğer ilginç bir şey, OOP'yi veri değerlerini ve yöntemlerini karıştırmadan kullanabilmenizdir. Burada her geliştirici kabul etmiyor (bazıları buna antipattern diyor), ancak ayrı veri sınıflarına (değer alanlarını depolar) ve mantık sınıflarına (mağaza yöntemlerine) sahip olduğunuz anemik veri modellerine sahip olabilirsiniz .
Bu, elbette, bir spektrumda. Kusursuz anemik olmanıza gerek yok, uygun gördüğünüzde yu kullanabilirsiniz.

Örneğin, bir kişinin adını ve soyadını basit bir şekilde birleştiren bir yöntem Personsınıfın içinde yer alabilir, çünkü bu gerçekten "mantık" değil, hesaplanmış bir değerdir.

(Bunları da genellikle programın hızının daha hızlı olması tercih edilen durumlar olduğunu göz önünde bulundurun - bir simülasyonun 25.000.000'den fazla zaman adımını çalıştırırken, olmasını istersiniz.)

Bir sınıf daima alanlarının toplamı kadar büyüktür. Locationİki floatdeğerden oluşan tekrar örneğe bakıldığında , burada tek bir Locationnesnenin iki ayrı floatdeğer kadar hafıza alacağını not etmek önemlidir .

Bu anlamda, OOP kullanıp kullanmamanız önemli değil. Hafıza ayak izi aynıdır.

Performansın kendisi de geçmek için büyük bir engel değildir. Örneğin global bir yöntem veya sınıf yöntemini kullanma arasındaki farkın çalışma zamanı performansı ile ilgisi yoktur, ancak derleme zamanı bytecode oluşturma ile ilgisi vardır.

Bunu şu şekilde düşünün: Pasta tarifimi İngilizce mi yoksa İspanyolca mı yazmam, pastanın pişmesi 30 dakika alacağı gerçeğini değiştirmez (= çalışma süresi performansı). Tarifin dilini değiştiren tek şey, aşçı malzemeyi nasıl karıştırdığıdır (= bytecode derleme).

Özellikle Python için, çağrmadan önce kodu açıkça önceden derlemenize gerek yoktur. Ancak, önceden derleme yapmadığınızda, kodu çalıştırmaya çalışırken derleme gerçekleşir. "Çalışma zamanı" derken, yürütmeyi önceden alabilecek derlemeyi değil yürütmeyi kastediyorum.


6

Temiz bilimsel kodun faydaları

  • ... programlama kitaplarına bakarken, genellikle daha büyük projelerde ele alınacak gibi görünüyor.

  • ... bazı standart şeyler yapıldığında, yazmak çok daha hızlı olacak ve programın azlığından dolayı benzer bir okunabilirlik seviyesi olacaktı.

Kodunuzu gelecekteki kodlayıcı perspektifinden değerlendirmek faydalı olabilir.

  • Bu dosyayı neden açtılar?
  • Ne arıyorlar?

Tecrübelerime göre

Temiz kod, sonuçlarınızı doğrulamayı kolaylaştırabilir

  • Programınızı çalıştırmak için kullanıcıların tam olarak ne yapmaları gerektiğini bilmelerini kolaylaştırın.
  • Bireysel algoritmaların ayrı ayrı karşılaştırılabilmesi için programınızı bölmek isteyebilirsiniz.

  • İlişkili olmayan bir işlemin başka bir işlemin farklı şekilde davranmasına neden olduğu, sezgisel yan etkileri olan işlevler yazmaktan kaçının. Bundan kaçınamıyorsanız, kodunuzun neye ihtiyacı olduğunu ve nasıl ayarlanacağını belgeleyin.

Temiz kod gelecekteki kodlayıcılar için örnek kod işlevi görebilir

Açık yorumlar (işlevlerin nasıl çağrılması gerektiğini içerenler de dahil olmak üzere) ve iyi ayrılmış işlevler, işinizden işe yarar bir şeyler yapmanın bir başkasının (veya geleceğiniz) başlamasının ne kadar süreceği konusunda büyük bir fark yaratabilir.

Buna ek olarak, algoritmalarınız için gerçek bir "API" yapmak, komut dosyalarınızı başkalarının kullanması için gerçek bir kütüphaneye koymaya karar verirseniz daha iyi hazırlanmanızı sağlayabilir.

öneriler

"Cite" matematiksel formülleri kullanarak yorumlar.

  • Özellikle optimizasyonlar (trig kimlikleri, Taylor serisi, vb.) Kullanıyorsanız, "alıntı" matematiksel formüllere yorumlar ekleyin.
  • Formülü kitaptan John Smith Method from Some Book 1st Ed. Section 1.2.3 Pg 180aldıysanız, bir web sitesinde veya bir gazetede formülü bulduysanız, bir alıntı da ekleyin .
  • "Yalnızca bağlantı" yorumlarından kaçınmanızı öneririm, kişilerin Google'a girmesine izin vermek için bir yere göre adı belirlediğinizden emin olun , eski iç sayfalara yönlendiren bazı "yalnızca bağlantı" yorumlarına rastladım ve çok sinir bozucu olabiliyor .
  • Unicode / ASCII'de okunması hala kolaysa, yorumunuzdaki formülü yazmaya çalışabilirsiniz, ancak bu çok garipleşebilir (kod yorumları LaTeX değildir).

Yorumları akıllıca kullanın

Kodunuzun okunabilirliğini iyi değişken adları / işlev adları kullanarak geliştirebilirseniz, önce bunu yapın. Yorumları kaldırıncaya kadar sonsuza dek sadık kalmaya devam edeceğinizi unutmayın, bu nedenle tarihi geçmeyecek yorumlar yapmaya çalışın.

Açıklayıcı değişken isimleri kullan

  • Tek harfli değişkenler bir formülün parçasıysa en iyi seçenek olabilir.
  • Gelecekteki okuyucuların yazdığınız koda bakabilmesi ve uyguladığınız denklemle karşılaştırması çok önemli olabilir.
  • Uygun olduğunda, gerçek anlamını açıklamak için buna bir sonek eklemeyi düşünün, örn. xBar_AverageVelocity
  • Daha önce de belirtildiği gibi, bir yorumda adıyla kullandığınız formülü / yöntemi açıkça belirtmenizi öneririm.

Programınızı bilinen iyi ve bilinen kötü verilere karşı çalıştırmak için kod yazın.

Daha küçük kod parçaları yazmak için birim testi gerekli midir?

Birim testinin faydalı olabileceğini düşünüyorum, bilimsel kod için en iyi birim test yönteminin bilinen kötü ve iyi veriler üzerinde çalışan bir dizi test olduğunu düşünüyorum.

Algoritmanızı çalıştırmak için bir kod yazın ve sonucun beklediğinizden ne kadar farklı olduğunu görmek için kontrol edin. Bu, hatalı pozitif sonuçlara neden olan bir şeyi yanlışlıkla kodladığınız ya da işlevin her zaman aynı değeri döndürmesine neden olan bir hata yaptığınız (muhtemelen çok kötü ve bulmak zor) sorunları bulmanıza yardımcı olacaktır.

Bunun, herhangi bir soyutlama düzeyinde yapılabileceğini unutmayın. Örneğin, bir desen eşleştirme algoritmasının tamamını test edebilirsiniz veya optimizasyon işleminizde iki sonuç arasındaki mesafeyi hesaplayan bir işlevi test edebilirsiniz. İlk önce sonuçlarınız için en önemli alanlardan ve / veya kodun en çok ilgilendiğiniz kısımlarından başlayın.

Yeni test durumları eklemeyi kolaylaştırın, "yardımcı" işlevler eklemeyi düşünün ve giriş verilerinizi etkili bir şekilde yapılandırın. Bu, muhtemelen giriş verilerinin dosyaya kaydedilmesi anlamına gelebilir, böylece yanlış pozitifleri veya önyargılı / önemsizce çözülmüş test durumlarını önlemek için çok dikkatli olmalısınız.

Çapraz doğrulama gibi bir şey kullanmayı düşünün , daha fazla bilgi için bu çaprazlama doğrulanmış gönderisine bakın .

Sürüm kontrolünü kullan

Sürüm kontrolünü kullanmanızı ve havuzunuzu harici bir sitede barındırmanızı tavsiye ederim. Ücretsiz depoları barındıracak siteler var.

Avantajları:

  1. Sabit diskinizin arızalanması durumunda yedekleme sağlar
  2. Diğer yararların yanı sıra, bir dosyayı yanlışlıkla değiştirmenizin yol açtığı sorunlardan kaynaklanıyorsa, sizi endişelenmekten alıkoyacak bir geçmiş sunar.
  3. İlgili olmayan işleri etkilemeden uzun süreli / deneysel kod üzerinde çalışmanın iyi bir yolu olan dallanma kullanmanıza olanak tanır.

Kod kopyalarken / yapıştırırken dikkatli olun

Kodumun tarzı kıvrımlıdır ve bir şeyi yapmanın alternatif yollarını veya üzerine kopyalanan kod satırlarını belirten eski yorumlarla doludur.

  • Kod kopyalamak / yapıştırmak size zaman kazandırabilir, ancak özellikle kendiniz yazmadığınız bir kod varsa (örneğin, bir meslektaşın kodu ise) yapabileceğiniz en tehlikeli şeylerden biridir.

  • Kodu çalıştırıp test ettiğinizde, değişkenleri yeniden adlandırmak veya anlamadığınız herhangi bir şeyi yorumlamak için çok dikkatli bir şekilde gözden geçirmenizi tavsiye ederim.



6

Ticaretin araçları genellikle bir ihtiyacı çözmek için icat edilir. Aracı kullanmanız gerekiyorsa, kullanmıyorsanız büyük olasılıkla kullanmak zorunda değilsiniz.

Özellikle, bilimsel programlar son hedef değil, araçlardır. Şimdi sahip olduğunuz bir sorunu çözmek için programı yazıyorsunuz - bu programın başkaları tarafından kullanılmasını beklemiyorsunuz (ve sürdürülmesi gerekiyor) on yıl içinde. Bu yalnız sizin olmadığım anlamına sahip akım geliştirici birimi testlerinde gibi kod sürüm kontrolü veya yakalama işlevselliği gibi diğerleri için tarih yazmak için izin araçlardan herhangi içine düşünmek.

O zaman sana ne yararı olur?

  • sürüm kontrolü güzeldir çünkü çalışmanızı kolayca yedeklemenizi sağlar. 2018 itibariyle github bunu yapmak için çok popüler bir yer (ve gerektiğinde daha sonra hareket ettirebilirsiniz - git çok esnektir). Yedeklemeler için ucuz ve basit bir alternatif işletim sisteminizdeki otomatik yedekleme prosedürleridir (Mac için Time Machine, Linux için rsync vb.). Kodunuzun birden fazla yerde olması gerekiyor!
  • Birim testleri güzeldir, çünkü ilk önce onları yazarsanız, kodun gerçekte ne yaptığını kontrol etmeyi düşünmek zorunda kalırsınız, bu da kodunuz için daha kullanışlı bir API tasarlamanıza yardımcı olur. Bu, daha sonra tekrar kullanmak üzere kod yazmaya başladığınızda ve bir algoritmayı değiştirirken size yardımcı olduğundan, bu durumlarda çalıştığını bildiğiniz için yararlıdır.
  • Belgeler. Kullandığınız programlama dilinde uygun belgeler yazmayı öğrenin (örneğin, Java için javadoc). Gelecek için yaz. Bu süreçte iyi değişken isimlerinin dokümantasyonu kolaylaştırdığını göreceksiniz. Uygulayın. Belgelerinize aynı şiirle aynı şiiri verin, şairlerin şiirleri olduğu gibi.
  • İyi araçlar kullanın. Size yardımcı olacak bir IDE bulun ve iyi öğrenin. Değişkenleri daha iyi bir adla yeniden adlandırmak gibi yeniden düzenleme, bu şekilde çok kolaydır.
  • Eğer meslektaşlarınız varsa meslektaş değerlendirmesini kullanmayı düşünün. Dışarıdan birinin kodunuzu incelemesi ve anlaması, yazdığınız geleceğin şimdi ve şimdiki sürümüdür. Eğer meslektaşınız kodunuzu anlamıyorsa, muhtemelen daha sonra söylemeyeceksiniz.

Bu cevap nasıl bir oy almadı? Şimdi oldu. Grubumuz, akran incelemesinin, bilimsel yasalara gelince, birim testlerinden çok daha önemli, hepsinin en etkili araçlarından biri olduğunu buldu. Bilimsel bir dergi makalesinde karmaşık bir denklem setini kodlamaya çevirirken hata yapmak kolaydır. Bilim adamları ve mühendisler çoğu zaman son derece zayıf programcılar için; Hakem incelemesi, kodu korumak / anlamak / kullanmak zorlaştıran mimari çirkinlikleri yakalayabilir.
David Hammen

5

Buradaki iyi önerilere ek olarak, programlamanızın amacını ve bu nedenle sizin için neyin önemli olduğunu düşünebilirsiniz.

“Bu, test ettiğim veya programlama ile araştırdığım matematik veya bilim hakkında daha fazla şey.”

Amaç, kendi anlayışınız için bir şeyi denemek ve test etmekse ve sonuçların ne olması gerektiğini biliyorsanız, kodunuz temelde hızlı bir şekilde atılır ve mevcut yaklaşımınız yeterli olsa da geliştirilebilir. Sonuçlar beklendiği gibi değilse geri dönüp gözden geçirebilirsiniz.

Ancak, kodlamanızın sonuçları araştırmanızın yönünü bilgilendiriyorsa ve sonuçların ne olması gerektiğini bilmiyorsanız , doğruluk özellikle önemlidir. Kodunuzdaki bir hata, genel araştırmanız için çeşitli kötü uygulamalarla denemenizden yanlış sonuçlar çıkarmanıza neden olabilir.

Bu durumda, kodunuzu ünite testleriyle kolayca anlaşılabilir ve doğrulanabilir fonksiyonlara sokmak, size sonuçlarınızda daha fazla güven veren daha sağlam yapı taşları sağlayacaktır ve daha sonra sizi çok fazla hayal kırıklığından kurtarabilir.


5

Sürüm kontrolü ve ünite testi, genel kodunuzu düzenli ve işlevsel tutmak için ne kadar iyi olursa, hiçbiri daha temiz bir kod yazmanıza yardımcı olmaz.

  • Sürüm kontrolü, kodun nasıl ve ne zaman olduğu kadar karışıklaştığını görmenize olanak sağlar.
  • Birim testleri, kodun tamamen karışık olmasına rağmen hala çalışmasını sağlar.

Kendinizi dağınık kod yazmaktan alıkoymak istiyorsanız, mesajların olduğu yerde çalışan bir araca ihtiyacınız vardır: kodu yazarken . Popüler bir alet türü olan linter denir. Bir python geliştiricisi değilim, ancak Pylint iyi bir seçenek olabilir gibi görünüyor .

Bir linter yazdığınız koda bakar ve yapılandırılabilir bir en iyi uygulama grubuyla karşılaştırır. Eğer linter değişkenleri olması gereken bir kurala sahipse camelCaseve siz de bir tane yazarsanız snake_case, bunu bir hata olarak işaretler. İyi linters "bildirilen değişkenler" kullanılmalıdır "ila" İşlevlerin döngüsel karmaşıklığı 3'ten az olmalıdır "arasında değişen kurallara sahiptir.

Kod düzenleyicilerin çoğu, her kaydettiğinizde veya genel olarak yazdıkça bir linter çalıştırmak veya satır içi sorunları belirtmek için yapılandırılabilir. Eğer böyle bir şey yazarsanız x = 7, x(yani yapılandırdığınız buysa) daha uzun, daha iyi bir isim kullanmak için bir talimat, vurgulanacaktır. Bu, çoğu kelime işlemcisinde yazım denetimi gibi çalışır, göz ardı edilmesini zorlaştırır ve daha iyi alışkanlıklar oluşturmaya yardımcı olur.


Bunun çok daha fazla oy hakkı olmalı. +1
heather

2
Ancak, cennetin uğruna, linter'i sevdiğiniz bir stile nasıl yapılandıracağınızı bildiğinizden emin olun, aksi takdirde sizi tedirginlikle kızdıracaktır.
DrMcCleod

4

Listelenen her şey mecazi araç kutusundaki bir araçtır. Hayattaki herhangi bir şey gibi, farklı araçlar farklı görevler için uygundur.

Yazılım, diğer mühendislik alanlarıyla karşılaştırıldığında, kendi başlarına oldukça basit olan bir grup ayrı parça ile çalışır. Bir ödev ifadesi, odanın sıcaklık dalgalanmalarına bağlı olarak farklı değerlendirilmez. Bir ifaçıklama yerine geçmez ve bir süre sonra aynı şeyi iade etmeye devam etmez. Ancak, bireysel unsurlar çok basit olduğu ve yazılım insanlar tarafından yazıldığı için, bu elemanlar sonuç o kadar geniş ve karmaşık hale gelinceye kadar daha büyük ve daha büyük parçalara birleştirilir ve bu insanların zihinsel olarak yönetebileceği sınırlara ulaşır.

Yazılım projeleri büyüdükçe ve büyüdükçe, insanlar onları incelemiş ve bu karmaşıklığı yönetmeye çalışmak için araçlar yaratmıştır. OOP bir örnektir. Giderek daha fazla soyut programlama dili, başka bir yoldur. Yazılımdaki paranın çoğu daha fazla şey yaptığı için, bunu başaracak araçlar görecek ve okuyacağınız şeyler olacaktır. Ancak bu durumlar sizin için geçerli değil gibi görünüyor.

Yani, bunlardan herhangi birini yapmanız gerektiğini hissetmeyin . Günün sonunda, kod sadece bir amaç için bir araçtır. Ne yazık ki, neyin uygun olup olmadığına dair doğru perspektifi size en iyi verebilecek olan şey, bazı daha büyük projeler üzerinde çalışmaktır, çünkü araç kutusu aklınızdayken neyin eksik olduğunu bilmek çok daha zordur.

Her durumda, senaryolarınız küçük olduğu sürece OOP veya diğer teknikleri kullanmama konusunda endişelenmem. Tanımladığınız sorunların çoğu sadece genel mesleki organizasyon becerileridir, yani eski bir dosyayı kaybetmemek tüm alanların üstesinden gelmesi gereken bir şeydir.


4

Şimdiye kadar verilen tüm iyi önerilere ek olarak, zamanla öğrendiğim ve gerekli bulduğum bir uygulama da, liberal olarak kodunuza ayrıntılı bir yorum eklemek. Uzun zaman geçtikten sonra bir şeye geri döndüğümde bu benim için en önemli şey. Ne düşündüğünüzü kendinize açıklayın. Bunu yapmak biraz zaman alıyor ancak nispeten kolay ve çoğunlukla ağrısız.

Bazen, özellikle kavramlar veya teknikler benim için yeni olduğunda ve kendime açıklama yaparken, kodumun iki veya üç katı yorum satırına sahibim.

Sürüm kontrolü yapın, uygulamalarınızı geliştirin, vb. Yukarıdakilerin tümü. Ama gittiğiniz şeyleri kendinize açıklayın. Gerçekten iyi çalışıyor.


4

Bu tür bir program için hangi özellikler önemlidir?

Muhtemelen bunu sürdürmesi veya geliştirmesi kolay değildir, çünkü şansı bu olmayacak.

Muhtemelen ne kadar verimli olduğu önemli değil.

Muhtemelen mükemmel bir kullanıcı arayüzüne sahip olup olmadığı veya kötü niyetli saldırganlara karşı güvenli olup olmadığı önemli değildir.

Okunabilir olması önemli olabilir: kodunuzu okuyan bir kişi, kendi iddia ettiği şeyi yaptığı konusunda kendilerini kolayca ikna edebilir.

Kesinlikle doğru olduğu önemli. Program yanlış sonuçlar verirse, bu, pencereden çıkan bilimsel sonuçlarınızdır. Ancak, yalnızca işlem yapmasını istediğiniz girişi doğru şekilde işlemesi gerekir; Negatif girdi veri değerleri verilmişse, tüm veri değerleriniz pozitifse düşüp düşmemesi çok da önemli değil.

Ayrıca, bir miktar değişim kontrolü sağlamanız da önemlidir. Bilimsel sonuçlarınızın yeniden üretilebilir olması gerekir ve bu, programın hangi sürümünün yayınlamayı düşündüğünüz sonuçları ürettiğini bilmeniz gerektiği anlamına gelir. Yalnızca bir geliştirici olduğu için, değişiklik kontrolünün çok ayrıntılı olması gerekmez, ancak zaman içinde bir noktaya geri dönüp sonuçlarınızı alabileceğinizden emin olmanız gerekir.

Bu nedenle programlama paradigmalarını, nesne yönelimini, algoritmik zarafeti merak etmeyin. Netlik ve okunabilirlik ve zaman içinde yaptığınız değişikliklerin izlenebilirliği hakkında endişelenmeyin. Kullanıcı arayüzü hakkında endişelenmeyin. Her olası girdi parametresi kombinasyonunu test etme konusunda endişelenmeyin, ancak sonuçlarınızın ve sonuçlarınızın geçerli olduğundan emin olmak (ve başkalarını güvende tutmak) için yeterli test yapın.


4

Benzer bir ortamda çok sayıda (matematik / bilim) kodu yazan akademisyenler ile çalıştım, ancak tanımladığınız aynı nedenlerden dolayı ilerlemeleri yavaş. Ancak, size de yardımcı olabileceğini düşündüğüm bir sorun olduğunu fark ettim: birden fazla projede kullanılabilecek özel bir kitaplık koleksiyonunun oluşturulması ve sürdürülmesi. Bu kütüphaneler faydalı fonksiyonlar sağlamalıdır ve bu nedenle mevcut projenizi problem alanına özel tutmaya yardımcı olacaktır.

Örneğin, alanınızdaki bir çok koordinat dönüşümü ile uğraşmak zorunda kalabilirsiniz (ECEF, NED, enlem / boylam, WGS84 vb.), Bu nedenle gibi bir işlev convert_ecef_to_ned()adı verilen yeni bir projeye girmelidir CoordinateTransformations. Projeyi sürüm kontrolü altına alın ve başkalarının kullanabilmesi (ve umarım iyileştirmesi) için departmanınızın sunucularında barındırın. O zaman birkaç yıl sonra, projelerinizde yalnızca belirli bir sorun / araştırma alanına özgü kod içeren sağlam bir kütüphane koleksiyonuna sahip olmalısınız.

Bazı daha genel tavsiyeler:

  • Her zaman özel sorununuzu, ne olursa olsun mümkün olduğunca doğru bir şekilde modellemeyi hedefleyin. Bu şekilde yazılım, değişkenleri neyin / nereye / nasıl koyacağınız gibi sorular tasarlar ve cevaplamak çok daha belirgin hale gelir.
  • Bilimsel kod fikirleri ve kavramları tanımladığından ve daha yaratıcı ve akıcı olduğundan, teste dayalı bir gelişmeyle uğraşmazdım; işlevsellik değiştirilirken tanımlanacak, bakımı yapılacak hizmetler, başkalarının kodlarına ilişkin riskler vb.

Diğer insanların onu geliştirmesine izin verme. Muhtemelen, kodun amacını anlamadıkları ve işleri mahvedecekleridir.
mathreadler

@ mathreadler Genel yardımcı program kütüphaneleriyse, başkalarının karıştırması biraz zor olacak, fikir bu.
jigglypuff

Genel amaçlı kütüphaneleri karıştırmak neden bu kadar zor? Ne yaptığınız hakkında bir fikriniz yoksa ya da bu konuda gerçekten çok çalışırsanız, o kadar da zor değil.
mathreadler

@ mathreadler Çünkü genellikle dönüşümleri veya birim dönüşümleri koordine etmenin tek bir yolu vardır.
jigglypuff

Sayılarınızın bellekte nasıl depolandığına, hangi gösterimleri kullandıklarına ve kütüphaneyi derlemeyi düşündüğünüz CPU işlemlerine bağlı olarak genellikle pek çok yöntem vardır. Bir kodlayıcı herkesin her zaman IEEE çiftlerini kullanacağını varsayabilir, örneğin bir diğeri neredeyse her zaman tek bir hassasiyet veya üçüncü bir tuhaf format kullanır. Bir kodlayıcı daha sonra şablon polimorfizmini kullanacak, ancak bir diğeri buna alerjisi olabilir, hatta üçüncüsü daha garip olanı bile düşük seviye c veya montajdaki her şeyi zor kodlar.
mathreadler

3

Aşağıdakiler benim görüşlerim ve kendi özel yolumdan çok etkilendiler.

Kodlama genellikle işleri nasıl yapmanız gerektiği konusunda dogmatik bakış açıları doğurur. Teknikler ve araçlar yerine uygun bir stratejiye karar vermek için kümülatif değerlere ve maliyetlere bakmanız gerektiğini düşünüyorum.

İyi, okunabilir, hata ayıklanabilir, sağlam bir kod yazmak çok zaman ve çaba gerektirir. Birçok durumda, sınırlı bir planlama ufku verilirse, bunu yapmaya değmez (analiz felci).

Bir meslektaşımın bir kuralı vardı; Eğer temelde üçüncü kez aynı şeyi yapıyorsanız, emeğe yatırım yapın, yoksa hızlı ve kirli bir iş yapmanız uygundur.

Bir çeşit test yapmak zorunludur, ancak bir kerelik projeler için, sadece göz küresi yeterli olabilir. Önemli bir şey için testler ve test altyapısı önemlidir. Değer, kodlama yaparken sizi serbest bırakmasıdır, maliyet, eğer test belirli bir uygulamaya odaklanırsa testlerin de bakım gerektirmesidir. Testler aynı zamanda işlerin nasıl yapılmasının beklendiğini de hatırlatır.

Kendi senaryolarım için (genellikle bir olasılık tahminini doğrulamak veya benzeri bir şey için), iki küçük şeyi çok yararlı buldum: 1. Kodun nasıl kullanıldığını gösteren bir yorum ekleyin. 2. Kodu neden yazdığınızın kısa bir açıklamasını ekleyin. Kod yazdığınızda bunlar çok açık, ancak barizlik zamanla boşa gidiyor :-).

OOP, kodu yeniden kullanmak, soyutlamak, enkapsülasyon yapmak, faktoring vb. İle ilgilidir. Kalite kodu ve tasarım üretmek sizin nihai amacınız değilse, çok kullanışlı, ancak kaybedilmesi kolaydır. Kaliteli malzeme üretmek zaman ve çaba gerektirir.


3

Ünite testlerinin yararları olduğunu düşünürken, bilimsel gelişim için şüpheli değerlere sahipler - çoğu zaman çok fazla değer sunmak için çok küçükler.

Ancak bilimsel kod için entegrasyon testlerini gerçekten seviyorum:

Kendi başınıza çalışabilecek küçük bir kod parçasını ayırın, örneğin ETL boru hattı. Sonra verileri sağlayan bir test yazın, etl boru hattını çalıştırın (veya sadece bir adım) ve sonucun beklentilerinize uygun olduğunu test edin. Test edilen yığın çok fazla kod olsa da, test hala değer sağlar:

  1. Kodunuzu yeniden çalıştırmak için sıkça çalıştırmanıza yardımcı olacak uygun bir kancanız var.
  2. Testinizde bazı varsayımları test edebilirsiniz.
  3. Bir şeyler kırılırsa, başarısız bir test eklemek ve düzeltmeyi yapmak kolaydır
  4. Beklenen girişleri / çıkışları kodlar, giriş veri formatını tahmin etmeye çalışmaktan kaynaklanan olağan baş ağrısından kaçınırsınız.
  5. Ünite testleri kadar yalın olmasa da, BT testleri hala kodunuzu parçalamaya ve kodunuza bazı sınırlar eklemeye zorlar.

Bu tekniği sık sık kullanıyorum ve çoğunlukla göreceli olarak okunabilir bir ana işlev görüyorum ancak alt işlevler genellikle oldukça uzun ve çirkin ancak sağlam G / Ç sınırları nedeniyle hızla değiştirilebilir ve yeniden düzenlenebilir.


2

Normalde çok büyük bir kaynak tabanı üzerinde çalışıyorum. Bahsettiğiniz tüm araçları kullanıyoruz. Son zamanlarda, bir yan proje için bazı python scriptleri üzerinde çalışmaya başladım. En fazla birkaç düzine birkaç yüz çizgiye kadardırlar. Alışkanlığım dışında, senaryolarımı kaynak kontrolüne adadım. Bu yararlı oldu çünkü işe yaramayacak deneyleri denemek için dallar oluşturabiliyorum. Kodu kopyalayıp başka bir amaç için değiştirmem gerekirse çatallayabilirim. Bu, tekrar ortaya çıkarmam gerekebilir diye orijinali inceliğinde bırakır.

"Birim testleri" için sadece elle kontrol ettiğim bilinen bir çıktı elde etmek için tasarlanmış bazı girdi dosyalarım var. Muhtemelen otomatikleştirebilirdim, ancak bunu yapmaktan tasarruf edeceğimden daha fazla zaman alacağı düşünülüyor. Muhtemelen komut dosyalarını ne kadar sıklıkla değiştirmem ve çalıştırmam gerektiğine bağlıdır. Her iki durumda da, eğer işe yararsa, yapın. Değerinden daha fazla sorun varsa, zamanınızı boşa harcamayın.


2

Yazma kodu ile - genel olarak yazarken olduğu gibi - asıl soru şudur:

Aklınızda hangi okuyucunuz var? veya Kodunuzu kim kullanıyor?

Resmi kodlama kuralları gibi şeyler, tek hedef kitleniz olduğunda hiçbir anlam ifade etmez.

Öte yandan, kodu bir şekilde, geleceğinizi hemen anlayabileceğiniz şekilde yazmak yararlı olacaktır.

Yani "iyi bir stil", size en çok yardımcı olanlardan biri olacaktır. Bu tarzın neye benzemesi gerektiği konusunda veremediğim bir cevap.

150 LOC dosya için OOP veya Unit testlerine ihtiyacınız olmadığını düşünüyorum. Özel bir VCS, bazı gelişen kodlara sahip olduğunuzda ilginç olacaktır. Aksi takdirde bir .bakhile yapar. Bu araçlar bir hastalığın tedavisidir, hatta sahip olamazsınız.

Belki de kodunuzu öyle bir şekilde yazmalısınız, sarhoşken okursanız bile, okuyabilir, anlayabilir ve değiştirebilirsiniz.

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.