Veritabanıyla ilgili yöntemler tasarlamak, hangisini döndürmek daha iyidir: true / false veya row etkilenmiş mi?


10

Bir veritabanında (ekleme, güncelleme ve silme) bazı veri değiştirme gerçekleştirmek için bazı yöntemler var. ORM Ben yöntemin bu tip dönüş satır etkilenen int değerleri kullanıyorum. İşlemin başarı / başarısızlık durumunu belirtmek için "yöntemim" için ne döndürmeliyim?

Aşağıdaki kodu döndüren kodu düşünün int:

A.1

public int myLowerLevelMethod(int id) {
    ...
    int affectedRows = myOrm.deleteById(id)
    ...

    return affectedRows;
}

Sonra kullanım:

A.2

public void myOtherMethod() {
    ...
    int affectedRows = myLowerLevelMethod(id)

    if(affectedRows > 0) {
        // Success
    } else {
        // Fail
    }
}

Boolean kullanarak karşılaştırın:

B.1

public boolean myLowerLevelMethod(int id) {
    ...
    int affectedRows = myOrm.deleteById(id)
    ...

    return affectedRows > 0;
}

Sonra kullanım:

B.2

public void myOtherMethod() {
    ...
    boolean isSuccess = myLowerLevelMethod(id)

    if(isSuccess) {
        // Success
    } else {
        // Fail
    }
}

Hangisi (A veya B) daha iyi? Veya her birinin artıları / eksileri?


"A.2" cihazınızda. Sıfır satırlar etkilenirse, sıfır satırların etkilenmesi gerekiyorsa neden başarısız olur? Başka bir deyişle, bir veritabanı hatası yoksa, neden başarısızdır?
Jaydee

5
"Başarısız" ve "sıfır satır etkilenen" arasında anlamsal bir fark var mı? Örneğin, bir müşterinin tüm siparişlerini silerken, "müşteri yok" ve "müşterinin siparişi yok" arasında bir fark vardır.
Cephalopod

Sıfır satır beklenmeyen bir silme düşünüyor musunuz? Bu durumda atın.
usr

@Arian bence gerçek soru bu. Sanırım B'yi seçtim, çünkü A ile kodum şu anda bazı yerlerde 0 ve diğerlerinde -1 için kontrol içeriyor
Hoang Tran

Yanıtlar:


18

Başka bir seçenek de temel türler yerine bir sonuç nesnesi döndürmektir. Örneğin:

OperationResult deleteResult = myOrm.deleteById(id);

if (deleteResult.isSuccess()) {
    // ....
}

Bununla, herhangi bir nedenden dolayı etkilenen satır sayısını döndürmeniz gerekirse, OperationResult'a bir yöntem ekleyebilirsiniz:

if (deleteResult.isSuccess()) {
    System.out.println("rows deleted: " + deleteResult.rowsAffected() );
}

Bu tasarım, mevcut kodu değiştirmeden sisteminizin büyümesine ve yeni işlevsellik (etkilenen satırları bilerek) içermesine olanak tanır.


2
+1 "Bu tasarım, sisteminizin mevcut kodu değiştirmeden büyümesine ve yeni işlevsellik (etkilenen satırları bilmek) dahil etmesine olanak tanır" Bu, bu soru kategorisini düşünmenin doğru yoludur.
InformedA

Eski projemde de benzer şeyler yaptım. Sarıcı istek ve sonuç nesnesi var. Her ikisi de daha fazla ayrıntı eklemek için Kompozisyonlar kullanır. ve her ikisinde de temel veriler var. Bu durumda, Sonuç nesnesinin bir durum kodu ve bir msg alanı vardır.
InformedA

Özellikle ORM kullanan bir sistem için bu en iyi uygulama diyebilirim. Söz konusu ORM zaten bu tür sonuç nesnesi türlerini de içerebilir!
Brian S

Sadece OPs örneğine bakarak, aklıma gelen tek şey deleteById bir noktada 2 dönecektir :) yani kesinlikle özel bir tür, evet.
deadsven

Bu yaklaşımı seviyorum. Bence engellemiyor, her iki yaklaşımımı da içeriyor ve değiştirilebilir / genişletilebilir (gelecekte gerekirse). Aklıma gelen tek dezavantajı, biraz daha fazla kod, özellikle de projemin ortasında geldiğinde. Bunu cevap olarak işaretleyeceğim. Teşekkür ederim.
Hoang Tran

12

Etkilenen satırların sayısını döndürmek daha iyidir çünkü işlemin nasıl devam ettiği hakkında ek bilgi verir.

Hiçbir programcı sizi suçlayamaz çünkü operasyon sırasında bazı değişiklikler olup olmadığını kontrol etmek için bunu yazmak zorundadır:

if(affectedRows > 0) {
    // success
} else {
    // fail
}

ancak etkilenen satırların sayısını bilmek zorunda kaldıklarında sizi suçlayacaklar ve bu sayıyı elde etmek için bir yöntem olmadığını anlayacaklar.

