11 Şubat 2019 Pazartesi

Verilen Parametrelerin Doğruluğunu Kontrol Etmek - Validation

Verilen Parametrelerin Doğruluğunu Kontrol Etmek - Validation Check
Validation check yaparken temel yöntemler var. Bir çok çatı ve kütüphanede her 3 yöntem de kullanılıyor.

1 . Magic value dönmek 
- null , -1 gibi bir değer döner. Magic value döngü içinde kullanılan stream sınıfları için çok uygun. StreamReader. Read gibi. Ya da index döndüren IndexOf gibi metodlar için de rahatlıklar kullanılabilir.

2. Exception atmak
Normalde çağrının çalışmasını bekler. Eğer gerçekten istisnai bir durum varsa exception atılabilir.
Bir diğer tabirle crach early de denilir.

Örnek
if not file.exists() :
  throw toysOutOfPram

if not validate(file) :
  throw foodAtMummy

# do stuff with file...
Magic Value dönmek ile Exception atmak seçenekleri arasında ciddi çekişme var.
Favour exceptions over error codes
şeklinde çalışan bir ekol, ve Objective-C gibi bu yöntemi tercih etmeyen bir başka ekol var.

Ayrıca Leaky Abstraction isminde bir arayüzün atılacak exception'ları belirlememesi yönünde fikirler de havada uçuşuyor.

3. false dönmek ve bir out parametre ile gerçek sonucu dönmek
Çağrı bir şeyin olup olmayacağını kontrol etmek içinse bu yöntem kullanılabilir. Dictionary.TryGetValue gibi.

4. Özel bir sonuç nesnesi dönmek
Bu yöntemi hiç kullanışlı bulmuyorum.
interface IMyResult
{
    bool Success { get; }
    // Only access this if Success is true
    MyOtherClass Result { get; }
    // Only access this if Success is false
    string ErrorMessage { get; }
}

Validation Check Nerede Yapılmalı
Yani validation check her zaman metodun başında yapılmalı. Martin Fowler, Specification Pattern ismiyle, bu kullanımı daha da karmaşık hale getirmiş.

Validation check yaparken tek return kuralında ısrar etmek uygun değil.

Örnek
Aşağıdaki örnekte basit bir validation check var. Hata varsa metod hemen dönüyor. Yapılacak gerçek iş ise rahatça okunabiliyor.
public String getSomeValue(String arg) {

  if (arg == null) {
    return "";
  }

  ...
  ...
  ...
  valueToReturn = "some value;

  return valueToReturn;
}
Örnek
Bu örnekteyse ise validation check validation check ve gerçek iş aşağıdaki if/else ifadesinin içinde. Bu bencence okuması daha zor bir kod.
public String getSomeValue(String arg) {

  String valueToReturn = null; 

  if (arg==null) {
     valueToReturn = "";
  }  else {
     ...
     ...
     ...
     valueToReturn = "some value";
  }

  return valueToReturn;
}
Örnek
Bu örnekteyse ise validation check validation check ve gerçek iş aşağıdaki if/else ifadesinin içinde. Bu bencence okuması daha zor bir kod.
function some_fun( a ) {
    var result;

    if ( !a ) {
        result = false;
    } else {
        // some big piece of code
        // with many levels of indention
        // and so on
        if ( /*  */ ) {
            // some code
            result = 1;
        } else {
            result = 2;
        }
    }

    return result;
}
Validation Sınıfın Kendi İçinde Olmalı
Örnek
Elimizde şöyle bir kod olsun.
new ZipCode("totally invalid zip code");
Validate etmek için şöyle yapalım
ZipCodeHelper.validate("totally invalid zip code");
Bu kullanım yanlış. Validation sınıfın içinde olmalı Şöyle yaparız.
public class ZipCode {
  private String zipCode;

  public ZipCode(string zipCode) {
    if (!validate(zipCode))
       throw new IllegalFormatException("Invalid zip code");

    this.zipCode = zipCode;
  }

  public static bool validate(String zipCode) {
    // logic to check format
  }

  @Override
  public String toString() {
    return zipCode;
  }
}
Validation Check İçin Kullanılan Diğer Örüntüler
Guard ve Monad var.
Guard
Özellikle notNull, exists gibi şeylerde kullanılıyor.
public void MyAction(string param) {
    Guard.Require(param).NotNull();
}
Monad 
En az 3 karakter olmalı benzeri kurallar için kullanılıyor.
public void MyAction(User user) {
    Guard.Require(user).NotNull();
    MyBusinessValidatorForUsers(user).UserNameAtLeast3Chars();
}



Hiç yorum yok:

Yorum Gönder