Como rescatar de las llamas del infierno un MDF sin el LDF

agosto 11, 2009 07:27 by sergio

Tomando como referencia el tipo de redacción de mi colega DDAZ voy a escribir este POST haciendo alusión a un “posible” caso de la vida real. Quiero aclarar que no soy DBA y no soy una eminencia optimizando sentencias SQL o una cosa por el estilo. Los nombres utilizados y su parecido con la realidad son mera coincidencia. 

El DBA despistado 

Josué, el encargado de la integridad de la información  y de los aspectos ambientales de la información de de una prestigiada empresa prestadora de servicios de tecnología (DBA), consiente y preocupado ante cualquier proceso de recuperación de desastres, análisis de rendimiento y optimización de base datos, olvidó (“por error”). Programar ya sea incrementalmente, diferencialmente o totalmente respaldos propios de la información contenida en las bases de datos de la compañía. 

Un día (viernes, que raro), ocurrió algo que estaba contenido en el plan de recuperación a desastres y solo se pensaba que podría llegar a ocurrir si el experimento que se está realizando en Suiza (entre las montañas del Jura y el lago de Ginebra), generara un poderoso arranque de gravedad que comprimiera la materia y terminara con la vida tal cual la conocemos. Un simple apagón de energía eléctrica, lo cual ocasionó que se dañaran varios sectores en disco duro, se malogrará el sistema de arranque del sistema operativo y se perdieran los log de transacciones de todas las bases de datos (LDF).

Cabe mencionar que el SMBD era SQL Server. La empresa sufrió mucho operativamente y la información vital de la misma, jamás se pudo recuperar. JAMÁS!! 

¿Por qué Sucedió esto? 

Josué, como todo profesionista promedio, tuvo un escenario en donde la teoría no sirve para nada ante situaciones prácticas donde se requiere actuar rápido para mantener el negocio. Adicionalmente también desconocía las bondades y la importancia de realizar respaldos de sus bases de datos como lo detalla la siguiente tabla*: 

 

Respaldo

Archivos en Respaldo Ventajas Desventajas
Completo ("Full") Todos Con este respaldo únicamente es posible recuperar toda la información Tiempo de Ejecución
De Incremento ("Incremental") Archivos con archive bit activo.(Aquellos que hayan cambiado desde el último Respaldo Completo) Velocidad Requiere del último Respaldo Completo y de todos los Respaldos de Incremento que le siguieron para recuperar el Sistema
Diferencial ("Differential") Archivos con archive bit activo.(Aquellos que hayan cambiado desde el último Respaldo Completo) Sólo requiere del último Respaldo Completo y del último respaldo Diferencial Ocupa mayor espacio en discos comparado con Respaldos de Incremento

*Clasificación de Respaldos. Osmosis Latina - http://www.osmosislatina.com/soporte/respaldos.htm 

¿Qué hacer si ya valió? 

Cabe mencionar que la siguiente alternativa solo funciona para SQL Server y no es una opción muy “elegante” al problema, yo sigo la siguiente filosofía: “A problemas piñatas, soluciones piñatas”, no por algo tengo un diploma a las “marranadas” (hablando de soluciones tecnológicas). 

La solución propuesta sería: 

1.    Crear las bases de datos afectadas en blanco, detener el servicio de SQL Server y cambiar el MDF por el que rescataron del server caído (Q.E.P.D). 

2.    Eliminar el LDF que se generó en blanco y reiniciar el servicio de SQL. Dado esto debería marcar la base de datos como suspect. 

3.    Posicionarse en la base de datos MASTER (USE MASTER) 

4.    Cambiar las opciones de configuración global del servidor actual para que permita hacer cambios al mismo. 

EXEC sp_Configure 'ALLOW UPDATES', 1
RECONFIGURE WITH OVERRIDE 

5.    Cambiar el estado de la base de datos a MODO DE EMERGENCIA. 

UPDATE SYSDATABASES SET STATUS = 32768 WHERE NAME = 'NombreBaseDeDatos'  

6.    Cambiar las opciones de configuración global del servidor actual para que ya no permita hacer cambios al mismo

EXEC sp_Configure 'ALLOW UPDATES', 0
RECONFIGURE WITH OVERRIDE 

7.    Cambiar la base de datos afectada a opción de usuario simple. 

EXEC sp_DBOption 'ArchivoIntegracion', 'SINGLE USER', 'TRUE' 

8.    Reconstruir el LOG de transacciones (LDF) de la base de datos (MDF). 

DBCC REBUILD_LOG ('NombreBaseDeDatos', 'C:\Program Files\Microsoft SQL Server\MSSQL\Data\NombreBaseDeDatos_Log.ldf') 

9.    Cambiar las opciones de configuración global del servidor actual para que permita hacer cambios al mismo. 

EXEC sp_Configure 'ALLOW UPDATES', 1
RECONFIGURE WITH OVERRIDE 

10. Cambiar el estado de la base de datos a MODO NORMAL. 

UPDATE SYSDATABASES SET STATUS = 0 WHERE NAME = 'NombreBaseDeDatos' 

11. Cambiar las opciones de configuración global del servidor actual para que ya no permita hacer cambios al mismo 

EXEC sp_Configure 'ALLOW UPDATES', 0
RECONFIGURE WITH OVERRIDE 

12. Cambiar la base de datos afectada a opción de usuarios múltiples. 

