Aralığın dışında anlamlı bir değer olması durumunda bir istisna mı atmalıyım yoksa kendim halledeyim mi?


42

Enlem / boylam koordinatlarını temsil eden bir yapı yazdım. Değerleri longtitudes için -180-180, lattitudes için 90-90 arasındadır.

Bu yapıdaki bir kullanıcı bana bu aralığın dışında bir değer verirse, 2 seçeneğim var:

  1. Bir istisna atma (aralık dışı arg)
  2. Değeri kısıtlamaya dönüştür

-185'in bir koordinatı anlamlıdır (kutupsal koordinatlar olduğu için kolayca +175'e çevrilebilir), kabul edip dönüştürebilirim.

Kullanıcıya kodunun bana vermemesi gereken bir değer verdiğini söylemek için bir istisna atmak daha mı iyi?

Düzenleme: Ayrıca lat / lng ve koordinatlar arasındaki farkı biliyorum, ancak daha kolay tartışma için basitleştirmek istedim - fikirlerin en parlakı değildi


13
Kullanıcının aralık dışında bir değer girmesine izin verilmeli midir? Cevap hayır ise, bir istisna atın. Kurallar o kadar katı değilse, dönüşümü yapın, ancak açıkça dönüşümün gerçekleşebileceğini belgeleyin. Ayrıca bazı dillerde istisnai durumun oldukça maliyetli olduğunu unutmayın.
Andy,

C #, önemli mi? Demek istediğin buysa, kısıtlamaları doğal olarak desteklemiyor.
K. Gkinis