BTW: "başarısızlık" ile sözdizimsel bir sorgu hatası anlamına gelirse (bu durumda etkilenen satır sayısı açıkça 0 ise), istisnayı atmak daha uygun olacaktır.


4
-1 verdiğiniz sebep yüzünden. Ek bilgi vermek her zaman iyi bir fikir değildir. Çoğu zaman, daha iyi tasarım arayan kişiye tam olarak ihtiyaç duyduğu şeyleri ve daha fazlasını ifade etmemize yol açar.
Arseni Mourzenko

1
@MainMa hiçbir şey aşırı yüklenmiş yöntemler yaratmanın önünde durmaz. Ek olarak, yerel dillerde (örneğin C ailesi), satır sayısı doğrudan mantıkta kullanılabilir (0 yanlıştır, başka bir şey doğrudur).
PTwr

@PTwr: yöntemin çok fazla bilgi döndürdüğü gerçeğiyle başa çıkmak için aşırı yük oluşturmayı mı öneriyorsunuz? Bu doğru görünmüyor. "Sıfır yanlış, sıfır olmayan doğru" ise, bu benim yorumumun amacı değildir ve bazı dillerde kötü bir uygulamadır.
Arseni Mourzenko

1
Muhtemelen şımarık programcılardan biriyim çünkü herhangi bir hile kullanmanın iyi bir uygulama olarak düşünülebileceğini düşünmüyorum. Başkasının koduyla uğraşmak zorunda zaman Aslında, ben yazdım ve did kim müteşekkirim değil herhangi bir hile kullanır.
proskor

4
Etkilenen satırların sayısını her zaman buraya iade etmelisiniz !!! Satır sayısının = 0 başarısız olup olmadığını veya satır sayısının = 3 başarılı olup olmadığını bilemeyeceğiniz için? Birisi 3 satır eklemek istiyorsa ve sadece 2 tane yerleştirilirse, doğru dönersiniz, ancak bu doğru değildir! Birisi update t set category = 'default' where category IS NULLetkilenen 0 satır bile isterse başarılı olur, çünkü artık hiçbir satır etkilenmemiş olsa bile kategorisiz bir öğe yoktur!
Falco

10

Ben hiçbirini tavsiye etmem. Bunun yerine, başarı hakkında hiçbir şey döndürmeyin (geçersiz) ve başarısızlığa bir istisna atın.

Bu, belirli sınıf üyelerini özel olarak bildirmeyi tercih ettiğim sebepten dolayıdır. Ayrıca işlevin kullanımını kolaylaştırır. Daha operasyonel bağlam her zaman daha iyi anlamına gelmez, ama kesinlikle daha karmaşık demektir. Ne kadar az söz verirseniz, o kadar soyutlaşırsınız, müşterinin anlaması o kadar kolay olur ve bunu nasıl uygulayacağınız konusunda daha fazla özgürlüğe sahip olursunuz.

Soru, başarının / hatanın nasıl gösterileceğidir. Bu durumda, bir istisna atarak başarısızlığa işaret etmek ve başarıya hiçbir şey döndürmemek yeterlidir. Neden kullanıcının gereksiniminden fazlasını sağlamam gerekiyor?

Arızalar / istisnai durumlar olabilir ve onlarla başa çıkmanız gerekir. İster bunu yapmak için dene / yakala, ister dönüş kodlarını inceleyin, tarz / kişisel tercih meselesidir. Deneme / yakalamanın arkasındaki fikirler şunlardır: normal akışı istisnai akıştan ayırın ve istisnaların en uygun şekilde işlenebilecekleri katmana kadar kabarmasına izin verin. Yani, birçok kişinin belirttiği gibi, başarısızlığın gerçekten istisnai olup olmamasına bağlıdır.


4
-1 Neden ekstra operasyonel bağlam sağlayan hiçbir olumsuz yan etkisi olmayan bir şeyi iade edebileceğiniz bir yere geri dönmüyorsunuz?
FreeAsInBeer

7
Tam olarak aynı nedenden ötürü, özel sınıfın belirli üyelerini ilan etmeyi seçiyorum. Ayrıca işlevin kullanımını kolaylaştırır. Daha operasyonel bağlam her zaman daha iyi anlamına gelmez, ama kesinlikle daha karmaşık demektir. Ne kadar az söz verirseniz, o kadar soyutlaşırsınız, müşterinin anlaması o kadar kolay olur ve bunu nasıl uygulayacağınız konusunda daha fazla özgürlüğe sahip olursunuz.
proskor

1
Peki, kullanıcının gerçekten hangi verileri alması gerekir? Soru, başarının / hatanın nasıl gösterileceğidir. Bu durumda, bir istisna atarak başarısızlığa işaret etmek ve başarıya hiçbir şey döndürmemek yeterlidir. Neden kullanıcının gereksiniminden fazlasını sağlamam gerekiyor?
proskor

4
@proskor: İstisnalar istisnai durumlar içindir. Bu senaryoda "başarısızlık" beklenen bir sonuç olabilir. Elbette, bunu potansiyel bir alternatif olarak öne sürün, ancak burada bir tavsiye yapmak için yeterli bilgi yok.
Nick Barnes

1
-1 İstisnalar normal program akışının bir parçası olmamalıdır. Hatanın bağlamında "hata" nın ne anlama geldiği belirsizdir, ancak veritabanı çağrısı bağlamındaki bir istisnanın veritabanında oluşan bir istisna nedeniyle olması gerekir. Sıfır satırları etkilemek bir istisna olmamalıdır . Ayrıştırılamayan, varolmayan bir tabloya vb. Atıfta bulunulan karışık bir sorgu bir istisna olacaktır, çünkü veritabanı motoru onu boğup atacaktır.

2

"Bu bundan daha mı iyi?" iki alternatif aynı şeyi yapmadığında yararlı bir soru değildir.

Etkilenen satır sayısını bilmeniz gerekiyorsa , A sürümünü kullanmanız gerekir. Gerekmiyorsa, B sürümünü kullanabilirsiniz - ancak daha az kod yazma çabası açısından kazanabileceğiniz herhangi bir avantaj zaten gitti her iki sürümü de çevrimiçi bir foruma gönderme sorununu yaşadınız

Demek istediğim: hangi çözümün daha iyi olduğu, tamamen bu uygulama için gereksinimlerinizin ne olduğuna bağlıdır ve bu koşulları bizden çok daha iyi bilirsiniz. Genel olarak daha iyi olan , endüstri çapında, kullanımı güvenli, en iyi uygulama, ateşlenmeyecek bir seçenek yoktur ; bunu kendiniz düşünmelisiniz. Ve bu kadar kolay revize edilen bir karar için, düşünmek için o kadar çok zaman harcamanıza gerek yok.


Bunun uygulama gereksinimlerine çok bağlı olduğunu kabul ediyorum. Bununla birlikte, bu tür bir durumun çok benzersiz olmadığı ve gümüş bir mermi aramıyorum, sadece başkalarının aynı / benzer şeyle ilgili deneyimini arıyorum (belki de soru biraz yanıltıcıdır, A dışındaki önerileri severim) / B)
Hoang Tran

1

Sürdürülebilir yazılım tasarımında en önemli ilkelerden ikisi KISS ve YAGNI'dır .

Neredeyse hiç hemen gerekmez mantık koymak için iyi bir fikirdir şu anda . Diğer birçok insan arasında, Jeff Atwood (StackExchange'in kurucu ortağı) bunu yazdı ve benim deneyimime göre o ve bu kavramların diğer taraftarları tamamen haklı.

Bir programa eklediğiniz herhangi bir karmaşıklığın maliyeti, uzun bir süre boyunca ödenir. Programın okunması zorlaşır, değiştirilmesi daha karmaşık hale gelir ve hataların içeri girmesi daha kolay hale gelir. "Her ihtimale karşı" bir şeyler ekleme tuzağına düşmeyin. Bu yanlış bir güvenlik duygusu.

İlk seferde nadiren herhangi bir kodu alacaksınız. Değişiklikler kaçınılmazdır; gelecekteki beklenmedik durumlara karşı savunmacı bir şekilde hazırlanmak için spekülatif mantık eklemek , geleceğin beklediğinizden farklı olduğu ortaya çıktığında sizi kodunuzu yeniden düzenlemenize gerek kalmaz . Gereksiz / koşullu mantıkla ilgili bakım, eksik işlevsellik eklemek için daha sonra yeniden düzenleme yapmaktan ziyade bir sürdürülebilirlik problemidir.

Bu nedenle, şimdilik tüm programınızın ihtiyaç duyduğu işlemin başarılı olup olmadığını bilmek olduğundan, önerilen çözüm B (tek bir boolean döndürün) doğru yaklaşımdır. Gereksinim değişirse daha sonra istediğiniz zaman yeniden düzenleyebilirsiniz. Bu çözüm en basit ve en düşük karmaşıklığa sahip (KISS) ve sadece ihtiyacınız olanı ve daha fazlasını yapmıyor (YAGNI).


-1

Satırların tamamı veya hata durumu

En azından çalışma zamanı seçeneği olarak tüm satırları döndürmeyi düşünün. DB eklerinde, eklenen verileri incelemeniz gerekebilir - çünkü genellikle DB'ye gönderdiğinizden farklı olacaktır; sık karşılaşılan örnekler arasında otomatik olarak oluşturulmuş satır kimlikleri (uygulamanın hemen ihtiyaç duyacağı), DB tarafından belirlenen varsayılan değerler ve bunları kullanırsanız tetikleyicilerin sonuçları yer alır.

Döndürülen veri gerekmiyorsa hatalar varsa o 0'a sonucu için yararlı olmadığından Öte yandan, o zaman da o zaman dönmek gerekir, etkilenen satır sayısı gerekmez ne tür bir proje hata işleme ilkelerinizle (istisnalar, sayısal hata kodları, her ne olursa olsun) tutarlı bir şekilde hata oluştu; ancak 0 satırı doğru şekilde etkileyecek geçerli sorgular vardır (gerçekte yoksa "süresi dolmuş tüm siparişleri sil").

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.