EXEC sp_dboption 'ArchivoIntegracion', 'SINGLE USER', 'FALSE' 


Y voila, ya quedó milagrosamente rescatado nuestro MDF sin necesidad de contar con el LDF respectivo. Josué ya puede estar más tranquilo al respecto y tener más cuidado para la próxima vez que ocurra esto en su organización (que esperemos y jamás vuelva a suceder).


Actualmente calificado con 5.0 por 3 personas

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

VSTO Capitulo 1 - Aplicaciones con Office? y eso como se come?

agosto 6, 2009 01:07 by ddaz

Les cuento 2 historias…., de esas que casi nunca ocurren –mínimo unas 500 veces al día en todo el mundo -  en un lugar muy muy lejano – quizá a 5 metros de Uds.-, cualquier parecido con la realidad, es pura coincidencia!!.

1 - El y  Su Amado Excel:

Era una persona, común y silvestre, que había estudiado alguna carrera de administración o0049648001181143847-shin-chan-enfadado quizá contabilidad o derecho, pudiera ser hasta “secretariado computarizado bilingüe” – y en mas extraño de los casos puede ser medico-, el punto es  que sus bastos conocimientos de computación –o informática- se extendían a un curso de “computación u Ofimática” de unos 6 meses – o quizá un poco mas-, sabe manejar a la perfección el Word, Excel, Outlook y el PowerPoint es súper especialista usando el MSN y sabe aplicarle parches para usar varias cuentas de Messenger a la vez, sin contar sus amplios conocimientos en Hi5, MetroFlog, FaceBook; esta persona como tal, siente que ya sabe lo suficiente y no le interesa saber mas de “computación”, ya que sabe que si tiene algún problema, existen unos seres extraños al que llama nerds, y que por mas que entre ellos se llamen “geeks”, para el son “nerds mejor vestidos”. se siente satisfecho con lo que sabe, y quizá lo único que le interesa saber es de donde bajar mas iconos para el Messenger.

Esta persona común y silvestre –si, de esas que andan sueltas por allí-, “implemento” u “organizo” su área, metiendo sus conocimientos de “informática" -a su modo-,  lo que antes se manejaba en papel, el lo movió a “archivos de Word y/o Excel”, hizo sus plantillas, toda la información que ocupaba “organizada”, la tiene en múltiples archivos de Excel “muy ordenadamente, separados por semana o mes” , cuando tiene que escribir un reporte, sabe que tiene una hoja base en Word, y solo hace “copy and paste” , y agrega una nueva hoja a su archivo de Word o modifica el existente; si algún día su jefe ocupa un reporte en graficas de los datos que maneja, puede crear una grafica en Excel o importarla a Word, o si ocupa unos nuevos cálculos, los puede hacer en unos 15 minutos usando las formulas de Excel. En otras palabras, el trabajo que realiza, a su forma de ver, esta organizado y tiene todo lo que ocupa, por mas que su jefe diga que el es ineficiente, el siente que tiene todo controlado, con sus macros y formulas, con sus hojas de Word, esta cómodo, ya que siente que no ocupa saber mas de las computadoras – solamente ocupa saber como ganar al maldito solitario y/o buscaminas, que siempre lo vence-,  es una persona que contantemente se actualiza en su profesión – la que sea-, va a cursos de actualización, y para no perder el ritmo fue a otro curso de ofimática, donde le enseñaron a usar la ultima versión del office.

Un día, llego lo llamo su jefe y le dijo que iban a “mejorar” su área, que habían contratado a una consultora que les haría un sistema, que mejoraría el proceso de la empresa y este conseguiría que se logre  ahorrar tiempos en el trabajo y tendrían un mayor control, de todo lo que pasa en la empresa, mientras su jefe decía todo esto, esta persona común y silvestre solo pensaba “pero yo tengo todo controlado, se que archivo de Excel tiene que información, se generar mis reportes, se hacer los cálculos, seguro andan pensando en reemplazarme por una maquina como esos robots de la TV, y me quedare sin trabajo” –aunque suena ilógico, hay quienes de verdad terminan pensando así-, y le presentan a ese ser extraño que “ mejorara los procesos y automatizara su trabajo”…

este ser extraño le hace muchas preguntas, lo interroga de todo  y el le cuenta aunque por dentro sigue pensando que será reemplazado por algún robot, y como se siente en “peligro” , siente que no debe decirle todo  o quizá simplemente de la pura presión, se le olvida hacerlo..; esa consultora cuenta un un “especialista en usabilidad y diseño  de interfaz”, que iba a hacer que sea “fácil de usar”.

y llega el día en que le enseñan el “nuevo sistema”, se le hace algo extraño, e totalmente diferente a su tan amado office, le parece un rectángulo con muchos botoncitos e iconos, allí no sabe donde están las cosas, por mas que le dan un curso de capacitación, se le hace complejo, además que si hacer algunos cálculos, no puede hacer sumas en las celdas de al lado “ por que no hay!”, y si ocupa nuevas cosas tiene que hacer un pedido, luego esperar unos días o semanas, ademas de que tiene algunos problemas que los seres raros llaman “bugs”, para el todo esto es muy pesado, el extraña su amado Excel y Word, donde si tenia un error de calculo, solo modificaba  y listo; y entonces llego un día, había una reunión y en esa el jefe le pidió de “ya” un reporte especial –con sus graficas y todo, ya que los jefes solo saben leer graficas- y “oh sorpresa” el reporte no existía en ese famoso sistema, llamo a los seres raros y ellos le dijeron que en unos 5 días estaría el reporte, luego de algunas discusiones, le dijeron que para el día siguiente, pero el los ocupaba de ya, así que agarro algunos datos de otro reporte, abrió su tan amado Excel copio los datos que ocupaba, y genero su grafica, todo esto en una 1 hora – mucho menos que lo que tardan los seres raros-, y de alli se colgó para comenzar a bombardear a ese sistema…, luego de un tiempo, el sistema dejo de ser usado, y el Volvió a su amado Excel.

