domingo, 7 de diciembre de 2008

La función Replace de Microsoft.VisualBasic

Etiquetas de Technorati: ,

Muchos de los que ahora programamos en VB.NET venimos del viejo mundo del VB6, ese mundo de caos donde no existía la orientación a objetos y para muchas cosas tenias que tirar de la API de Windows.

Ahora que utilizamos VB.NET nuestro mundo se ha simplificado mucho pero tenemos que ir con cuidado ¡sin darnos cuenta vamos y volvemos al lado oscuro! Ya que dentro del framework existe la librería Microsoft.VisualBasic.dll que es un vínculo que nos han dejado los desarrolladores de Microsoft para que la transición fuera menos traumática.
El problema es que ese vínculo que nos dejaron con el pasado afecta directamente contra el rendimiento de nuestras aplicaciones. Un ejemplo claro de sería la función Replace.


Dim str As String = "ABA"
str = Replace(str, "A", "X")


Cuando utilizamos la función Replace, estamos llamando la función que hay en la librería Microsoft.VisualBasic, denominada Strings.Replace.









Si decompilamos esta función, con .NET Reflector, vemos que realmente se llama a la siguiente función:

















   1: Public Shared Function Replace(ByVal Expression As String, ByVal Find As String, ByVal Replacement As String, ByVal Optional Start As Integer = 1, ByVal Optional Count As Integer = -1, <OptionCompare> ByVal Optional [Compare] As CompareMethod = 0) As String








   2:     Dim str As String








   3:     Try 








   4:         If (Count < -1) Then








   5:             Throw New ArgumentException(Utils.GetResourceString("Argument_GEMinusOne1", New String() { "Count" }))








   6:         End If








   7:         If (Start <= 0) Then








   8:             Throw New ArgumentException(Utils.GetResourceString("Argument_GTZero1", New String() { "Start" }))








   9:         End If








  10:         If ((Expression Is Nothing) OrElse (Start > Expression.Length)) Then








  11:             Return Nothing








  12:         End If








  13:         If (Start <> 1) Then








  14:             Expression = Expression.Substring((Start - 1))








  15:         End If








  16:         If (Find Is Nothing) Then








  17:             Return Expression








  18:         End If








  19:         If ((Find.Length = 0) OrElse (Count = 0)) Then








  20:             Return Expression








  21:         End If








  22:         If (Count = -1) Then








  23:             Count = Expression.Length








  24:         End If








  25:         str = Strings.ReplaceInternal(Expression, Find, Replacement, Count, [Compare])








  26:     Catch exception As Exception








  27:         Throw exception








  28:     End Try








  29:     Return str








  30: End Function














Esta a su vez llama a :

















   1: Private Shared Function ReplaceInternal(ByVal Expression As String, ByVal Find As String, ByVal Replacement As String, ByVal Count As Integer, ByVal [Compare] As CompareMethod) As String








   2:     Dim ordinal As CompareOptions








   3:     Dim compareInfo As CompareInfo








   4:     Dim num5 As Integer








   5:     Dim length As Integer = Expression.Length








   6:     Dim num2 As Integer = Find.Length








   7:     Dim builder As New StringBuilder(length)








   8:     If ([Compare] = CompareMethod.Text) Then








   9:         compareInfo = Utils.GetCultureInfo.CompareInfo








  10:         ordinal = (CompareOptions.IgnoreWidth Or (CompareOptions.IgnoreKanaType Or CompareOptions.IgnoreCase))








  11:     Else








  12:         compareInfo = Strings.m_InvariantCompareInfo








  13:         ordinal = CompareOptions.Ordinal








  14:     End If








  15:     Do While (num5 < length)








  16:         Dim num4 As Integer








  17:         If (num4 = Count) Then








  18:             builder.Append(Expression.Substring(num5))








  19:             Exit Do








  20:         End If








  21:         Dim num3 As Integer = compareInfo.IndexOf(Expression, Find, num5, ordinal)








  22:         If (num3 < 0) Then








  23:             builder.Append(Expression.Substring(num5))








  24:             Exit Do








  25:         End If








  26:         builder.Append(Expression.Substring(num5, (num3 - num5)))








  27:         builder.Append(Replacement)








  28:         num4 += 1








  29:         num5 = (num3 + num2)








  30:     Loop








  31:     Return builder.ToString








  32: End Function














Conclusión:








Cuando hacemos un Replace realmente estamos creando un StringBuilder y ejecutando un bucle While. Increible, ¿no?









Solución:








Normalmente cuando utilizamos esta función es para realizar un reemplazo de todas la coincidencia y no utilizamos la mayoría de opciones de ofrece la función Replace. Yo me simplifico la vida y utilizo la que viene nativa con el tipo String.

















   1: Dim str As String = "ABA"








   2: str = str.Replace("A", "X")














That's it!

domingo, 30 de noviembre de 2008

Las reglas de la optimización son sencillas. Regla 1: No optimices. Regla 2 (solo para expertos): No optimices todavía.

Cuantas veces estamos delante de un programa, creando una función y de repente nos desviamos de nuestro objetivo principal para emprender una cruzada para reducir el tiempo de procesamiento e intentar lograr que esa función o procedimiento se ejecuto lo más rápido posible.
Seguramente esta situación nos la encontramos más veces de las que deseamos.

Este proceso se denomina optimización prematura y se produce cuando el programador permite que las consideracionesStop ! Right now !s de reducción del tiempo o espacio afectan al diseño inicial.

Normalmente las decisiones de optimización en la etapa de codificación son subjetivas, básicamente se basan en las sensaciones que el programador tiene durante esta fase y no en datos empíricos.

Antes de iniciar un proceso de optimización del código fuente os recomiendo:

  1. Asegurarse que sigue el diseño preestablecido en las etapas anteriores.
  2. Crear una batería de pruebas que nos permita confirmar que cumple todas las funcionalidades acordadas en el análisis funcional.
  3. No optimices.

Las optimizaciones de código se deben hacer siempre después de que este se haya finalizado y probado correctamente certificando así que cumple las especificaciones funcionales establecidas en las etapas previas.
Es preferible no optimizar hasta que realmente lo necesitemos, en ese momento se deberá estudiar dónde y cómo optimizar ya que no todo depende de nuestro código fuente y pueden existir recursos externos se deban tener en cuenta.