Ne zaman ve neden boşluk kullanmalısınız (örneğin, bool / int yerine)


30

Bazen bir geliştiricinin işlev için kritik olmayan bir şey döndürmeyi seçtiği yöntemler ile karşılaşıyorum. Demek istediğim, koda bakarken, göründüğü kadar güzel bir şekilde çalışıyor voidve bir an düşündüğümden sonra, "Neden?" Bu size tanıdık geliyor mu?

Bazen bunun bir gibi bir şey dönmek daha iyidir çoğunlukla kabul ediyorum boolya intziyade sadece yapın void. Yine de, büyük resimde, artılar ve eksiler hakkında emin değilim.

Duruma göre, geri dönerek intarayanı yöntemden etkilenen satır veya nesne miktarından haberdar edebilirsiniz (örneğin, MSSQL'e kaydedilen 5 kayıt). "InsertSomething" gibi bir yöntem bir boolean döndürürse, truebaşarılı olursa geri dönmek için tasarlanmış yöntemi alabilirim false. Arayan kişi bu bilgi üzerinde hareket etmeyi seçmemeyi seçebilir.

Diğer yandan,

  • Bir yöntem çağrısının daha az net bir amacına yol açabilir mi? Kötü kodlama çoğu zaman beni yöntem içeriğini iki kez kontrol etmeye zorlar. Bir şeyler dönerse, o yöntem bir tür olduğunu söyler sahip dönen sonuç bir şeyler yapmak.
  • Başka bir sorun, eğer yöntem uygulaması sizin için bilinmiyorsa, geliştirici işlevsellik açısından kritik olmayan bir şeyi geri getirmeye karar vermiştir? Tabii ki yorum yapabilirsiniz.
  • İşlem, yöntemin kapanış parantezinde sonlandırılabildiğinde, dönüş değerinin işlenmesi gerekir.
  • Kaputun altında ne olur? Çağrılan yöntem false, atılmış bir hata nedeniyle mi oldu? Yoksa değerlendirilen sonuçtan dolayı yanlış mı döndü?

Bununla deneyimleriniz neler? Bu konuda nasıl hareket edersiniz?


1
Boşluğu döndüren bir işlev, teknik olarak hiç bir işlev değildir. Bu sadece bir yöntem / prosedür. voidEn azından geri dönüş , geliştiriciye yöntemin dönüş değerinin önemsiz olduğunu bilmesini sağlar; bir değer hesaplamak yerine bir eylemde bulunur.
KChaloux

Yanıtlar:


32

Bir yöntemin başarısını veya başarısızlığını gösteren bir bool dönüş değeri olması durumunda, Tryçeşitli .NET yöntemlerinde kullanılan -prefix paradigmasını tercih ederim .

Örneğin void InsertRow(), aynı anahtarla bir satır zaten varsa, bir yöntem bir istisna atabilir. Sorun şu ki, arayanın InsertRow'u çağırmadan önce sırasının benzersiz olmasını sağladığını varsaymak mantıklı mı? Cevap hayır ise, o zaman bool TryInsertRow()satır zaten varsa yanlış olanı da veririm . Db bağlantı hataları gibi diğer durumlarda, TryInsertRow, db bağlantısını korumanın arayanın sorumluluğu olduğunu farz ederek hala bir istisna atabilir.


4
Beklenen ve beklenmeyen başarısızlıklarla başa çıkmak arasında ayrım yapmak için +1 - kendi cevabım bunu yeterince vurgulamadı.
Péter Török

Kesinlikle, hem deneme yöntemini hem de ana yöntemi, bakımını daha kolay ve daha kolay bir şekilde yapmalarını sağlayan TryXX yöntemleri için bir prensip icat etmeye çalışmak için bir +1.
Bağımsız

+1 Peki dedi. Bu sorunun en iyi cevabının anahtarı, bazen arayana bir istisna atacak iddialı bir yöntem seçeneği vermek istediğinizdir. Bu gibi durumlarda, istisna yakalanmamalı ve iddialı bir yöntemle sahte kullanılmamalıdır. Mesele şu ki, arayanın sorumlu kılınması. Öte yandan, bir Try-paradigması (veya Monad) istisnaları yakalamalı ve ele almalı, daha sonra eğer daha fazla ayrıntı gerekiyorsa bir bool veya tanımlayıcı bir Enum geri göndermelidir. Arayan kişinin bir Dene / Monad'in ASLA bir istisna atmayacağını umduğunu unutmayın. Bir giriş noktası gibi.
Suamere

Bu yüzden, bir istisnanın hiçbir zaman bir Try / Monad'dan kaynaklanması beklenmediğinden, bir bool, arayan kişiye bir db bağlantısının başarısız olduğunu bildirecek kadar açıklayıcı değildir veya bir http isteği farklı şekilde davranması gereken birçok dönüş değerinden birine sahiptir. Try / Monad'ınız için bool yerine Enum kullanabilirsiniz.
Suamere

Eğer TryInsertRow varsa - bir geri döndürme döndürme - eğer varsa, veritabanında birden fazla benzersiz kısıtlama varsa - hatanın ne olduğunu tam olarak nasıl biliyorsunuz - ve bunu kullanıcıya iletir misiniz? Hata mesajı / kodu ve başarı artışını içeren daha zengin bir geri dönüş tipi kullanılmalı mıdır?
niico,

28

Bir "durum kodu" döndüren IMHO, C # gibi orta - üst düzey dillerde istisnalar yaygın hale gelmeden önceki tarihlerden kaynaklanır. Bugünlerde, beklenmeyen bir hata, yönteminizin başarılı olmasını engelliyorsa, bir istisna atmak daha iyidir. Bu şekilde hatanın farkedilmediğinden emindir ve arayan kişi bununla başa çıkabilir. Dolayısıyla, bu durumlarda, bir yöntemin voidbir boolean durum bayrağı veya bir tamsayı durum kodu yerine hiçbir şey (yani ) döndürmemesi gayet iyi . (Tabii ki, yöntemin hangi istisnaları ne zaman ve ne zaman verebileceğini belirtmek gerekir.)

Öte yandan, eğer katı anlamda bir işlevse, yani girdi parametrelerine dayanarak bazı hesaplamalar yaparsa ve bu hesaplamanın sonucunu döndürmesi bekleniyorsa, geri dönüş tipi açıktır.

Bir ikisi arasında bir gri alan var olabilir onun arayanlar için faydalı görüldüğü takdirde, yönteme bir miktar "ekstra" bilgisini dönmeye karar verirler. Örnekteki gibi, etkilenen satır sayısındaki örneğiniz gibi. Veya bir öğeyi ilişkisel bir koleksiyona koyma yönteminde, eğer varsa, bu anahtarla ilişkili önceki değeri döndürmek faydalı olabilir. Bu kullanımlar, bir API'nin (bilinen ve öngörülen) kullanım senaryolarını dikkatlice analiz ederek belirlenebilir.


4
Durum kodu üzerindeki istisnalar için +1. Bunun istisnası (amaçlanan kötü punto) iyi kullanılan TryXX modelidir.
Andy Lowry,

Ben orada seninleyim. TcF ve susturma hataları! Muhtemelen, gri bölge. Her zaman bir şeyler iade kullanmak olabilir . Etkilenen satırlar, en son eklenen ID, bir yazılımın çalıştırdığı PID, ancak geliştirmeye devam ederken "cehennem evet, bunu iade ediyorum" diye düşünmenin daha kolay olduğunu düşünüyorum. Ardından, bir yıl sonra genişletme yaparken, "ne? Bu bir ´int someThing = RunProcess (x) 'yapıyor mu, çalıştırılamazsa ne olur?"
Bağımsız

+1 fazladan bilgi, bunun gibi yöntemleri C # gibi üst düzey dillerde kodlamamın nedenidir. Bu, ihtiyaç duyduğunuzda ilave bilgilerin kullanımını kolaylaştırır.
ashes999

2
-1 Vay, kendi sözlerin çok çelişkili ve yanlıştır. Kontrol akışı veya iletişim için asla istisnalar kullanmamalısınız. Şartlıdan çok daha pahalıdırlar. "İstisnalar öncesi olağan hale gelme zamanı" ne zaman? - ... deneyin / yakalanmayı engelleyen blokların ortak hale gelmesinden önce demek istiyorsun? İstisnalar sonsuza dek yaygındı. “Beklenmeyen bir hata varsa bir istisna at ...” Beklenmeyen bir şey için nasıl harekete geçersin? Neden bir istisna yakaladın, sonra tekrar fırlattın? Bu çok pahalı. Neden "hata" diyorsun? Hatalar ve İstisnalar farklı şeylerdir.
Suamere

1
Ve kim atılan bir istisnanın fark edilmeyeceğini söyleyemez? Hiçbir şey kimseyi bir alıcı bloğuna giriş yapmaya zorlamaz, neden "o zaman" bloğuna giriş yapmıyorsunuz? Neden "yöntemin ne zaman ve ne zaman verebileceği istisnaları belgelemek"? Kendi kendini belgeleyen kod yazarsak ve bir yöntem bu yöntemin beklenen son durumlarını içeren bir enum döndürürse ne olur? Durum kontrol edilerek olası bir istisnadan kaçınılabilirse, atmadan yakalanmalı ve kullanılmalıdır.
Suamere

14

Peter'ın cevabı istisnaları iyi kapsar. Buradaki diğer hususlar, Komut Sorgu Ayrımı ile ilgilidir.

CQS prensibi, bir yöntemin bir komut veya bir sorgu olması gerektiğini ve her ikisinin de olmaması gerektiğini söyler. Komutlar hiçbir zaman bir değer döndürmemeli, yalnızca durumu değiştirmeli ve sorgular yalnızca durumu değiştirmeli ve değiştirmemelidir. Bu, anlambilimi çok net tutar ve kodun daha okunaklı ve bakımsız olmasına yardımcı olur.

CQS ilkesini ihlal eden birkaç vaka var iyi bir fikir. Bunlar genellikle performans veya iplik güvenliği ile ilgilidir.


1
-1 Yanlış ve Yanlış. Öncelikle, CQS'nin tüm noktası Q'da yatmaktadır. Arayan, bu hizmetin durumunu değiştirme korkusu olmadan bazı devletli servis aracılığıyla hesaplamalar veya dış aramalar yapabilmelidir. Ayrıca, CQS gevşek bir şekilde takip etmek için yararlı bir ilke olsa da, sadece belirli tasarımlarda kesinlikle takip edilir. Son olarak, sıkı CQS'de bile hiçbir şey bir komutun bir değer döndüremediğini söylemez, dış hesaplamaları hesaplamak veya çağırmak ve veri döndürmek zorunda değildir . C veya Q, arayanlar için faydalıysa son durumlarını geri getirmekte özgür olabilir.
Suamere

Ah, ancak bir Komuttan etkilenen satır sayısı, eskilerden yeni komutlar oluşturmayı çok daha kolaylaştırır. Kaynak: yıllar ve tecrübeler.
Joshua

@Joshua: Benzer şekilde, "yeni kayıt ekleyin ve ekleme sırasında oluşturulan bir kimliği (bazı yapılar için, bir satır numarası) döndürün", aksi takdirde verimli bir şekilde elde edilemeyen amaçlar için kullanılabilir.
supercat,

Etkilenen satırları iade etmeniz gerekmez. Komut kaç tane etkileneceğini bilmeli. Eğer bu # dışında bir şeyse, garip bir şey olduğu için geri çekilmeli ve bir istisna atmalıdır. Bu nedenle, arayan kişi gerçekten onunla ilgilenmez. (Kullanıcının gerçek # bilgisini bilmesi ve verilen verilerden anlatamazsanız). Yine de DB oluşturulan ID'ler, verilerin toplanmasının durumunu değiştirdiği yığınlar / sıralar gibi gri alanlar var, ancak bu senaryolarda "CommandQuery" oluşturmayı seviyorum, bu yüzden kimse "tuhaf" bir şey yapmaya çalışıyor.
Daniel Lorenz

3

Yol ne olursa olsun, onunla yürüyeceksin. Gelecekte kullanmak için geri dönüş değerleri yoktur (örneğin, işlevler her zaman doğrudur) bu çok büyük bir çaba kaybıdır ve kodu okumayı daha açık hale getirmez. Bir dönüş değerine sahipseniz, her zaman kullanmalı ve kullanabilmeniz için en az 2 olası dönüş değerine sahip olmalısınız.


+1 Bu soruya cevap vermiyor, ama kesinlikle doğru bilgi. Bir karar verirken, karar bir ihtiyaca dayanmalıdır. Arayanlar geri dönüş verilerini yararlı bulmazsa, yapılmamalıdır. Ve hiç kimse, “gelecekteki prova” için zamanın% 100'ünü iade etmekte fayda bulamaz. Kabul edersek, "gelecek" sanki ... birkaç gün sonra ve bunun için bir görev var, bu farklı bir hikaye, lol.
Suamere

1

Eskiden pek çok geçersiz fonksiyon yazıyordum. Ama tüm yöntemi çatlak zincirleme yöntemine bindiğimden beri, bunu geçersiz kılmak yerine geri göndermeye başladım - birilerinin geri dönüşün avantajlarından faydalanmasına izin verebilirim çünkü boşluğa dayanamazsınız. Ve onunla hiçbir şey yapmak istemiyorlarsa, bunu görmezden gelebilirler.


1
Metod zincirlemesi kalıtımın zahmetli ve zor olmasına neden olabilir. Yöntemlerinizi "geçersiz" olarak vermek istemediğinizden başka iyi bir nedeniniz olmadığı sürece yöntem zincirlemesi yapmam.
KallDrexx

Doğru. Ancak devralma hantal ve kullanımı zor olabilir.
Wyatt Barnett

(Tüm nesne söz) ne olursa olsun dönüşü bilinmeyen kod baktığımızda .. çok dikkat sadece akış iç ve dış yöntemler kontrol öder
Independent

Sanırım Rubybir noktaya gelmedin mi? Beni metot zincirleme ile tanıştırdı.
KChaloux

Metot zincirleme ile sahip olduğum bir özellik, böyle bir ifadenin orijinali referans olarak return Thing.Change1().Change2();değiştirmeyi Thingve geri göndermeyi bekleyip beklemeyeceği ya da orijinalden ayrılırken orijinalden farklı yeni bir şey referansı göndermesinin beklenmemesidir. Orijinal el değmemiş.
supercat
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.