2 - Amor al Word por toda la vida!

Otro Caso es de un Medico, que hacia los reportes de las consultas de su consultorio en "en Word”, tenia muchos muchos archivos, y un día fueron a ofrecerle un sistema, le costo una buena cantidad –le cobraron bien, pq es doctor y dicen k puede pagar- el lo pago, pensando que le ayudaría, e igual recibió un cuadrado, que no se parecía en nada a su Word, con muchos rectángulos donde le dijeron que metiera los datos, y donde tenia que escribir el diagnostico, no veía forma de resaltar los aspectos importantes, – negritas, subrayado, etc- luego de un tiempo, los seres extraños, hicieron unos botones para que pueda hacer eso, pero no era tan cómodo y simple como su amado Word, que por mas que le decía que tenia una copia pirata, aun le dejaba hacer las cosas como el quería, luego de un tiempo…. dejo el sistema y volvió a su tan amado Word..

Por que Sucedió esto?

así como estos casos hay miles y miles, de proyectos que terminaron en fracaso, y ojo, no me refiero necesariamente a los proyectos que están súper mal programados.. – eso es otro tema –, en muchos casos, es por que los usuarios son personas que no les interesa estar actualizados “tecnológicamente”, no saben, ni les interesa saber que existen cosas como silverligth, Ajax, WPF, etc. personas que tienen carreras no relacionadas con cosas de tecnología, mas que con cosas de ofimática, personas que están mas preocupados en actualizarse en cosas relacionadas con su carrera, que en cuestiones tecnológicas, están cómodos con su forma de trabajar con el Office y tienen gran resistencia al cambio, muchas veces son los causantes de “serruchar, grillar, o promover que un sistema deje de ser usado”  ya que comienzan a ver todos sus “problemas”, los cuales básicamente son “por que el office me hace esto y el sistema no?” , aunque parezca ilógico, hay sistema que fracasan por eso, por que esos usuarios comunes y silvestres, no se acostumbran a esa nueva interfaz, ya sea web, win , RIA, etc… por que simplemente no se acostumbran – y no le da la gana de acostumbrarse –, en  teoría lo usuarios deberían usar si o si el sistema, pero la realidad muestra que muchas veces, estos son saboteados por los mismos usuarios, o hacen a propósito el trabajo mas lento… y esto por que? 

ellos solo quieren usar el office y nada mas, para nuestra suerte desde hace un tiempo existe algo llamado

Visual Studio Tools for Office – VSTO

y que 3#$#$%#$%#  es eso? 

Son herramientas, que están en el Visual Studio –desde el VS 2005 con modo gráfico, ya que en 2003 era como un beta, muy limitado –, las cuales nos dejan desarrollar aplicaciones para office, y OJO, no me refiero a VBA, esto es totalmente diferente, ya que se pueden usar los lenguaje VB o C#, la programación es muy parecida a Windows Form, con la diferencia que en el ide del Vs en vez de ver un formulario, veremos una hoja de Excel, o de Word, –además de poder hacer add-in muy fácilmente-, pero que beneficios tenemos aparte de esto? :

  • Podemos aprovechar la funcionalidad existente del Office:  cuestiones como guardado, importación, exportación, graficas, corrector ortográfico, ya están incluidos, listo para usar por el cliente, sin que nosotros tendríamos que programar algo extra, aunque como es lógico,  mediante programación podemos usar y extender esas funcionalidades, esto nos ahorra mucho tiempo de programación ,de cosas repetitivas.
  • Interfaz Amigable para el usuario : Muchas veces la resistencia al cambio, del usuario es por que no se siente seguro con la aplicación, pero si le damos una aplicación que este dentro del office, de entrada el usuario se sentirá mas cómodo de usarlo, ya que sabe donde se encuentra mucha funcionalidad, y solo hay que indicarle que mas se le a agregado; con esto, la resistencia al cambio es mínimo o nulo.
  • El Usuario puede hacer Cambios sin ocupar llamar a soporte constantemente : ya que las demás celdas o funcionalidad, no quedan bloqueadas – por defecto-, si el usuario por ejemplo ocupara hacer un grafico X de los datos que le muestra el sistema, no ocuparía llamar a soporte, solo lo haría como ya sabe hacerlo, o igual si ocupa modificar un reporte – una suma, un calculo extra-, el usuario podría agregar los campos que ocupe, ya que sabe usar el Excel como tal sin ningún problema.
  • soporte para trabajar “Offline” – en casa – :  como el office ya de por si puede guardar datos, podemos configurar la aplicación, para poder trabajar datos, en modo offline – trabajo en casa les suena?- y ya cuando vuelve a la oficina, la aplicación  actualizaría la db y esto sin necesidad de instalar alguna db “imagen” en el cliente.
  • Soporta Lenguajes .NET : al estar dentro de .net, podemos usar los lenguajes de programación .net que usamos comúnmente, así que no habría que saber otro lenguaje de programación, lógicamente si cosas inherentes al VSTO – como trabaja- pero nos ahorramos el lenguaje.

los que mencione son algunas de las funciones, y las que a mi parecer son las mas destacables.

ahora si les cuento, hace unas 2 semanas, platicaba con un amigo y me dijo que por que no publicaba los borradores que tenia – post-  y bueno, digamos que me convenció, y los iré sacando, -en el orden de la cola en que están – , y  de los mas antiguos que tenia eran sobre VSTO,  así que sacare  varios POST, sobre como es el desarrollo para office,  el cual uso en mi trabajo y los usuarios que lo usan están muy satisfechos, intentare compartirles mis experiencias y tips de como programar allí, desde un “hola mundo” hasta aplicaciones mas avanzadas, y luego –quizá- si hay gente que le interese, hasta podría hacer un – o varios – webcast al respecto, lógicamente dependiendo del interés de la gente, según cálculos, enviare mínimo 1 por semana.. y si se me olvida, plz hágamelo recordar plz.

creo que sin querer me salió otro testamento – será posible que alguna vez envíe uno corto?? –, este fue la introducción, en el siguiente voy a mostrar ya de un modo técnico como trabaja el VSTO.

casi me olvido, lógicamente todo esto será con Visual Basic !

Salu2

Ddaz


Actualmente calificado con 5.0 por 1 personas

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Clases Abstractas vs Interfaces. ¿Cómo, Cuándo y Por Qué?

febrero 17, 2009 07:10 by sergio

Enviado por Johnatan Flores Carmona el 17 de febrero de 2009  

Saludos a todos, en esta nueva aportación quiero compartir con ustedes un tema que cuando se está iniciando en el aprendizaje de la programación orientada a objetos no se encuentra en ningún libro o bien, pocos instructores lo mencionan -debo admitir que cuando impartí la materia de Introducción a la Programación Orientada a Objetos en el Instituto Tecnológico de León ni siquiera lo mencioné- y me refiero a ¿Cuándo y por qué usar clases abstractas o interfaces?

El concepto de clases abstractas e interfaces puede ser un poco confuso para los principiantes en la programación orientada a objetos ya que una clase abstracta sin ninguna implementación se ve cómo una interface, sin embargo existen muchas diferencias y similitudes entre ellas.

¿Qué es una clase abstracta?

Una clase abstracta es una clase que no puede ser instanciada y que debe ser heredada. Una clase puede implementarse en su totalidad, pero lo más habitual es que se implemente parcialmente o no se implemente en absoluto, encapsulando funcionalidad común para clases heredadas. Para información más detallada, vea Clases abstractas.

¿Qué es una Interface?

Una interface describe un grupo de comportamientos relacionados que pueden pertenecer a cualquier clase o estructura. Las interfaces contienen las firmas de métodos, propiedades, eventos o indizadores. La implementación de los miembros se hace en la clase o la estructura que implementa la interfaz. Para información más detallada, vea Interfaces.

Diferencias y Similitudes

A continuación extraigo parte de una tabla del artículo Abstract Class versus Interface en la que se describen las diferencias y similitudes que existen entre las clases abstractas y las interfaces:

Característica

Interface

Clase abstracta

Herencia Múltiple

Una clase puede heredar tantas interfaces requiera.

Una clase sólo puede heredar una clase abstracta.

Implementación por defecto

Una interface no puede proporcionar ningún código de implementación, solo la firma.

Una clase abstracta puede proporcionar la implementación completa o parcial.

Modificadores de acceso

Una interface no puede tener modificadores de acceso, todas sus firmas son públicas.

Los miembros de una clase abstracta pueden tener modificadores de acceso.

Núcleo vs Periferia

Las interfaces son usadas para definir las habilidades periféricas de una clase. Un Humano y un Vehiculo pueden implementar una interface IMovible

Una clase abstracta define el núcleo de una clase y es usada para objetos del mismo tipo.

Campos y Constantes

No pueden ser definidas en una interface

Una clase abstracta puede contener campos y constantes.

Recomendaciones para el uso de clases abstractas vs interfaces

La opción de diseñar tu funcionalidad cómo una interface o cómo clase abstracta puede ser difícil en algunas ocasiones. Microsoft en su artículo Recommendations for Abstract Classes vs. Interfaces nos hace las siguientes recomendaciones que trataré de ejemplificar para mostrar las ventajas de seguirlas.

Múltiples Versiones

Si sabe de antemano que va a crear varias versiones del componente, cree una clase abstracta. Las clases abstractas proporcionan un medio fácil y sencillo para crear versiones de los componentes. Al actualiza la clase base, todas las clases heredadas se actualizan automáticamente con el cambio. Por el contrario, las interfaces no se pueden cambiar una vez creadas. Si necesita una nueva versión de una interfaz, deberá crear una totalmente nueva.

Ejemplo: Pensemos en el caso de crear el ABC de una base de datos que contiene la tabla Persona, y además dos especializaciones de esta llamadas Cliente y Empleado; también existe la regla de negocio que indica que no puede registrarse a una persona si no es registrada cómo cliente o cómo empleado.

