sábado, 17 de enero de 2009

El patrón de diseño Singleton

El patrón de diseño Singleton, o de Instancia única, nos permite asegurar que de una determinada clase sólo hay un instancia en todo el sistema.

La idea es que nuestra clase Singleton no mostrará públicamente las operaciones necesarias para su instanciación (constructor) y por lo tanto será ella quien misma quien gestiones su instanciación.

Imaginaros la típica clase de acceso a la base de datos o a unos datos de configuración o a un sistema de escribir un fichero LOG. Realmente son tareas que realizamos en todos nuestros programas y seguramente lo resolvemos guardando información en variables globales o realizando el proceso de carga o configuración cada vez que lo necesitamos.
En todos estos casos es muy interesante tener la posibilidad de tener una clase común que nos proporcione acceso a sus recursos pero sin tener que estar instanciando la clase cada vez que la necesitamos.

La implementación de patrón Singleton en VB.NET sería así:

Public NotInheritable Class Singleton

Private Shared _Instance As Singleton = Nothing
Private Shared ReadOnly _Sync As New Object

Private Sub New()
End Sub

Public Shared ReadOnly Property Instance() As Singleton
Get
If _Instance Is Nothing Then
SyncLock _Sync
If _Instance Is Nothing Then
_Instance = New Singleton()
End If
End SyncLock
End If
Return _Instance
End Get
End Property

End Class


Para utilizar la clase que hemos creado simplemente hay que definir una variable de ese objeto y llamar a la propiedad Instance.


Dim MiSingleton As Singleton = Singleton.Instance
'Ejemplo de llamada de un Metodo de Singleton
MiSingleton.HacerAlgo()



Aquí os dejo el fichero Singleton.vsi que os permitirá incluir en vuestro Visual Studio el code snippet del patrón Singleton.

martes, 13 de enero de 2009

Gestión global de excepciones

Software bug 04

Aunque cada vez el software que desarrollamos es más robusto la verdad es que nadie se escapa de dejar algún gazapo que en cualquier momento se le presentará al usuario final en forma de un horrible mensaje de error.

Si queremos evitar estas situaciones podemos definir los eventos UnhandledException y ThreadException en nuestros programa y problema resuelto. La verdad es que no parece demasiado lógico que tengamos que definir dos eventos para capturar las excepciones que no controlamos pero el primero se encarga de manejar las que no tienen que ver con el interface gráfico y el segundo se encarga de las visuales.

La implementación sería de la siguiente manera:

  1. Definición de los eventos:
    Private Sub Form1_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load

    Dim currentDomain As AppDomain = AppDomain.CurrentDomain
    AddHandler currentDomain.UnhandledException, AddressOf AppDomain_UnhandledException
    AddHandler Application.ThreadException, AddressOf Application_ThreadException

    End Sub


  2. Declaración del evento que maneja la UnhandledException:

    Private Sub AppDomain_UnhandledException(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)

    Dim st As New StackTrace()
    Dim pila As String = st.ToString() 'Obtenemos el estado actual de la pila

    Dim ex As Exception = DirectCast(e.ExceptionObject, Exception)

    'Acciones a realizar para registrar las excepciones
    MessageBox.Show("UnhandledException" & ex.Message)

    End Sub


  3. Declaración del evento que maneja la ThreadException:

    Private Sub Application_ThreadException(ByVal sender As Object, ByVal e As Threading.ThreadExceptionEventArgs)

    Dim st As New StackTrace()
    Dim pila As String = st.ToString()

    'Acciones a realizar para registrar las excepciones
    MessageBox.Show("ThreadException" & e.Exception.Message & ". " & pila)

    End Sub


¡Y eso es todo! Ahora ya no hay excusa para no facilitarle el trabajo al usuario final mostrándole esos feos mensajes de error y además nos permitirá registrar toda la información existente en el sistema en el momento que se lanzó la excepción.