2
Bana göre açıkça anlaşılıyor ki, doğru yaklaşım kullanıcının aralığın dışındaki herhangi bir şeyi girmesi ve bunu yaparken bir istisna atması için çevirmektir (eğer standart abs değerinin 180'den büyük olmaması gerektiğini söylerse açık bir ihlal). Bu arada, C # aslında istisnaların oldukça maliyetli olduğu dillerden biridir, bu yüzden onları gerçekten istisnai durumlarda kullanın, bu onu yakalamamak anlamına gelir, uygulamanızı bozmaz, bunun gibi durumlar.
Andy,

2
Belirli parametre değerlerini, özellikle de kodumun karşılamadığı şeyleri ileterek, kullanıcının ne anlama geldiğiyle ilgili varsayımlarda bulunmamaya meyilliyim. Benzer bir davaya benziyor.
JᴀʏMᴇᴇ

2
Web Mercator koordinatları -180 - 180 ve -90 - 90 arasında değildir . Bu enlem / boylamdır (ve bunun için birkaç koordinat sistemi bile vardır). Mercator projeksiyonları tipik olarak yüzbinlerce veya milyondadır ve "metre" birimlerine sahiptir (kesinlikle değil, çünkü her birimin uzunluğu kutuplara yaklaşırken gerçek zemin mesafesini arttırmayı kapsar). Derece cinsinden bile, ± 85.051129 dereceyle sınırlandırılmıştır, çünkü projeksiyon kutuplarda sonsuz genişler. (Sorunun özü olmadığı için bunu düzelten bir düzenleme gönderdim.)
jpmc26

Yanıtlar:


51

Sorunuzun özü bu ise ...

Bazı müşteri kodları, veri yapımın modellediği şey için değeri geçersiz bir argüman iletirse, değeri reddetmeli mi ya da mantıklı bir şeye dönüştürmeli miyim?

... o zaman benim genel cevabım "reddet" olacaktır, çünkü bu, müşteri kodunda geçersiz değerin programda görünmesine ve kurucunuza ulaşmasına neden olan potansiyel hatalara dikkat çekmesine yardımcı olacaktır. Hatalara dikkat çekmek, genellikle çoğu sistemde, en azından geliştirme sırasında (sisteminizin hata durumunda karışması istenen bir özellik olmadığı sürece) istenen bir özelliktir.

Asıl soru, bu dava ile karşı karşıya gelip gelmediğiniz .

  • Veri yapınız genel olarak kutupsal koordinatları modellemek için tasarlandıysa, -180 ve +180 aralığının dışındaki açılar gerçekten geçersiz olmadığı için değeri kabul edin. Mükemmel derecede geçerlidirler ve daima -180 ve +180 aralığında bir eşdeğerine sahip olurlar (ve onları bu aralığa hedeflemek istiyorsanız, çekinmeyin - müşteri kodunun genellikle ilgilenmesi gerekmez) .

  • Eğer veri yapınız açıkça Web Mercator koordinatlarını modelliyorsa (ilk formdaki soruya göre), şartnamede belirtilen herhangi bir hüküm takip etmek en iyisidir (bilmiyorum, bu konuda bir şey söylemeyeceğim) . Eğer bir şey sen modelleme spesifikasyonu bazı değerlerin geçersiz olduğunu söylüyor, onları reddetmek. Mantıklı bir şey olarak yorumlanabileceğini söylerse (ve dolayısıyla gerçekten geçerli olurlarsa), kabul et.

Mekanizma değerlerin kabul veya edilmemesine sinyale kullandığınız dilinin genel felsefesi ve performans gereksinimleri özelliklerine bağlıdır. Bu nedenle, bir istisna atarak (yapıcıda) veya yapınızın çürük halindeki bir sürümünü (özel bir yapıcıyı çağıran statik bir yöntemle) döndürerek ya da bir boole döndürerek yapınızı çağıran bir outparametre olarak (yeniden özel bir kurucu çağıran statik yöntem), vb.


12
-180 ila +180 aralığının dışındaki bir boylam muhtemelen kabul edilebilir olarak kabul edilmelidir, ancak -90 ila +90 aralığının dışındaki enlem saçma görünebilir. Biri Kuzey ya da Güney Kutbu'na ulaştığında, kuzey ya da güneyde daha fazla yolculuk tanımsızdır.
supercat

4
@supercat Sizinle aynı fikirdeyim ama Web Mercator spesifikasyonunda hangi değerlerin gerçekten geçersiz olduğunu bilmediğim için zor sonuçlara varmamaya çalışıyorum. OP sorunlu alanı benden daha iyi biliyor.
Theodoros Chatzigiannakis,

1
@supercat: Meridyenin ekvator'a ulaştığı yerden başlayın. enlemlere göre meridyen boyunca yolculuk. Enlem> 90 ise, o zaman aynı büyük çember boyunca devam edin. Sorun değil. Belgelendirin ve gerisini müşteriye bırakın.
kevin cline

4
@supercat Bundan daha kötü. Web Mercator projeksiyonunda ± 90 gerçekte sonsuz bir genişliğe yansıtılır. Bu yüzden standart aslında ± 85.051129'da keser. Ayrıca, lat / long! = Web mercator koordinatları. Merkatör koordinatları derece değil, metre değişken kullanır. (Kutuplara yaklaştıkça, her "metre" aslında daha büyük ve daha büyük bir toprak parçasına karşılık gelir.) OP koordinatları tamamen uzun / uzundur. Web Mercator'ın, bir Web Mercator temel haritasının tepesinde gösterilebileceğinden başka bir ilgisi yoktur ve bazı mekansal kütüphane onlar için kaputun altına yansır.
jpmc26

1
Asıl koordinat olmadığı için "± 85.051129'un eşdeğeri" demeliyim.
jpmc26

10

Bu çok bağlıdır. Ancak bir şeyler yapmaya ve belgelemeye karar vermelisiniz .

Sadece kesin yanlış yapmak için kodu için bir şey yanlışlıkla bazı davranışa sahip beklenen aralık ve yazma kodu dışında olabileceğini kullanıcı girişi dikkate unutmaktır. Çünkü o zaman bazı insanlar kodunuzun nasıl davrandığı ve hatalara neden olacağı konusunda yanlış bir varsayımda bulunacak, diğerleri ise kodunuzun kazayla yaptığı davranışa bağlı olarak (bu davranış tamamen bağlayıcı olsa bile) sona erecek ve böylece daha fazla hataya neden olacaksınız. sorunu daha sonra düzelttikten sonra.

Bu durumda her iki şekilde de argümanları görebilirim. Birisi 175 dereceden +10 dereceye kadar seyahat ederse, -175'te bitmelidir. Eğer her zaman normalleştirmek kullanıcı girişi ve -175 sonra müşteri koduna eşdeğer olarak tedavi 185 öylesine olamaz o 10 derece eklediğinde Yanlış bir şey yapmak; her zaman doğru etkiye sahiptir. Eğer bir hata olarak 185 görüyorsan istemci kodu (ya da en azından sizin normalizasyon prosedürü çağırmak unutmayın) normalleştirme mantığı koymak için göreli derecelerini ekleyerek her durumda zorlamak, aslında olacak nedeniHatalar (hızlıca ezilecek olanları yakalamak umarım kolay olsa da). Ancak, bir boylamsal sayı kullanıcı tarafından girilirse, programda kelimenin tam anlamıyla yazılırsa veya her zaman [-180, 180) 'de olması amaçlanan bir prosedürle hesaplanırsa, o zaman bu aralığın dışındaki bir değerin bir hatayı göstermesi çok muhtemeldir, yani "yararlı" "dönüştürmek sorunları gizleyebilir.

Bu durumda benim idealim muhtemelen doğru etki alanını temsil eden bir tür tanımlamak olacaktır. Soyut bir tür kullanın (müşteri kodunun yalnızca içindeki ham sayılara erişmesine izin vermeyin) ve hem normalleştirici hem de onaylayıcı bir fabrika sağlayın (böylece müşteri değişmeyi yapabilir). Ancak, bu tür bir değer ne yapılırsa yapılsın, 185, herkese açık API'nizden göründüğünde -175'ten ayırt edilemez olmalıdır (inşaatta dönüştürülüp dönüştürülmemeleri veya eşitliği, erişim sağlayıcıları ve farkı bir şekilde görmezden gelen diğer işlemleri sağlamanız farketmez) .


3

Bir çözüm seçmeniz sizin için gerçekten önemli değilse, kullanıcının karar vermesine izin verebilirsiniz.

Yapınızın salt okunur bir nesne olduğu ve bir yöntem / yapıcı tarafından yaratıldığı için, kullanıcının sahip olduğu seçeneklere bağlı olarak iki aşırı yükleme sağlayabilirsiniz:

  • Bir istisna atma (aralık dışı arg)
  • Değeri kısıtlamaya dönüştür

Ayrıca, kullanıcının diğer yöntemlere geçmek için geçersiz bir yapıya sahip olmasına asla izin vermeyin, oluşturma işlemini hemen yapın.

Düzenleme: yorumlara dayanarak, c # kullandığınızı varsayıyorum.


Giriş için teşekkürler! Bunu düşüneceğim, ancak biri kaçınabilseydi, istisna atama yapıcısının amacını baltalayacağından korkuyorum. Yine de ilginç!
K. Gkinis

Bu fikri kullanacaksanız, bir arayüz tanımlamak ve fırlatan veya dönüştüren iki uygulamaya sahip olmak daha iyi olacaktır . Bir yapıcıya, tanımladığınız gibi çalışacak şekilde makul bir şekilde aşırı yükleme yapmak zor olacaktır.

2
@Snowman: Evet, aynı argüman tiplerine sahip bir kurucuya aşırı yükleme yapmak zor olurdu, ancak iki statik yöntem ve özel bir kurucu olması zor olmazdı.
wchargin

1
@ K.Gkinis: İstisna atma yapıcısının amacı "uygulamanın öldüğünden emin olma" değildir - her şeyden önce müşteri her zaman catchistisnalarınızı yapabilir . Diğerlerinin dediği gibi, müşterinin istediği takdirde kendisini kısıtlamasına izin vermek . Gerçekten hiçbir şeyi atlatmıyorsun.
wchargin

Bu öneri, yararsızlık için kodu zorlaştırmaktadır. Ya yöntem geçersiz girişi dönüştürmeli ya da değiştirmemelidir. İki aşırı yüke sahip olmak, ikilemi çözmeden kodu daha karmaşık hale getirir.
JacquesB

0

Girişin doğrudan bir kullanıcı tarafından bazı kullanıcı arabirimi aracılığıyla mı yoksa sistemden mi yapıldığına bağlıdır.

Bir kullanıcı arayüzü üzerinden giriş

Geçersiz girdilerin nasıl kullanılacağı bir kullanıcı deneyimi sorusudur. Dava hakkında bir şey bilmiyorum ama genel olarak birkaç seçenek var:

  • Kullanıcıyı hataya karşı uyarın ve devam etmeden önce kullanıcının onu düzeltmesini sağlayın (En yaygın)
  • Otomatik olarak geçerli aralığa dönüştür (mümkünse), ancak kullanıcıyı değişiklik konusunda uyar ve devam etmeden önce kullanıcının doğrulamasını sağla.
  • Sessizce geçerli aralığa dönüştürün ve devam edin.

Seçim, kullanıcıların beklentilerine ve verilerin ne kadar kritik olduğuna bağlıdır. Örneğin Google, sorgularda yazımı otomatik olarak düzeltir, ancak yararsız bir değişiklik sorun olmadığından ve düzeltmesi kolay olduğu için bu düşük risklidir (ve o zaman bile sorgunun değiştiği sonuç sayfasında açıkça belirtilmiştir). Diğer yandan, bir nükleer füze için koordinatlar giriyorsanız, daha katı bir giriş doğrulaması ve sessiz geçersiz veri düzeltmeleri istemeyebilirsiniz. Yani evrensel bir cevap yok.

En önemlisi, girişi düzeltmenin kullanıcı için bir faydası olup olmadığını göz önünde bulundurmalısınız. Bir kullanıcı neden geçersiz veri girsin? Birinin nasıl yazım hatası yapabileceğini görmek kolaydır, ama neden biri -185 boylamına girsin ki? Kullanıcı gerçekten +175 anlamına geldiyse muhtemelen +175 yazmış olacaktı. Bence bu büyük olasılıkla geçersiz boylam basit bir yazım hatası olduğunu ve kullanıcı anlamına -85 veya başka bir şey olduğunu. Bu durumda sessizce dönüştürme kötü ve yararsızdır . Uygulamanız için en kullanıcı dostu yaklaşım, kullanıcıyı geçersiz değere karşı uyarmak ve kullanıcının kendileri düzeltmesini sağlamak olabilir.

API üzerinden giriş

Giriş başka bir sistemden veya alt sistemden geliyorsa, soru yoktur. Bir istisna atmalısın. Geçersiz girişi başka bir sistemden silmemelisiniz, çünkü sistemdeki herhangi bir yerde hataları maskeleyebilir. Girdi "düzeltildi" ise, UI katmanında gerçekleşmeli, sistemde daha derinde olmamalıdır.


0

Bir istisna atmalısın.

Verdiğiniz örnekte, 185'i gönderiyor ve bunu -175'e çeviriyorsanız, o zaman bazı durumlarda bu işlevselliği sağlamak kullanışlı olabilir. Peki ya arayan 1 milyon gönderirse? Gerçekten bunu dönüştürmek mi istiyorlar? Bir hata olduğu daha muhtemel görünüyor. Öyleyse, 1.000.000 için bir istisna atmanız gerekirse ancak 185 için bir istisna atmanız gerekirse, bir istisna atmak için keyfi bir eşik hakkında karar vermeniz gerekir. Bazı arama uygulamaları eşiğin etrafına değer gönderiyor olduğundan, bu eşik bir süre sizi yukarı çeker.

Aralığın dışındaki değerler için istisna atmak daha iyidir.


-1

Bir geliştirici için en uygun seçenek, aralık dışı değerler için platformda bir derleme zamanı hata desteği olacaktır. Bu durumda, aralık aynı zamanda parametre türlerinde olduğu gibi yöntem imzasının bir parçası olmalıdır. Aynı şekilde, yöntem imzanız bir tamsayı alacak şekilde tanımlanmışsa API kullanıcınız bir Dize iletemezse , kullanıcının değerin yöntem imzasında verilen aralık dahilinde olup olmadığını kontrol etmeden bir değeri geçememesi gerekirdi. İşaretli değilse derleme zamanı hatası almalı ve çalışma zamanı hatası önlenebildi.

Ancak şu anda çok az sayıda derleyici / platform bu tür bir derleme zamanı denetimini desteklemektedir. Yani, bu bir geliştirici baş ağrısı. Ancak ideal olarak, yönteminiz desteklenmeyen değerler için anlamlı bir istisna atmalı ve açıkça belgelendirmelidir.

BTW, Joe Duffy'nin burada önerdiği hata modelini gerçekten çok seviyorum .


Kullanıcı girişi için derleme zamanı hatalarını nasıl sağlarsınız?
JacquesB

@JacquesB Kullanıcı girişi, aralıktaki gerçek değerden bağımsız olarak, yerleştirmeden sonra aralık içinde olup olmadığına bakılmazsa hata verir .
Gulshan

Ancak girdiyi reddetmek veya geçerli bir aralığa dönüştürmek isteyip istemediğinize karar vermeniz gerekir, bu nedenle orijinal soruya cevap verilmez.
JacquesB

@JacquesB Bunu söylemeliyim, ilk başta her zaman, OP'nin bir API geliştirdiğini ve kullanıcı arayüzünün API'sini tüketen bir başkası tarafından geliştirildiğini düşündüm. Bu konuda yanılmışım. Sadece soruyu tekrar okudum ve bunu anladım. Söylemeye çalıştığım tek şey, doğrulama API tüketicilerinde yapılmalı ve değilse derleyici bir hata yapmalıdır.
Gulshan

Bu yüzden ... girdileri ve doğrulamaları içeren yeni bir sınıf oluşturmanız gerekir. Annnnnd, class nesnesini ham girdilerden oluşturduğunuzda ne olur? Bir istisna atmak? Sessizce geçmek? Sen sadece problemi taşı.
djechlin

-1

Bir istisna atmak için varsayılan değer olmalıdır. strict=falseElbette strict=truevarsayılan olarak bayrağa bağlı olarak, zorlama gibi bir seçeneğe izin verebilir ve yapabilirsiniz . Bu oldukça yaygındır:

  • Java esnekliğiDateFormat destekliyor .
  • GSON JSON ayrıştırıcı ayrıca destekler hafif modu.
  • Vb.

Bu kod yarar için kodunu zorlaştırıyor.
JacquesB

@JacquesB varsayılan olarak istisna atıyor veya izin veriyor strict=falsemu?
djechlin

@JacquesB Sıkı ve esnek modları destekleyen bazı API örnekleri ekledim, lütfen bir göz atın.
djechlin

-2

Benim için en iyi uygulama kullanıcı girişini asla değiştirmemek. Genelde benim yaptığım yaklaşım, onaylamayı yürütmeden ayırmak.

  • Sadece verilen parametreleri kullanan basit bir sınıf var.
  • Yürütme sınıfını etkilemeden, istendiğinde değiştirilebilecek bir doğrulama katmanı sağlamak için bir dekoratör kullanın (veya bu yaklaşım çok zorsa başka bir onaylayıcı enjekte edin).

Soruya atıfta bulunan "kullanıcı", son kullanıcıyı değil API'yi kullanan geliştiricidir ...
Jay Elston
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.