Solución con Clases Abstractas: Se debería de crear una clase abstracta llamada Persona y que defina las propiedades comunes entre Empleado y Cliente así como los métodos que implementan los procesos de Alta, Baja, Cambio de la tabla Persona; adicional a esto se deben crear las clases Empleado y Cliente, ambas heredan de Persona. Cada una deberá definir las propiedades que los diferencian y sobrescribir los métodos Alta, Baja y Cambio de la clase padre, en la sobre escritura de los métodos, se tendrá que hacer una llamada al método base correspondiente y agregar la implementación para modificar la tabla correcta.

Solución con Interfaces: Se debería de crear una interface llamada IPersona y que defina las firmas de los procesos de Alta, Baja, Cambio; adicional a esto se deben crear las clases Empleado y Cliente, ambas que implementen la interface IPersona. Cada una deberá definir las propiedades y campos comunes tanto comunes como diferentes, ambas también deben codificar la implementación de los métodos Alta, Baja y Cambio que realizarán los procesos en la tabla Persona y en la tabla correspondiente.

Conclusión: Cómo se puede ver, utilizando clases abstractas se puede reutilizar mucho código al heredar los campos, propiedades y llamando a los métodos de la clase base; en cambio con interfaces tenemos que re-escribir los campos y propiedades comunes en todas las clases así cómo el código de los métodos.

Funcionalidad Común

Si la funcionalidad que está creando va a ser útil en una amplia gama de objetos diferentes, utilice una interfaz. Las clases abstractas deben utilizarse principalmente para objetos estrechamente relacionados, mientras que las interfaces son más adecuadas para proporcionar funcionalidad común a clases no relacionadas.   

Ejemplo: Se tiene el caso de querer implementar diferentes medios de transporte que existen y se han identificado el Autobus, Avión y Barco. ¿Cómo se implementaría con clases abstractas y cómo con interfaces?

Solución con Clases Abstractas: Se crearía una clase abstracta llamada Transporte que defina el método abstracto Transportar; Se crearán las clases Autobus, Avion y Barco, todas ellas heredarán de Transporte y deberán realizar la implementación del método abstracto.

Solución con Interfaces: Se debería de crear una interface llamada ITransporte que defina la firma del método Transportar; Se crearán las clases Autobus, Avion y Barco, todas ellas implementarán la interfaz ITransporte.

Conclusión: A simple vista se podría decir que ambas soluciones son iguales, ya que las dos le delegan la responsabilidad de implementar el método Transportar a las clases finales Autobus, Avion y Barco, pero la diferencia está en lo siguiente, ¡No existe herencia múltiple! Por lo tanto con la solución de clases abstractas estaremos desperdiciando una oportunidad de heredar de otra clase, pensemos en este caso, podríamos tener una clase padre llamada Avion y las clases hijas Avioneta, AvionComercial, etc., entonces hazte la siguiente pregunta ¿Avioneta y AvionComercial deberían heredar de Avion o de Transporte? En este caso claramente se ve que la mejor opción es utilizar interfaces.

Pequeña Funcionalidad

Si va a diseñar fragmentos pequeños y concisos de funcionalidad, utilice interfaces. Si va a diseñar unidades funcionales grandes, utilice una clase abstracta.

Conclusión: Esta recomendación va muy ligada a las dos anteriores, mientras más grande la funcionalidad es más recomendable la reutilización por lo que las clases abstractas son la mejor opción; con funcionalidad pequeña no es recomendable perder la oportunidad de heredar nuestra clase con una clase padre que tenga una funcionalidad grande para reutilizar sus propiedades y métodos por lo que la utilización de interfaces es nuestra mejor opción.

Funcionalidad común

Si desea proporcionar funcionalidad común e implementada en todas las implementaciones del componente, utilice una clase abstracta. Las clases abstractas permiten implementar parcialmente una clase, mientras que las interfaces no contienen ninguna implementación para ningún miembro.

Conclusión: Siempre que encuentres funcionalidad común entre dos o más clases, busca la manera de utilizar herencia para la reutilización de código (mientras menos escribas mejor).

Si deseas el código fuente utilizado para este discusión puedes descargarlo de:


Actualmente calificado con 4.2 por 5 personas

  • Currently 4,2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

‘Aplicaciones Dinámicas’ con .NET Reflection y su Rendimiento

febrero 11, 2009 06:38 by Admin

Enviado por Johnatan Flores Carmona el 19 de enero de 2009 

Saludos a todos, antes que nada quisiera comentar que felicito a los propietarios de este grupo así cómo a los usuarios por esta nueva etapa ahora en 'Live'. He sido miembro de este grupo desde ya algunos años y aunque mi participación ha sido casí nula me gustaria pensar "Año Nuevo, Grupo Nuevo, Actitud Nueva" así que para empezar con la nueva actitud, me gustaría compartir con ustedes algo que he tenido que a prender por las malas: El maravillos mundo de .NET Reflection........

Problema:

Actualmente en la institución donde laboro me asignaron a un proyecto que consiste en construir un ‘Bridge’ para que la aplicación ‘X’ pudiera comunicarse con la aplicación ‘Y’. Uno de los muchos requerimientos que solicitaron fue: ‘Actualmente debes conectar ‘X’ con ‘Y’, pero este bridge debe servir posteriormente para comunicar a ‘W’ con ‘Z’, ‘Y’ con ‘W’, etc. por lo que debe ser una aplicación que su funcionalidad deba ser configurable desde base de datos. ¿Cuál fue la solución a estos requerimientos?  R:= .NET Reflection. 

