domenica 29 aprile 2007

Lasciare che si verifichi l'errore e poi intercettarlo o verificare prima?

A volte capita di porsi il problema se sia più performante intercettare l'errore oppure realizzare una verifica personalizzata.

La migliore soluzione credo dipenda da molte cose, se ad esempio il verificarsi dell'errore non influisce sulle prestazioni del programma e si sta interagendo con l'utente è perfettamente plausibile lasciare che l'eccezione abbia luogo.
Invece se si è all'interno di un blocco / ciclo, e cioè quando il programma sta svolgendo del lavoro su molti dati (magari l'operatore viene tentato di premere il famigerato bottone "stop") allora la domanda "intercetto o verifico l'errore?" comincia ad avere senso.

Ho trovato in rete questo frammento relativo allo stesso controllo di validità di una data, frammento che propongo:

Verifica dei dati e dell'errore prima dell'eccezione.

C#

GregorianCalendar calendar = new GregorianCalendar();
Regex verify = new Regex(@"^(0[1-9]|[1-2]\d|3[0-1])/(0[1-9]|1[0-2])/(\d\d\d\d)$",RegexOptions.Compiled);
for (int i = 0; i < 1000000; i++) {
     string date = "14/12/2006"
     Match match = verify.Match(date);
     if (match.Groups.Count == 4) {
        int year = int.Parse(match.Groups[3].Value);
        int month = int.Parse(match.Groups[2].Value);
        int day = int.Parse(match.Groups[1].Value);
        if (day <= calendar.GetDaysInMonth(year, month)) {
           DateTime theDate = new DateTime(year, month, day);
       }
   }
}

VB.NET
Dim calendar As New GregorianCalendar()
Dim verify As New Regex("^(0[1-9]|[1-2]\d|3[0-1])/(0[1-9]|1[0-2])/(\d\d\d\d)$", RegexOptions.Compiled)
For i As Integer = 0 To 999999
   Dim [date] As String = "14/12/2006"
   Dim match As Match = verify.Match([date])
   If match.Groups.Count = 4 Then
       Dim year As Integer = Integer.Parse(match.Groups(3).Value)
       Dim month As Integer = Integer.Parse(match.Groups(2).Value)
       Dim day As Integer = Integer.Parse(match.Groups(1).Value)
      If day <= calendar.GetDaysInMonth(year, month) Then
          Dim theDate As New DateTime(year, month, day)
      End If
   End If
Next

Con questo metodo si processano un milione di date in circa tre secondi e si "spende" un secondo per intercettare un milione di date errate in meno di un secondo (ovviamente questo va ricondotto alla propria installazione)

Si lascia che l'errore avvenga e si intercetta l'eccezione

C#

for (int i = 0; i < 1000000; i++) {
   string date = "12/13/2006"
   try {
       DateTime theDate = DateTime.ParseExact(date, "dd/MM/yyyy", CultureInfo.InvariantCulture);
   }
   catch (Exception ex)
   {
   }
}

 

VB.NET

For i As Integer = 0 To 999999
    Dim [date] As String = "12/13/2006"
    Try
       Dim theDate As DateTime = DateTime.ParseExact([date], "dd/MM/yyyy", CultureInfo.InvariantCulture)
    Catch
   End Try
Next

 

Con questa seconda strategia vengono analizzate un milione di date corrette in meno di un secondo però ... ad intercettare un milione di date errate intercettando l'errore ci mette 60 secondi!.

Con il framework 2.0 sono stati introdotti alcuni TryParse che sono sicuramente da preferire rispetto all'intercettazione dell'errore.

In conclusione: qualsiasi test precedente è migliore di lasciare che si verifichi l'errore.

Nessun commento: