domingo, 8 de octubre de 2017

Inversión de Control IoC e Inyección de Dependencias DI

Principio de Inversión de Dependencias DIP 

DIP (Dependency Inversion Principle), se trata de una estrategia utilizada por la ingeniería del software, basada en los principios del manifiesto SOLID de ingeniería. Esta estrategia tiene como objetivo obtener la mejor eficiencia del software. Por ejemplo, la estrategia evita que los módulos de alto nivel, no dependan de los de bajo nivel y que por el contrario, dependan de las abstracciones. Ello quiere decir que, a través de este proceso, se logra reducir el factor de acomplamiento. En esencia, esta es la característica fundamental que justifica la estrategia del Control de Inversión IoC  y de la Inyección de Dependencias DI. 

Factor de Acoplamiento 

La construcción del software basado en el paradigma Orientado a Objetos, generalmente hace uso de los procesos que brinda la herencia y la implementación de interfaces. En efecto, gracias a este proceso, podemos construir software escalable y robusto. Sin embargo, existe un punto crítico al que debemos considerar. Este punto es el factor de acomplamiento. El factor no es más que la estrategia mecánica de acomplar clases e interfaces entre sí. Si este proceso tiende a ser muy diversificado y masivo, el factor nos arrojará una tasa elevada de acomplamiento y en consecuencia, podría condicionar los procesos de la mantenebilidad del software. 

Además, el contexto podría tender a ser complejo. Es cuando se acuña el término de factor "alto-acomplamiento" o altamente acomplado, en inglés Strongly-Coupled. Por tanto, cuando reducimos esta tasa de acoplamiento, estaremos haciendo la estretegia contraria, que es "bajo-acomplamiento" o débilmente acoplada que en inglés, se la conoce con el término de Weakly-Coupled. 

En consecuencia, resulta muy importante considerar estos puntos clave. Para mejorar estos aspectos y optimizarlos, podremos utilizar las estrategias que proponen IoC y DI, de manera de poder hacer eficiente la construcción de nuestro software. 

Inversión de Control IoC 

IoC (Inversion on Control) o Inversión de Control se trata de una estrategia de programación que básicamente controla el flujo del programa. El paradigma que plantea, resulta ser yuxtapuesto con respecto al proceso convencional que poseen los desarrolladores y programadores, que desde un principio, plantean todo el aspecto del flujo del programa. 

Inyección de Dependencias DI

DI (Dependency Injection) o Inyección de Dependencias se trata nada menos que de un patrón de diseño y cuyo gran objetivo final, es el de construir software con los factores mínimos de acomplamientos. El proceso hace uso de una técnica de "inyección" hacia los módulos en juego. Ello quiere decir que cuando se construyen las dependencias sobre una clase y se las proporciona, el proceso de inclusión, se realiza de modo similar a un proceso de inyectado. 

Para poder comprender mejor estos conceptos, vamos hacer uso de código en el lenguaje de C#, basado en clases a modo de ejemplo. No obstante, esta estrategia puede ser aplicada perfectamente en cualquier lenguaje orientado a objetos. 

public class Clientes
{
       public int Id { get; set; }
       public String Razon { getset; }
       public String Direccion { getset; }
       public String Telefono { getset; }
       public String Email { getset; }
}

Aquí hemos creado una clase de tipo Entidad de Datos llamada Clientes, a los efectos gestionar los datos en las subsiguientes clases, las que en esencia, nos permitirán demostrar los procesos DIP. 

public class NoDIP 
{
    private Clientes cliente;

    public NoDIP(
        int id, String razon, String direccion,
        String telefono, String email
    ) {
            cliente = new Clientes() {
            Id =id,
            Razon =razon,
            Direccion =direccion,
            Telefono =telefono,
            Email =email
        };
        Console.WriteLine("Datos del Cliente:");
        Console.WriteLine("Id: {0}", cliente.Id);
        Console.WriteLine("Razón: {0}", cliente.Razon);
        Console.WriteLine("Dirección: {0}", cliente.Direccion);
        Console.WriteLine("Teléfono: {0}", cliente.Telefono);
        Console.WriteLine("Email: {0}", cliente.Email);
    }
}

Esta clase no hace uso de la Inyección de Dependencias. Si observamos bien, podremos apreciar que la clase Clientes, es creada como campo dentro de la clase NoDIP. Luego, a través de los parámetros de su constructor, se pasan los datos del cliente mediante argumentos. El proceso siguiente, es pasar estos datos desde estos argumentos a la clase Clientes misma, usando su propio constructor dinamicamente. Finalmente, los datos, son pasados a los procesos de escritura de la consola, de modo de que más tarde, se muestren en pantalla. 

public class SiDIP
{
    public SiDIP(Clientes cliente) {
        Console.WriteLine("Datos del Cliente:");
        Console.WriteLine("Id: {0}", cliente.Id);
        Console.WriteLine("Razón: {0}", cliente.Razon);
        Console.WriteLine("Dirección: {0}", cliente.Direccion);
        Console.WriteLine("Teléfono: {0}", cliente.Telefono);
        Console.WriteLine("Email: {0}", cliente.Email);
    }
}

En esta clase hacemos de la Inyección de Dependencias. Si apreciamos el código, podremos ver que aquí simplemente a través del constructor de la clase SiDIP, pasamos como argumentos, la clase Clientes como constructor. Luego, los datos son pasados directamente a los procesos de la consola para que posteriormente, sean impresos en pantalla. Aquí se nota claramente la gran diferencia. Observemos que existe menos dependencia de la clase Clientes que en el anterior caso. 

Para poder probar nuestro ejemplo, simplemente creamos el siguiente código. 

class Program
{
    static void Main(string[] args)
    {

        NoDIP nodip = new DIP.NoDIP(
            1, "ALITEL SA", "Av Sperantus 123"
            "989-1234-5678", "info@alitelsa.com");

        Console.WriteLine("");

        SiDIP sidip = new DIP.SiDIP(
            new Clientes() {
                Id = 2, 
                Razon = "TERNARIUS SA"
                Direccion = "Av Saint Lorenze 234"
                Telefono = "989-9876-4532"
                Email = "info@ternarius.com"
            });

        Console.Read();
    }

La Resultante es la siguiente: 

Datos del Cliente:
Id: 1
Razón: ALITEL SA
Dirección: Av Sperantus 123
Teléfono: 989-1234-5678
Email: info@alitelsa.com

Datos del Cliente:
Id: 2
Razón: TERNARIUS SA
Dirección: Av Saint Lorenze 234
Teléfono: 989-9876-4532
Email: info@ternarius.com

Conclusiones 

Como hemos visto en este artículo, el factor de acomplamiento resulta ser bastante interesante para el desarrollo del software. Sus ventajas son bastantes amplias y aquí, tan solo he citado una de ellas. Tenemos que considerar que esta estrategia también se puede aplicar a las interfaces e incluso, tanto a métodos como a las propiedades. El uso racional y enfocado en este contexto, nos permitirá desarrolla software más eficiente y lo más importante de todo, de fácil mantenebilidad sin olvidar la escalabilidad.  

Hasta pronto. 


sábado, 2 de septiembre de 2017

¿Cuál es la diferencia entre los Comparadores Estrictos y No Estrictos en JavaScript?

Aclarando Dudas en JavaScript 

¿Cuál es la diferencia entre los Comparadores Estrictos y No Estrictos en JavaScript?
Esta pregunta suele ser muy frecuente entre mis alumnos en JavaScript. Sin embargo, también la he visto realizarce en varios foros. Al parecer, crea bastante confusión y más aún en aquellos desarrolladores novatos y algunos programadores olvidadizos. Bueno, vayamos al grano. 

Se puede decir a modo groso que un Comparador Estricto realiza una comparación de Tipos de Datos mientras que un Comparador No Estricto lo hace en función a los valores. Recordemos que en el lenguaje de JavaScript, se basa en un paradigma Orientado a Objetos y fundamentado en el Protitpado de Objetos. También, se trata de un lenguaje débilmente tipado. Por tanto, este lenguaje incorpora tipos de comparaciones conocidos con los términos de Falsly y Truthly. Analicémos unos ejemplos sencillos para comprender mejor.


Comparación No Estricta
1 == "1"           // Esto es verdadero - true 
'' == 0              // Esto es verdadero - true 
false == 0       // Esto es verdadero - true

Comparación Estricta
1 === "1"         // Esto es falso - false 
'' === 0            // Esto es falso - false 
false === 0     // Esto es falso - false

Un contraste de comparaciones entre palabras clave:
null == undefined          // Esto es verdadero - true 
null === undefined        // Esto es falso - false

Explicación

En el ejemplo de las comparaciones No Estrictas, podremos observar que lo que se está comparando son efectivamente "valores". Por tanto, el valor de 1, tomándolo simplemente como un valor, es igual al 1 que se encuentra contenido dentro de la cadena "1". Quizá aquí lo desconcertante es el comportamiento de '' == 0. Esto se debe a la regla Falsly que considera al 0, false y "" o '' (cadena vacía) como equivalentes entre si. Por tanto, en el proceso de comparación No Estricta, su resultante es igual a true "verdadero". Así mismo sucede con false == 0. 

Sin embargo, en el caso de comparaciones Estrictas, observamos que sucede el caso inverso. La regla utilizada por las comparaciones Estrictas es Truthly. La regla Truthly fuerza a un proceso de comparación de tipos. Ello quiere decir que su proceso de comparación es más específico basándose en el tipo de datos. Por tanto, si comparamos 1 === "1" la resultante es false debido a que un número no puede ser igual una cadena. Ambos son diferentes tipos de datos. 

Bueno, espero haber dejado en claro este menudo dilema y haber sido de utilidad. 
Hasta pronto.
- Ariel.

martes, 11 de julio de 2017

Diferencias entre Un Algoritmo de Ordenado Estable e Inestable

Diferencias entre Un Algoritmo de Ordenado Estable e Inestable 

Artículo - Entrevista a Javin Paul - Developer Java Code Geeks 

Recientemente en una de mis entrevistas, después de algunas de las preguntas que me hicieron acerca de los algoritmos de ordenado. Preguntas tales como cómo escribir algoritmos como QuickSort u otros diferentes entre QuickSort y MergeSort. Además, también en esa entrevista, una persona me preguntó la diferencia entre la estabilidad e inestabilidad de los algoritmos de ordenado. Estas preguntas fueron nuevas para mi lectura y le dije a él. Disculpa, nunca oí hablar de eso. La historia termina cuando el entrevistador hizo otras preguntas, como mucha de las de ustedes suelen hacerme. Haciendo una lectura de esto, hallé menos respuestas que preguntas y ultimamente, más cuando él me preguntó qué significaba la estabilidad e inestabilidad de un algoritmo de ordenado. En consecuencia, he decidido responder a esta pregunta clave a través de este artículo. 
Un algoritmo de ordenado se dice que es estable si este mantiene un orden relativo de números de registros en caso de ser iguales. O sea, si tu necesitas ordenar la serie 1 2 3..., luego si no cambias el orden de estos primeros dos números el algoritmo será estable, pero si tu intercambias a ellos luego pasarán a ser inestables, sobre todo a pesar del resultado u ordenamiento del mismo ordenado. 
Estas diferencias son más que obvias cuando tu ordenas objetos. O sea, el ordenamiento de pares clave valor. En el caso de un algoritmo estable, el orden original del par clave valor es retenido como se muestra en el siguiente ejemplo. 
Actualmente, el entrevistador me preguntó seguido a ello que no me olvide de mencionar los conceptos acerca de QuickSort versus MergeSort. Una de las principales diferencias entre QuickSort y MergeSort es que formalmente QuickSort es inestable aunque MergSort es un algoritmo de ordenamiento estable. 

Algoritmos Estables vs Inestables

Supongamos que tienes un ordenado basado en par claves valor en un orden incremental clave como: 

INPUT: (4, 5), (3, 2) (4, 3) (5, 4) (6, 4) 

Ahora, existen dos posibilidades para solucionar estos pares donde la clave es la misma, es decir (4, 5) y (4, 3) como se muestra a continuación: 

OUTPUT1: (3, 2),  (4, 5),  (4, 3),  (5, 4),  (6, 4)

OUTPUT2: (3, 2),  (4, 3),  (4, 5),  (5, 4),  (6, 4)

El ordenamiento del algoritmo que se produce en la primera salida debería saber cómo estabilizar al algoritmo de ordenamiento dado que el orden original de las claves iguales serán mantenidas, esto lo podrás ver con (4, 5) seguido anteriormente por (4, 3). 
En otra pasada, el algoritmo que produce la segunda salida será como un algoritmo de ordenamiento inestable dado que el orden de los objetos con la misma clave no es mantenida en el orden de forma ordenada. Podrás observar que en la segunda salida, el par (4, 3) es seguido anteriormente por (4, 5). 
Ahora, la gran pregunta es ¿cuáles son ejemplos de algoritmos de ordenamientos estables e inestables? La respuesta es entonces dividiéndolos a todos en algoritmos de ordenamiento bien conocidos dentro de ordenados y desordenados. Algunos ejemplos de algoritmos estables son Merge, Sort, Insertion Sort "Ordenamiento de Inserción", Bubble Sort "Ordenamiento Burbúja" y Tree Binary "Árbol Binario". Mientras que QuickSort, Heap Sort "Ordenamiento de Apilado" y Selection Sort "Ordenamiento por Selección", son algoritmos de ordenamiento inestables. 
Si tu recuerdas el método de ordenamiento de Collections.sort() de la plataforma Java Collection, este utiliza una interacción del método Merge Sort que es un algoritmo estable. Esto va más allá de las comparaciones de NLog(N) para el caso de entradas de matrices o vectores que cuentan con un proceso previo de ordenamiento parcializado. 
Si verdaderamente estás interesado acerca de estos temas, te sugiero que leas un buen libro sobre estructuras de datos y de algoritmos. Existe un autor que ha escrito un libro llamado "Introduction to Algorithms" por Thomas H. Cormen (disponible en inglés). Este libro está disponible en Amazón. Haz clic aquí si estás interesado Introduction to Algorithms.
En la siguiente figura de ejemplo se cuenta con mil palabras, en esta imagen podremos detallar cómo operan los procesos de estabilidad e inestabilidad del ordenado. 

Todo esto trata acerca de las diferencias entre algoritmos de ordenamiento estables e inestables. Recuerda, que si el ordenamiento original de claves o números iguales es mantenido en el ordenamiento saliente, luego el algortimo sabrá cómo ordenarlo. Algunos ejemplos comunes de algoritmos de ordeamiento estables son Merge Sort, Insertion Sort y el clásico Bubble Sort. 

Artículo Javin Paul - Blog de Java Code Geeks
https://www.javacodegeeks.com/2017/06/difference-stable-unstable-sorting-algorithm.html.
Traducido por Ariel Alejandro Wagner.
Muchas gracias por leer. ¡Hasta la próxima entrega!

martes, 2 de mayo de 2017

Estrategias de la Arquitectura del Software

Estrategias de la Arquitectura del Software

El proceso de construcción y desarrollo del software demanda una serie de estrategias específicas. Estas estrategias se pueden entender como algo más que buenas prácticas. Se trata en breve de una serie de reglas fuertemente basadas en la experiencia. A modo groso, una estrategia podría consistir en escribir código robusto, escueto y potente. Entre otras cosas, hacer énfasis en las repitencias de procesos, etc. Las estrategias pueden ser prácticamente infinitas. A continuación, describiremos algunas de ellas para poder conocer bien de cerca algunas de sus virtudes.

Estrategia DRY

La estrategia DRY (Don’t Repeat Yourself) “No Repitas las Cosas”, en breve se trata de una estrategia que nos ayuda a evitar la repitencia de código. El eje fundamental de esta estrategia es la de crear un código único para su uso y por supuesto, la gran posibilidad de reutilizarlo cuando sea oportuno. Dicho de modo gracioso, es una suerte de “guerra contra el copy & paste”. 

Un buen ejemplo de ello son el uso de las clases. Usted crea una librería más o menos elaborada, la que debe cumplir un rol específico en su código. Una mala práctica sería que su código, se repita y se desperdigue por todo el contexto de su aplicación. En lugar de ello, a través de su clase creada, usted acude a la reutilización evitando la repitencia mediante las técnicas de herencias o instancias de clases. En breve, su clase es escrita por única vez y luego consumida por el resto de los diversos módulos de la aplicación.

Estrategia SRP

La estrategia SRP (Simple Responsibility Principle) “Principio de Responsabilidad Simple”, hace énfasis en las responsabilidades de los módulos intervinientes en un contexto de una aplicación. La idea de fondo es crear una responsabilidad única para cada módulo. Un uso colectivo de dichos procesos tienden a desnaturalizar las responsabilidades. Ello quiere decir que el destino de un proceso, no queda muy claro en el contexto de las operaciones. Existe una suerte de difusión de procesos o una multiplicidad de responsabilidades que desnaturalizan la interpretación de los procesos.

Un buen ejemplo de ello es la construcción de una librería que contribuye a resolver un código de barras. Mientras que esta librería es utilizada para cumplir el rol destinado, se cumple la regla. La regla dejará de tener efecto cuando esta librería se la utilice para realizar una tarea que difiere de su origen. Imagine que esta librería se utilizara para generar un código aleatorio para otro destino que no sea el código de barra. Si bien podría ser una solución interesante, de fondo rompe la regla SRP. Por tanto, este tipo de prácticas deben ser evitadas en lo posible si pretendemos ser coherentes con los estándares, la arquitectura y las buenas prácticas.

Estrategia OCP

La estrategia OCP (Open Closed Principle) “Principio Abierto Cerrado”, se basa en el proceso de evitar las modificaciones y aceptar las extensibilidades. La idea de fondo es hacer énfasis fuertemente en la extensión de los desarrollos y evitar los cambios originales. Pongamos un ejemplo para que se pueda comprender mejor.

Durante la fase de desarrollo de librerías de clases en una aplicación, se debe considerar varios factores. Por empezar, las clases primarias deben ser genéricas o muy básicas para luego, a medida de que se vayan extendiendo, se vayan especificando. Sin embargo, el desarrollo de esta escalabilidad, demanda evitar cambios en los procesos originales. El desarrollo de esta estrategia, debería considerar que las bases del proceso de escala, no deben cambiar dado que los cambios, podrían crear un efecto avalancha sobre las extensibilidades, convirtiéndolo en inestable y poco seguro. Por tanto, un buen diseño que prevee la extensibilidad, debe plantearse muy seriamente este proceso primordial para evitar malas prácticas y romper la regla OCP.

Estrategia LSP

La estrategia LSP (Liskov Substitution Principle) “Principio de Substitución de Liskov”, hace énfasis en los subtipos puesto que cada clase que hereda de otra, puede usarse como su base, sin la necesidad de conocer sus diferencias entre estas. Veamos un ejemplo para comprender mejor.

Un ejemplo lo podemos encontrar en el uso de las interfaces donde son implementadas en una clase hija y que luego, dentro del contexto de la misma, se pueden sobrescribir para que cumplan su rol destinado específico, sin tener que alterar las interfaces primarias.

Estrategia IOC

La estrategia IOC (Inversion Of Control) “Inversión de Control”, se trata de un proceso de inversión del flujo de control con respecto y en comparación con el proceso de programación procedural. También es conocido con el término convencional de “Delegando Responsabilidades”. Se puede entender rápidamente como que una parte de la programación procedural que utiliza o consume otra parte del código que se encuentra dentro del control del proceso.

Un ejemplo muy cercano a estos procesos son los Framework. En el caso de los desarrolladores de Framework .NET, contamos con varias soluciones que hacen uso intensivo de estos procesos y que gestionan los ciclos de vida. Por ejemplo, en el caso de los formularios de Windows “WinForms”, el uso de eventos que gestionan los procesos en el contexto de los formularios o el modelo MVC, cuando son orientados a los servicios o páginas Webs, donde a través de los helpers de MVC, se obtienen diversos procesos autogestionados.

Estrategia DIP

La estrategia DIP (Dependency Injection Principle) “Principio de Inyección de Dependencias” o DI (Dependency Injection) “Inyección de Dependencias”, a modo groso podemos decir que se encarga de “inyectar” componentes a las clases que tenemos implementadas.

Las clases son dependientes del proceso para poder funcionar correctamente. El proceso no permitirá que nuestras clases creen las condiciones para cumplir sus roles sino que serán proporcionadas desde otras clases contenendoras, obviamente pertenecientes al mismo Framework de inyección de dependencias. Estas inyectarán la implementación deseada en nuestro contrato, es decir en nuestras clases, sin la necesidad de requerir de los procesos de la palabra clave new, que dicho del paso, es utilizada para crear instancias de objetos de clases.

Para concluir, no confundir DIP o DI con IOC. Si bien los procesos pueden en algunas ocasiones aparentar ser similares, existe una diferencia de fondo muy importante. La confusión que surgen entre ambos radica en el contexto de uso para algunas soluciones, que aparentan realizar operaciones similares aunque ambas estrategias, resultan ser totalmente diferentes.

Estrategia COC

La estrategia COC (Convention Over Configuration) “Convención Sobre Configuración”, se centra en el proceso de diseño y consiste en la declaración de una serie de convenciones que permiten asumir el proceso de configuración de un sistema por defecto.

Estrategia ISP

La estrategia ISP (Interface Segregation Principle) “Principio de Segregación de Interface”, se puede comprender muy fácilmente cuando una clase A que tiene una dependencia con la clase B, no debería depender de los métodos de la clase B que no vaya a usar nunca. En breve, los diversos recursos de una clase, no deben depender si o si de tener que ser utilizados pese a no utilizarlos en otros propósitos. Esto podría verse muy a menudo en aquellos casos donde se hace un uso abusivo de clases abstractas, aquellas que deben implementar si o si todos sus recursos y peor aún, que terminen por depender de todos ellos. Esto en consecuencia, rompería la regla de ISP.

Resumen

Las diversas estrategias permiten desarrollar y crear software de altas prestaciones, normalizado, escalable, sólido y seguro. Las diversas estrategias que plantean la mayoría de los Framework, resultan ser muy convenientes porque presentan muchísimas ventajas. Cuando se construye el software, el factor de coherencia más la debida aplicación de las estrategias, nos conducirán por las buenas prácticas más aún, a contribuir a desarrollar sistemas robustos. La gran base de todo esto es en esencia la de satisfacer los principios de la Ingeniería del Software. Por ejemplo, cuando se hace uso de los patrones como el MVC (Model View Controller) “Modelo Vista Controlador”, estamos proporcionando un modo deserrallo y constructivo del software que facilita la escala, lo convierte en ágil y máxime aún, permite que los desarrollos y diseños resulten ser mucho más fluídos y eficaces.

Por tanto y para ir cerrando estos conceptos, resulta primordial considerar todos estos análisis estratégicos, si deseamos obtener los mejores resultados. Siguiendo esta línea coherentemente, los resultados que obtendremos serán extraordinarios. 


martes, 25 de abril de 2017

Las Doce Reglas de las Bases de Datos

El diseño de las bases de datos tradicionalmente se sujeta a una serie de reglas que permiten su diseño y construcción de forma eficiente. Estas reglas son conocidas como “Las 12 Reglas de las Bases de Datos”. Estas reglas fueron propuestas por el mismo creador del lenguaje SQL (Structure Query Language), el Dr. Edgar Frank Codd. Resulta conveniente rápidamente repasar estas reglas, de modo que para nuestra aplicación, apliquemos estas recomendaciones. En futuros proyectos, usted podrá diseñar eficientemente tipos de bases de datos.

Las 12 Reglas Codd

Las reglas también se las conoce como “Las 12 Reglas Codd”. A continuación, detallamos de forma abstracta las reglas. Este pormenorizado, es una extracción de Wikipedia. 

Regla 0: Cualquier sistema que se proclame como relacional, debe ser capaz de gestionar sus bases de datos enteramente mediante sus capacidades relacionales.
Regla 1: La regla de la información, toda la información en la base de datos es representada unidireccionalmente, por valores en posiciones de las columnas dentro de filas de tablas. Toda la información en una base de datos relacional se representa explícitamente en el nivel Lógico exactamente de una manera con valores en tablas.
Regla 2: La regla del acceso garantizado, todos los datos deben ser accesibles sin ambigüedad. Esta regla es esencialmente una nueva exposición del requisito fundamental para las llaves primarias. Dice que cada valor escalar individual en la base de datos debe ser lógicamente direccionable especificando el nombre de la tabla, la columna que lo contiene y la llave primaria.
Regla 3: Tratamiento sistemático de valores nulos, el sistema de gestión de base de datos debe permitir que haya campos nulos. Debe tener una representación de la "información que falta y de la información inaplicable" que es sistemática, distinto de todos los valores regulares.
Regla 4: Catálogo dinámico en línea basado en el modelo relacional, el sistema debe soportar un catálogo en línea, el catálogo relacional debe ser accesible a los usuarios autorizados. Es decir, los usuarios autorizados deben poder tener acceso a la estructura de la base de datos (catálogo).
Regla 5: La regla comprensiva del sublenguaje de los datos, el sistema debe soportar por lo menos un lenguaje relacional que:
  • ·         Tenga una sintaxis lineal.
  • ·         Puede ser utilizado de manera interactiva.
  • ·         Soporte operaciones de definición de datos, operaciones de manipulación de datos (actualización así como la recuperación), seguridad e integridad y operaciones de administración de transacciones.

Regla 6: Regla de actualización, todas las vistas que son teóricamente actualizables deben ser actualizables por el sistema.
Regla 7: Alto nivel de inserción, actualización y borrado, permitiendo el sistema realizar manipulación de datos de alto nivel, es decir, sobre conjuntos de tuplas. Esto significa que los datos no solo se pueden recuperar de una base de datos relacional de filas múltiples y/o de tablas múltiples, sino también pueden realizarse inserciones, actualización y borrados sobre varias tuplas y/o tablas al mismo tiempo (no sólo sobre registros individuales).
Regla 8: Independencia física de los datos, los programas de aplicación y actividades del terminal permanecen inalterados a nivel lógico cuando quiera que se realicen cambios en las representaciones de almacenamiento o métodos de acceso.
Regla 9: Independencia lógica de los datos, los cambios al nivel lógico (tablas, columnas, filas, etc.) no deben requerir un cambio a una solicitud basada en la estructura. La independencia de datos lógica es más difícil de lograr que la independencia física de datos.
Regla 10: Independencia de la integridad, las limitaciones de la integridad se deben especificar por separado de los programas de la aplicación y se almacenan en la base de datos. Debe ser posible cambiar esas limitaciones sin afectar innecesariamente las aplicaciones existentes.
Regla 11: Independencia de la distribución, la distribución de las porciones de la base de datos a las varias localizaciones debe ser invisible a los usuarios de la base de datos. Los usos existentes deben continuar funcionando con éxito:
  • ·         Cuando una versión distribuida del SGBD se introdujo por primera vez
  • ·         Cuando se distribuyen los datos existentes se redistribuyen en todo el sistema.


Regla 12: La regla del orden, si el sistema proporciona una interfaz de bajo nivel de registro, aparte de una interfaz relacional, que esa interfaz de bajo nivel no se pueda utilizar para subvertir el sistema, por ejemplo: sin pasar por seguridad relacional o limitación de integridad. Esto es debido a que existen sistemas anteriormente no relacionales que añadieron una interfaz relacional, pero con la interfaz nativa existe la posibilidad de trabajar no relacionalmente.

viernes, 17 de marzo de 2017

Patrones en MVC en PHP

Framework

El lenguaje PHP se trata de un lenguaje de comandos del servidor cuyas características permiten la inclusión de diversos patrones basados en el modelo clásico MVC (Model View Controller) o Modelo-Vista-Controlador. Puesto que el lenguaje PHP tiene posibilidades de ser flexible y ampliable, durante los últimos años, se han ido incorporando una serie de patrones y ampliaciones para facilitar el desarrollo de aplicaciones Web. Estas nuevas inclusiones le permiten a los desarrolladores optar por diversos escenarios de desarrollos más sólidos y flexibles que contribuyen en mejoras tales como desarrollos rápidos, facilidades de manutención, bajos factores de acoplamiento, bajos costes, entre otras características.

MVC (Model View Controller)

Antes de explorar los Framework de PHP, es necesario entender que es el modelo MVC. El modelo MVC se trata de un estándar para el desarrollo de software de aplicaciones Web. El estándar cubre una serie de requerimientos fundamentales, tales como escala, bajos acoplamientos, modularidad, etc. Este modelo se divide en tres grandes áreas operativas. Véase la figura 1.



Figura 1 – Modelo Vista Control MVC

Modelo

El área llamada Modelo se trata de una sección donde se encuentra la capa de negocio y la interacción con las bases de datos. La capa de negocio proporciona muchas alternativas para el desarrollo interactivo entre las bases de datos y el modelo. Si bien en este curso hemos visto la interoperación entre PHP y MySQL, esta interoperatividad que propone el modelo permite el uso de otros gestores de bases de datos, tales como Oracle, SQLite, etc. Lo importante es comprender que el Modelo garantiza la interoperación entre la capa de negocio y el gestor de base de datos.
Si observa la figura 1, en la sección de Modelo, puede ver que se hace mención de consultas “Querys”, encapsulación, solicitudes y respuestas incluso el estado entre otras cualidades. En efecto, la capa de negocio permite construir estas negociaciones. Una consulta que es peticionada  por la sección de Vista hacia la capa de negocio, establece un punto de petición de datos. Según las características de la petición el negocio, se establece la interacción con el gestor de base de datos y los datos, que más tarde, son manipulados de modo tal que el Modelo pueda devolverlos a las otras secciones de MVC, en este caso sobre el área de Vistas. Todos estos pasos serán orquestados por la sección de Control.

Vista

La sección Vista está relacionada directamente con la interfaz gráfica del usuario. La interfaz proporciona al usuario un punto de interacción con la aplicación. Por otra parte, a su vez, la sección Vista produce un punto de interacción con la sección del Modelo. Lo interesante de la sección Vista, es el factor de acoplamiento que existe entre la Vista y el Modelo que permite, entre otras cosas, la modularidad entre distintos tipos de interfaces. Por ejemplo, el uso de pantallas con objetos CGI, celulares, el uso de Applets de Java, módulos de plugins tales como Flash o Silverlight, etc., que enriquecen las interfaces gráficas y cuyos usos no alteran las otras secciones Modelo y Control.
En efecto, Ud., puede optar por varias de estas tecnologías sin que estas mismas alteren al Modelo. Además, se dice que es de alta convergencia puesto que Ud., podría considerar ambientes diversos de tecnologías gráficas sin alterar las características del Modelo y producir una alta convergencia para cada uno de los casos con la sección del Modelo. Por ejemplo, la interfaz gráfica de un celular y la de su pc. Ambas son totalmente distintas. Sin embargo, por ejemplo, ambas pueden realizar la misma funcionalidad y es la de accesar recursos de una base de datos.

Controlador

La sección de Control cumple la función de gestionar el comportamiento de las interacciones que surgen entre las secciones de Vista y del Modelo. A rasgos generales, la sección de Control mapea todas las actividades que ejecuta el usuario y la forma en cómo las secciones Vista-Modelo interactuarán entre sí. Todo el proceso de peticiones y de respuestas deben ser gestionadas de modo que la información pueda manipularse correctamente para cada etapa del modelo. La sección de Control dirige estos procesos y mantiene en sincronía las tareas que estos demandan al sistema. 

El Porqué del Uso de Patrones MVC

El uso de patrones tiene mucha relevancia en varias áreas para el desarrollo. Por empezar, el desarrollo deja de ser un trabajo continuo, incluso aglutinado y pasa a ser un modelo más racional porque le permite colocar el proyecto y dividirlo entre tres áreas operativas. Al contar con áreas separadas, se facilitan varios factores de desarrollo, escala y manutención, etc.
Además, el patrón le permite que un equipo de desarrollo pueda dividir las tareas y cargar con responsabilidades separadas para acelerar los procesos de desarrollo. Esto beneficia al proyecto puesto que cada uno se aboca a su respectiva área, enfocándose en las áreas de forma eficiente en un lapso de tiempo paralelo durante el desarrollo de dicho proyecto.

Tipos de Framework

En la actualidad, existen una serie infinita de Framework, de hecho, mientras estoy escribiendo esto, están surgiendo cada vez más, nuevos patrones modelo. Esta diversidad permite al desarrollador optar por varias opciones y ajustarse a las necesidades que cada uno de estos proponen.
A continuación cito alguno de ellos o, al menos, los más importantes y conocidos en el mercado para el lenguaje PHP y ellos son los siguientes:

  • Achievo ATK - http://www.achievo.org/atk
  • Akelos Framework - http://www.akelos.org/
  • AModules3 - http://adevel.com/amodules3
  • Ambivalence - http://amb.sourceforge.net/
  • Aukyla PHP Framework - http://www.auton.nl/software/en/doxygen/index.html
  • Binarycloud - http://www.binarycloud.com/
  • Biscuit - http://ripcord.co.nz/biscuit/
  • Bitweaver - http://www.bitweaver.org/
  • Booby - http://www.nauta.be/booby
  • CakePHP - http://www.cakephp.org/
  • Castor - http://castor.2le.net/
  • Cgiapp - http://cgiapp.sourceforge.net/
  • CodeIgniter - http://codeigniter.com/
  • Copix - http://copix.aston.fr/
  • Core Enterprise PHP - http://sourceforge.net/projects/cep
  • FastFrame - http://www.codejanitor.com/
  • Fusebox - http://www.fusebox.org/
  • FuseLogic - http://www.haltebis.com/index/wakka/main/FuseLogic
  • Konstrukt - http://konstrukt.dk/
  • Kumbia - http://kumbia.sf.net/
  • Krysalis - http://www.interakt.ro/products/Krysalis/index.php
  • Inek - http://wiki.opensourcebox.de/index.php/Inek_Framework
  • InterJinn - http://www.interjinn.com/
  • Ismo - http://ismo.sourceforge.net/
  • Medusa - http://medusa.tigris.org/
  • Nexista - http://www.nexista.org/
  • P4A - http://p4a.crealabsfoundation.org/
  • PHP on Trax - http://phpontrax.com/
  • PHPulse - http://www.phpulse.com/
  • PhpMVC - http://www.phpmvc.net/
  • Popoon - http://www.bitflux.ch/developer/cms/popoon.html
  • Prado - http://www.xisc.com/
  • Qcodo - http://www.qcodo.com/
  • Rwfphp - http://www.rwfphp.org/
  • Seagull - http://seagull.phpkitchen.com/
  • Sitellite - http://www.sitellite.org/
  • SolarPHP - http://www.solarphp.com/
  • sQeletor - http://www.proyectofindecarrera.com/
  • Studs - http://www.mojavelinux.com/projects/studs/
  • struts4php - http://www.struts4php.org/
  • symfony - http://www.symfony-project.com/
  • TaniPHP - http://www.taniphp.org/
  • Tigermouse - http://tigermouse.sf.net/
  • web.framework - http://www.webframework.org/
  • Wolfden CMF - http://www.framework.wolfden.com.ua/
  • YII - http://www.yiiframework.com/
  • Zephyr Framework - http://zephyr-php.sourceforge.net/
  • Zoop Framewor - http://www.zoopframework.com/

Elección de un Framework Adecuado

Ante una diversidad muy amplia que ofrece el mercado del software, a veces resulta bastante difícil determinar cuál es el más apropiado y proceder con su elección. Cada Framework tiene sus pros y sus contras. De hecho, analizar cada uno de ellos en particular, podría resultar en una tarea bastante compleja y entiendo que tendría poco sentido ajustarlo a nuestro curso. Esto para nada significa que no se tengan en cuenta estas cuestiones en particular. Sin embargo, el debate que creo que no deja de ser más que interesante, pero por otro lado, escaparía totalmente a los objetivos de este curso.
En este curso conoceremos el Framework YII y veremos también CodeIgnitor de modo de que abarquemos dos Framework que, a mi modesto juicio, encierran características adecuadas para el curso que está haciendo.

Analizando un Caso Simple con MVC en PHP

El siguiente ejemplo se trata de un sencillo modo de enlistar artículos en un blog. Ver figura 1.

<php?
// Conexión a la base de datos.
$cn = mysql_connect('localhost''usuario''clave');
mysql_select_db('db'$cn);

// Consulta SQL para traer los artículos.
$resultado=mysql_query('SELECT fecha, titulo FROM articulo'$cn);
?>
<h1>Listado de Articulos:</h1>
<table>
     <tr><th>Fecha</th><th>Titulo</th></tr>
<php?
     // Recorre el resultado pintando la fecha y titulo.
     while ($fila = mysql_fetch_array($resultado, MYSQL_ASSOC))
     {
        echo "";
        echo " ".$fila ['fecha'] ." ";
        echo " ".$fila ['titulo'] ." ";
        echo "";
     }
?>
</table>
<php?
// Cerramos la conexión.
mysql_close($cn);
?>
Figura 1 – Código para Enlistar Artículos en un Blog

Si observa el código detenidamente podrá notar que en el mismo archivo fuente, se encuentran todas las funcionalidades juntas para la aplicación. Esta forma de desarrollar en el lenguaje PHP puede ser muy a menudo frecuente, pero encierra muchas desventajas. Por empezar, Ud., tiene todo el código en un archivo. Esto dificulta la manutención del mismo porque, si tuviera que realizar algún cambio o una actualización, inevitablemente, tendrá que modificar el único archivo fuente. También, cada parte vital del programa depende de ese archivo fuente y, por tanto, dificulta su interpretación.
En el ejemplo que tenemos, vemos que el código es más o menos sencillo, pero puede que se encuentre con soluciones más complejas y, en ese caso, las dificultades irán en aumento. En breve, cuanto más código se deba desarrollar, mayor será el grado de dificultades tanto en interpretación como en manutención, entre otras características.

Refactoreo de la Solución Usando un Patrón MVC

Para normalizar el programa fuente del citado ejemplo, hemos de incluir el modelo de patrón MVC cómo alternativa para una solución más racional y eficiente. Por empezar, tomaremos el código y lo dividiremos en tres áreas perfectamente especificadas. Cada una de estas cumplirá la función de proveer los recursos necesarios para mejorar la solución y obtener una aplicación adecuada al estándar propuesto.

Fase Controlador

En la siguiente sección se describe el sector que se encargará de gestionar el comportamiento de esta aplicación. Ver figura 2.

require('modelo.php');

$articulos = getArticulos();

require('vista.php');
Figura 2 – Fase de Control – control.php

Fase Vista

En la siguiente fase se describe el código para las vistas en la pantalla de interfaz del usuario y cómo este verá e interactuará con dicha vista. Ver figura 3.

<h1>Listado de Artículos</h1>
<table>
     <thead>
       <tr><th>Fecha</th><th>Titulot</th></tr>
     </thead>
     <tbody>
       <php? foreach($articulos as $articulo): ?>
       <tr>
          <td><php? echo $articulo ['fecha'?></td>
          <td><php? echo $articulo ['titulo'?></td>
       <tr>
       <php? endforeach?>
     </tbody>
</table>
Figura 3 – Fase de Vista – vista.php

Fase Modelo

En la siguiente fase se crea las negociaciones más adecuadas para establecer un punto de contacto entre la base de datos y la aplicación. Ver figura 4.

<php?
function getArticulos() {
    $cn = mysql_connect('localhost''usuario''clave');
    mysql_select_db('db'$cn);

    $resultado = mysql_query(
              'SELECT fecha, titulo FROM articulo'$cn);
    $articulos array();

    while($articulo = mysql_fetch_assoc($resultado)) {
        $articulos[] = $articulo;
    }

    mysql_close();
}
?>
Figura 4 – Fase de Modelo – modelo.php

Refactorizando el Área de Modelo

En la fase de Modelo hemos construido el código con la consulta para establecer el negocio con la base de datos. Esto es válido y muy útil, sin embargo, se puede plantear un refactoreo más. Podría dividir esta etapa en dos secciones.  Una sección la llamaremos Capa Abstracta y la otra sección la llamaremos Capa de Acceso de Datos. A continuación, muestro los dos códigos respectivos. Véase la figura 5 y 6 respectivamente.


function crearConexion($servidor$usuario$clave){
  return mysql_connect($servidor$usuario$clave);
}

function cerrarConexion($cn){
  mysql_close($cn);
}

function consulta($consulta$base_datos$cn){
  mysql_select_db($base_datos$cn);

  return mysql_query($consulta$cn);
}

function getResultado($resultado$tipo = MYSQL_ASSOC){
  return mysql_fetch_array($resultado$tipo);
}
?>
Figura 5 – Abstracción de Datos - abstrac.php


function getTodosLosArticulos(){

  $cn = crearConexion('localhost''usuario''clave');
  $resultado = consulta(
        'SELECT fecha, titulo FROM articulo''db'$cn);
  $articulos array();
  while ($articulo = getResultado($resultado)){
     $articulos[]  = $articulo;
  }
  cerrarConexion($cn);
  return $articulos;
}
?>
Figura 6 – Acceso a Datos – access.php
Esta separación entre estas dos capas tiene muchas ventajas significativas. Una de ellas por ejemplo es la reutilidad, es decir, que esta porción del código podría estar disponible para otras aplicaciones que requieran de recursos similares para establecer una negociación similar a la expuesta. Esto ahorra cierta cantidad de código cuando se desarrolla o amplía su aplicación. Otro factor relevante es que podría resultar fácil la adaptación para un posible uso para otros gestores de bases de datos que demandan otras clases de tipos de librerías para el acceso y manipulación de datos. Entre otras características y una de las más importantes es que esta forma de particionar el código facilite enormemente su manutención.


Desarrollado y redactado por Wagner, Ariel Alejandro
Job Systems Solutions