Solución con Reflection:

Implementaciones: Cada uno de las aplicaciones (W, X, Y, Z) tiene sus propias ‘reglas’ de comunicación, por lo que para comunicar XàY se requiere una ‘implementación’ diferente que para comunicar a WàZ y otra totalmente diferente para YàW.

Interfaz de implementación: Todas las implementaciones deberán exponer un método llamado ‘Ejecutar’ el cuál servirá para llevar a cabo los procesos necesarios para cada una de las implementaciones.

Fabrica de implementaciones: Se requiere un método que nos permita obtener la implementación correcta en base a los parámetros de entrada (posiblemente un ID o un nombre).

Diccionario de implementaciones: Requerimos un diccionario que nos permitirá conocer el nombre de la clase que deseamos utilizar para realizar la implementación correcta (en nuestro caso una base de datos o un archivo xml).

Prueba: El método Main que realiza la prueba (hipotetica) de esta solución sería de la siguiente manera:

    class TestRendimientoReflection

    {

        static void Main(string[] args)

        {

            

            //Codigo para medir el tiempo de ejecucion

            EjecutarTest(totalIteraciones);

        }

        static void EjecutarTest(int totalIteraciones)

        {

            Random generadorIdentificadores = new Random();

            for (int i = 0; i < totalIteraciones; i++)

            {

                int idClase = generadorIdentificadores.Next(1, 11);

                IImplementacion clase = FabricaImplementacion.CrearImplementacion(idClase);

                Console.WriteLine(clase.Ejecutar());

            }

        }

    }

Solución sin Reflection:

Implementaciones: (Igual que con Reflection)

Interfaz de implementación: (Igual que con Reflection)

Prueba: El método Main que realiza la prueba de esta solución (hipotetica) sería de la siguiente manera:

    class TestRendimientoSinReflection

    {

        static void Main(string[] args)

        {

            

            //Codigo para medir el tiempo de ejecucion 

            EjecutarTest(totalIteraciones);

        }

        static void EjecutarTest(int totalIteraciones)

        {

            Random generadorIdentificadores = new Random();

            for (int i = 0; i < totalIteraciones; i++)

            {

                int idClase = generadorIdentificadores.Next(1, 11);

                IImplementacion clase = null;

                switch (idClase)

                {

                    case 1:

                        clase = new Implementacion01();

                        break;

                    case 2:

                        clase = new Implementacion02();

                        break;

                    //Todos los case necesarios

                    default:

                        clase = new Implementacion10();

                        break;

                }

                Console.WriteLine(clase.Ejecutar());

            }

        }

    }

Rendimiento:

Cuando se me cuestionó sobre si la utilización de Reflection afectaría el rendimiento que podría tener la aplicación tuve que investigar sobre dicho tema y encontré la siguiente referencia: .Net Reflection and Performance

En este enlace menciona que los procesos de obtener y asignar valores a propiedades con reflection resultó de 2.5 a 3 veces más lento que hacerlo directamente; además de que la invocación de métodos fue 3.5 a 4 veces más lento con reflection que realizar una llamada directa al método.

Estos resultados claramente no son satisfactorios para una aplicación que posiblemente tendría que atender cientos o miles de peticiones, pero también no es nuestro caso la asignación o lectura de propiedades ni mucho menos la ejecución de métodos utilizando reflection. Los datos que necesitábamos conocer era el rendimiento al instanciar clases utilizando reflection.

A continuación los datos que fueron obtenidos:

Rendimiento de Reflection
  Prueba con Reflection Prueba sin Reflection
Total iteraciones 10,000 10,000
Total de Pruebas 20 20
Promedio (ms): 3,813.44 3,706.60
Media (ms): 3,793.24 3,592.44
Mediana (ms): 3,914.25 3,867.38

 Con estos datos se puede decir que el rendimiento de instanciar clases utilizando reflection es de 0.01 a 0.06 veces más lento que creando las instancias directamente. 

Beneficios:

A continuación mencionaré algunas métricas que son utilizadas en el desarrollo de software que están ligadas al código fuente y cómo el uso de Reflection podria ayudar a mejorarlas:

Mantenibilidad: Cómo se puede observar, ambos códigos (con Reflection y sin él) son fácilmente mantenibles ya que si existe un cambio en los procesos de una implementación, sólo tendríamos que modificar la clase correspondiente.

Complejidad Ciclomática: Esta métrica se ve mejorada al utilizar reflection ya que cómo podemos observar no necesitaremos la sentencia ‘switch / case’ para la creación de los objetos con las implementaciones deseadas.

Líneas de código: Las líneas de código también se ven reducidas considerablemente al hacer uso de Reflection.  }

Bajo acoplamiento: Debido a que la construcción se basa en un 'diccionario' de implementaciones, si se deseara que los procesos requeridos para comunicar X con Y ya no es la clase 'ImplementacionXY y en su lugar se utilizaría NuevaImplementacionXY; utilizando Reflection sólo se tendría que modificar el diccionario y no todas las porciones de código que hicieran referencia a esa clase (cómo sería con la instanciación directa). 

Conclusiones:

