jueves, 26 de febrero de 2015

Atributos personalizados

Situación:

Tengo una dll con sus clases, métodos y acceso a base de datos (insertar, modificar y muestra por pantalla una determinada clase).
Tengo que cambiar el acceso de base de datos por un acceso a un servicio web (que no hacemos nosotros)
El servicio web proporciona unos objetos que no se ajustan nuestras clases originales

Requisitos:

Que fuera una dll es significativo porque quiere decir que se usa por varias aplicaciones y por lo tanto la modificación de las clases debe tener el menor impacto posible .

Solución:

  • Para empezar duplique la dll existente cambiando el nombre al ensamblado
  • Identifique los valores de nuestras tablas y propiedades con su correspondencia en el servicio web
  • Quite el acceso a datos por las llamadas al servicio web
  • Mi "problema" se complicó cuando comprobé que no sería todo tan sencillo:
    • tendría aplicaciones que posiblemente hiciera consultas SQL a esas tablas (usando evidentemente el nombre de las columnas)
    • El servicio web, me proporciona métodos para hacer la consultas, pero no pasando como parámetros un objeto sino lista de clave-valor , donde la calve era del tipo campo1,campo2.. (no me preguntéis porque esa codificación)
  • A mis clases de entidad les añadí un atributo personalizado. Esto me permitía relacionar las tablas SQL con los parámetros del servicio web con un mínimo impacto.
Adjunto un ejemplo sencillo, para que veas que es bastante sencillo de usar.


Module miEjemplo

    Public Sub Ejemplo()
        Dim miSqlViejo = "select dni, nombre from personas "
        For Each attribute As MiEntityAttribute In MiEntityAttribute.GetMiEntityAttribute(GetType(miClaseDecorada)).Values
            If Not attribute Is Nothing Then
                miSqlViejo = miSqlViejo.Replace(attribute.ColumnaOLD, attribute.ColumnaNew)
            End If
        Next
        Console.Write(miSqlViejo) 'select dni_cif, nombreCompleto from personas
    End Sub
    Public Class miClaseDecorada
        Private _dni As String
        Private _nombre As String

        <MiEntity("dni", "dni_cif")>
        Public Property DNI() As String
            Get
                Return _dni
            End Get
            Set(ByVal value As String)
                _dni = value
            End Set
        End Property

        <MiEntity("nombre", "nombreCompleto")>
        Public Property Nombre() As String
            Get
                Return _nombre
            End Get
            Set(ByVal value As String)
                _nombre = value
            End Set
        End Property

    End Class

    ''' <summary>
    ''' Atributos personales
    ''' </summary>
    ''' <remarks></remarks>
    <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)>
    Friend Class MiEntityAttribute
        Inherits Attribute

        Private _columnaBDOLD As String
        Private _columnaBDnew As String

        Public Sub New()
        End Sub

        Public Sub New(columnaBDOLD As String, columnaBDnew As String)
            Me._columnaBDOLD = columnaBDOLD
            _columnaBDnew = columnaBDnew
        End Sub
        ''' <summary>
        ''' Nombre de la propiedad dentro de la base de datos vieja
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overridable ReadOnly Property ColumnaOLD() As String
            Get
                Return _columnaBDOLD
            End Get
        End Property
        ''' <summary>
        ''' Nombre de la propiedad dentro de la base de datos nueva
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overridable ReadOnly Property ColumnaNew() As String
            Get
                Return _columnaBDnew
            End Get
        End Property
        Friend Shared Function GetMiEntityAttribute(ByVal ot As Type) As Dictionary(Of String, MiEntityAttribute)
            Dim oret As Dictionary(Of String, MiEntityAttribute) = New Dictionary(Of String, MiEntityAttribute)
            For Each propiedad As PropertyInfo In ot.GetProperties()
                If propiedad.GetCustomAttributes(GetType(MiEntityAttribute), False).Any() Then
                    oret.Add(propiedad.Name, CType(propiedad.GetCustomAttributes(GetType(MiEntityAttribute), False)(0), MiEntityAttribute))
                Else
                    oret.Add(propiedad.Name, Nothing)
                End If
            Next
            Return oret

        End Function
    End Class
End Module
Documentación al respecto: MSDN
Por supuesto pensé en un método "tradicional" : funciones para convertir objetos, enumerados que mantengan la relaciones entre las distintas propiedades…Pero el uso de los atributos me parece que da una solución sencilla y fácil de mantener.
Supongo que los trabajan con MVC el tema de los atributos lo tienen más que superado. Pero si eres de asp o de aplicaciones de escritorio, esto te facilita la vida con poco esfuerzo.

Otra solución con interfaces :http://blog.koalite.com/2015/03/interfaces-marcadoras-atributos-y-convenciones/

viernes, 13 de febrero de 2015

Formación

¿Estudias o trabajas? Bueno yo siempre contesto que la dos cosas, te dediques a lo que te dediques siempre hay que estar formándose. La informática no es una excepción.
Podríamos hablar de formación de en la empresa, pero si están en una consultora para un cliente, lo tendrás bastante mal.
Aquí un par de sugerencias , se hacen on-line, son gratis, en castellano.. el interés lo pones tú

http://www.microsoftvirtualacademy.com/

https://www.miriadax.net/

Y

http://www.openeducationeuropa.eu/es/find/moocs