Utilizar .NET Reflection indiscriminadamente en nuestras aplicaciones hará que el rendimiento de ejecución sea bastante pobre; sin embargo, si se planea bien las arquitectura y las estrategias para utilizar .NET Reflection, el costo de utilizar esta poderosa API no es alto si se consideran los beneficios que se pueden obtener.

Si se desea conocer las buenas practicas de programación al utilizar reflection, pueden leer este excelente artículo: Dodge Common Performance Pitfalls to Craft Speedy Applications

Código Fuente:


Actualmente calificado con 5.0 por 1 personas

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Qué es ASP .NET Control Extenders?

febrero 11, 2009 06:29 by Admin
Aqui dejamos un aporte de la comunidad enviado a través de la seccion de Foro (foro.barreteros.net), este fue enviado por nuestro amigo Johnatan Flores Carmona [johnatan.jfk@gmail.com], el es un Desarrollador .NET de la ciudad de León Guanajuato, aquí dejo el aporte:
------------------------------------------------------------------------------------------
Saludos a todos de nuevo, espero que tengan un bonito día festivo. Y ya que yo tuve que venir a trabajar a pesar de que toda la empresa descansó, estoy aquí para compartir con ustedes otro tema que tuve que investigar hace un tiempo, espero les sea de utilidad. 

  

Qué es ASP .NET Control Extenders?

ASP .NET Control Extenders son controles que derivan de la clase base ExtenderControl (System.Web.UI) la cual puede ser usada para agregar funcionalidad adicional (usualmente soporte AJAX o JavaScript) a controles declarados dentro de una pagina. Esto habilita a los desarrolladores el encapsulamiento de comportamientos IU, y hacer muy fácil agregar funcionalidad a una aplicación web. Un ejemplo de esto es el ASP .NET AJAX Control Toolkit (1)

Según MSDN Library: "La clase ExtenderControl permite mediante programación agregar funcionalidad AJAX a un control de servidor ASP .NET. El ExtenderControl hereda desde la clase Control e implementa la interfaz IExtenderControl. La clase Control define las propiedades, métodos y eventos que son compartidos por todos los controles de servidor ASP .NET. La interfaz IExtenderControl es una clase abstracta la cual no puede ser instanciada directamente. En su lugar debes crear un tipo derivado." (2)

  

Pasos para crear un control extendido

  1. Crear clase abstracta base que hereda ExtenderControl
  2. Crear el archivo .js que implementará el comportamiento de IU (ECMAScript)
  3. Crear una clase que herede de la clase creada en 1 la cual será el extensor del control.
  4. Utilizar el control en una pagina .aspx

En las siguientes secciones se explicarán los pasos necesarios para crear un extensor de control que permite cambiar el estilo al control cuando el mouse pase encima de el.

  

Crear clase base que hereda de ExtenderControl

Cuando se crea una clase que herede de ExtenderControl se requiere que se implementen los métodos abstractos GetScriptDescriptor y GetScriptReferences.

public abstract class ExtenderControlBase : ExtenderControl
{
   protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
   {
      throw new NotImplementedException();
   }
   protected override IEnumerable<ScriptReference> GetScriptReferences()
   {
   throw new NotImplementedException();
   }
}
  • GetScriptDescriptor: Método usado para obtener una colección de descriptores script que representan los componentes cliente ECMAScript (JavaScript).
  • GetScriptReferences: Método usado para obtener una colección de objetos ScriptReference que definen los recursos script que el control requiere.

  

GetScriptDescriptors

Este método debe regresar una colección de objetos ScriptDescriptor que definen que propiedades serán pasadas a la representación del control en el lado del cliente.

protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
{
   ScriptControlDescriptor descriptor = new ScriptControlDescriptor(this.GetType     
                                          ().FullName, targetControl.ClientID);
   descriptor.AddProperty("id", this.ClientID);
   PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this);
   foreach (PropertyDescriptor property in properties)
   {
      ExtenderControlPropertyAttribute propertyAttribute =
            property.Attributes[typeof(ExtenderControlPropertyAttribute)] as
            ExtenderControlPropertyAttribute;
      if (propertyAttribute != null)
      {
          object value = property.GetValue(this);
          string name = (propertyAttribute.Name != null) ?
                            propertyAttribute.Name : property.Name;
      if (value != null)
             descriptor.AddProperty(name, value);
   }
   }
   yield return descriptor;
}

En el código anterior se crea el objeto que contendrá todas las propiedades que contendrá nuestro control; para ello se obtiene la colección de propiedades que contiene nuestra clase (la clase hija que se creará en el paso 2). Una vez obtenida la colección se recorrerán cada uno de los objetos contenidos y se agregan al descriptor con el método .AddProperty

  

GetScriptReferences

Este método regresará una colección de objetos ScriptReference para incluirlos en la pagina del lado del cliente.

protected override IEnumerable<ScriptReference> GetScriptReferences()
{
   object[] scriptReferences = Attribute.GetCustomAttribute(
   this.GetType(), typeof(ScriptReferenceAttribute), false);
   foreach (ScriptReferenceAttribute sra in scriptReferences)
       yield return sra.GetScriptReference();
}

  

Crear el archivo ECMAScript

Este archivo es el que contiene todo el código (JavaScript) que controla los comportamientos que tendrá el control extendido. A continuación se presenta el bloque de código base que debe tener este archivo.

Type.registerNamespace("CustomAjaxControlKit");
CustomAjaxControlKit.MouseOverExtender = function(element){
   CustomAjaxControlKit.MouseOverExtender.initializeBase(this,[element]);
};
CustomAjaxControlKit.MouseOverExtender.prototype = {
   initialize: function(){
      CustomAjaxControlKit.MouseOverExtender.callBaseMethod(this, "initialize");
   },
   dispose: function(){
      CustomAjaxControlKit.MouseOverExtender.callBaseMethod(this, "dispose");
   }
};
CustomAjaxControlKit.MouseOverExtender.registerClass  
      ("CustomAjaxControlKit.MouseOverExtender", Sys.UI.Behavior);
Sys.Application.notifyScriptLoaded();

El código anterior debe modificarse para que se vea cómo el código siguiente:

Type.registerNamespace("CustomAjaxControlKit");
CustomAjaxControlKit.MouseOverExtender = function(element){
   CustomAjaxControlKit.MouseOverExtender.initializeBase(this, [element]);
   this._MouseOverCssClass = null;
   this._MouseOutCssClass = null;
   this._mouseOverHandler = Function.createDelegate(this, this._onMouseOver);
   this._mouseOutHandler = Function.createDelegate(this, this._onMouseOut);
};
CustomAjaxControlKit.MouseOverExtender.prototype = {
   initialize: function(){
      CustomAjaxControlKit.MouseOverExtender.callBaseMethod(this, "initialize");
      var targetElement = this.get_element();
      $addHandler(targetElement, "mouseover", this._mouseOverHandler);
      $addHandler(targetElement, "mouseout", this._mouseOutHandler);
},
   dispose: function(){
      var targetElement = this.get_element();
      $removeHandler(targetElement, "mouseover", this._mouseOverHandler);
      $removeHandler(targetElement, "mouseout", this._mouseOutHandler);
      CustomAjaxControlKit.MouseOverExtender.callBaseMethod(this, "dispose");
   },
   get_MouseOverCssClass: function(){
      return this._MouseOverCssClass;
   },
   set_MouseOverCssClass: function(value){
      this._MouseOverCssClass = value;
   },
   get_MouseOutCssClass: function(){
      return this._MouseOutCssClass;
   },
   set_MouseOutCssClass: function(value){
      this._MouseOutCssClass = value;
   },
   _onMouseOver: function(eventArgs){
      var targetElement = this.get_element();
      if(targetElement != null)
         targetElement.className = this.get_MouseOverCssClass();
   },
   _onMouseOut: function(eventArgs){
      var targetElement = this.get_element();
      if(targetElement != null)
         targetElement.className = this.get_MouseOutCssClass();
   }
};
CustomAjaxControlKit.MouseOverExtender.registerClass     
                     ("CustomAjaxControlKit.MouseOverExtender", Sys.UI.Behavior);
Sys.Application.notifyScriptLoaded();

  

Crear la clase que será el extensor del control

Debido a que se creó una clase abstracta base que hereda de la clase ExtenderControl (véase el paso 1), la creación de nuestra clase que será el extensor de control simplemente debe agregar la WebReference del archivo ECMAScript, heredar la clase ExtenderControlBase y agregar las declaraciones de las propiedades que tendrá nuestro extensor de control.

A continuación se muestra el código de nuestra clase:

[assembly: WebResource("CustomAjaxControlKit.MouseOver.MouseOverBehavior.js",
                                                         "text/javascript")]
namespace CustomAjaxControlKit
{
   [TargetControlType(typeof(Control)), ScriptReference(
        "CustomAjaxControlKit.MouseOver.MouseOverBehavior.js", CustomAjaxControlKit")]
   public class MouseOverExtender : ExtenderControlBase
   {
      [ExtenderControlProperty]
      public string MouseOverCssClass { get; set; }
      [ExtenderControlProperty]
      public string MouseOutCssClass { get; set; }
   }
}

  

Utilizar el extensor de control en una pagina .aspx

Para poder utilizar nuestro extensor de control en una pagina .aspx tenemos que primero agregar la referencia al dll que contiene el código de nuestro extensor. Una vez realizado esto se debe incluir la directiva @Register para poder incluir en la pagina los tags de nuestro control: 

<%@ Register Assembly="CustomAjaxControlKit" Namespace="CustomAjaxControlKit" TagPrefix="cack" %>
Por último debemos agregar el control que sufrirá los efectos de nuestro extensor y a continuación declarar nuestro control:
<asp:Label runat="server" ID="Label1" Text="Texto prueba" />
<cack:MouseOverExtender ID="MouseOverExtender1" runat="server" TargetControlID="Label1"  MouseOutCssClass="MouseOutStyle"
                       MouseOverCssClass="MouseOverStyle" />

  

Ejemplo: Codigo Fuente

Si deseas ver el código fuente completo de este control puedes descrgarlo en el siguiente link:

  

Referencias

  1. ScottGu; Using ASP .NET AJAX Control Extenders in VS 2008; http://weblogs.asp.net/scottgu/archive/2007/08/19/using-asp-net-ajax-control-extenders-in-vs-2008.aspx
  2. MSDN Library; About ExtenderControl Class; http://msdn.microsoft.com/en-us/library/system.web.ui.extendercontrol.aspx

Sea el primero en calificar este post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5