Propuesta de Estándar de desarrollo o codificación (Tercera Entrega) #programacion

Características de un buen programa

  • Ejecución correcta: funciona de acuerdo a las especificaciones.
  • Ejecución eficiente: uso mínimo de recursos de tiempo y memoria.
  • Fácil de leer y comprender.
  • Fácil de depurar.
  • Fácil de mantener.
  • Interfaz de usuario independiente de las funciones de cálculo.

Árbol de proyectos

 

 

 

 

 

 

 

 

Propuesta de Estándar de desarrollo o codificación (Segunda Entrega) #programacion

Las técnicas de codificación están divididas en tres secciones:

  • Nombrado
  • Documentación Interna (Comentarios)
  • Formato

Nombrado

El esquema de nombres es una de las ayudas más importantes para entender el flujo lógico de una aplicación. Un nombre debe más bien expresar el “qué” que el “cómo”. Si se utiliza un nombre que evite referirse a la implementación se estará conservando la abstracción de la estructura ya que la implementación está sujeta a cambios, de esta manera se describe que hace la estructura y no como lo hace.

Por ejemplo es más claro nombrar un procedimiento de acceso a datos SeleccionarRegistro() que RealizarConsultaSelect(), porque lo que importa es que se supone que hace el método y no como lo hace.

Otra directiva es la de utilizar nombres tan largos como para que se entiendan pero a la vez tan cortos como para que no den información irrelevante.

Estructuras (namespaces, procedimientos, clases, interfaces y propiedades)

  • Los nombres de todas las estructuras de código deben estar en el mismo idioma.
  • Los namespaces deben empezar por el nombre de la compañía seguido del proyecto y la capa:

Namespace Ejemplo.Contabilidad

Namespace Ejemplo.Contabilidad.Core

  • El nombre del ensamblado y el namespace root deben ser idénticos.
  • Evite el uso de nombre completamente cualificado
  • El nombre de la clase y el archivo fuente deben ser iguales.
  • En la POO es redundante incluir nombres de clases en el nombre de las propiedades de clases, como por ejemplo Rectángulo.RectánguloArea, en su lugar, utilice Rectángulo.Area, pues el nombre de la clase ya contiene dicha información.
  • Utilice la técnica verbo-sustantivo para nombrar procedimientos que ejecuten alguna operación en un determinado objeto, como por ejemplo BuscarEmpleados().
  • Empiece los nombres de clase y propiedades con un nombre, por ejemplo CuentaBancaria, la primera letra de cada palabra debe ser mayúscula.
  • (PASCAL  para tipos, métodos y constantes)

Public Class SomeClass

Const DefaultSize As Integer = 100

Public Sub SomeMethod()

End Sub

End Class

  • Empiece los nombres de interfaz con el prefijo “I”, seguido de un nombre o una frase nominal, como IComponente, o con un adjetivo que describa el comportamiento de la interfaz, como IPersistible.
  • Evite colocar valores explícitamente a los enum.
  • Evite usar una función como parámetro en una condición. Asigne el valor a una variable local.
  • No use cadenas de texto en hardcode para presentar información a usuarios. Use archivos de recurso.
  • Nunca use cadenas de configuración de la aplicación en hardcode. Use archivos de configuración.
  • Cuando construya cadenas de texto largas use StringBuilder No string
  • Todos los recursos deben ser referenciados por ruta relativa.

Variables

  • Las variables miembro se escriben con la primera letra de cada palabra en mayúscula a excepción de las variable miembro privadas. Las Variables internas o de bloque deben ir en minúscula. En el caso de las variablesmiembro privadas, se debe utilizar el prefijo “m_” sumado al nombre de la variable (m_variable).
  • Es recomendado que las variable booleanas contengan una palabra que describa su estado: puedeEliminarse, esGrande, tieneHijos, etc. Y siempre se debe referir al estado verdadero: tieneCredito en cambio de noTieneCredito
  • Incluso para el caso de una variable de poco uso, que deba aparecer sólo en unas cuantas líneas de código, emplee un nombre descriptivo. Utilice nombres de variables de una sola letra, como i o j sólo para índices (ciclos for).
  • No utilice números o cadenas literales, como por ejemplo For i = 1 To 7. En su lugar, emplee constantes con nombre, del tipo For i = 1 To Enumeracion.length para que resulten fáciles de mantener y comprender.

(Use el prefijo (m_)  y continúe con PASCAL para los miembros privados)

Private Sub MyMethod(ByVal someNumber As Integer)

Dim number As Integer

End Sub

Parámetros

Los parámetros siguen el mismo estándar de las variables

Tablas

  • Cuando ponga nombres a tablas, hágalo en singular. Por ejemplo, use Empleado en lugar de Empleados.
  • Cuando ponga nombre a las columnas de las tablas, no repita el nombre de la tabla; por ejemplo, evite un campo llamado FacturaFecha de una tabla llamada Factura.
  • No incorpore el tipo de datos en el nombre de una columna.

Microsoft SQL Server

  • No ponga prefijos sp_ a los procedimientos almacenados, ya que se trata de un prefijo reservado para la identificación de procedimientos almacenados de sistemas.  Use USP_.
  • No ponga prefijos fn_ a las funciones definidas por el usuario, ya que se trata de un prefijo reservado para funciones integradas.  Use UFN_
  • No ponga prefijos xp_ a los procedimientos almacenados extendidos, ya que se trata de un prefijo reservado para la identificación de procedimientos almacenados extendidos.
  • Los nombres de los campos deben empezar por Mayúscula.
  • Evite colocar lógica en los procedimientos almacenados. ASP.Net y Web Services
  • Evite colocar código directo en la pagina use el archivo de código oculto.
  • El código oculto debe llamar a un componente que es que tiene la lógica de negocio.
  • Siempre verifique que las session variables no están en null antes de tener acceso a ellas.
  • Almacene las session variables en SQL Server.
  • Habilite Smart Navigation en las paginas ASP.Net.
  • Envuelva las session Variables en una propiedades.

Comentarios

Uno de los problemas de la documentación de software interna es garantizar que se mantengan y actualicen los comentarios al mismo tiempo que el código fuente. Aunque unos buenos comentarios en el código fuente no tienen ningún valor en el tiempo de ejecución, resultan valiosísimos para un programador que tenga que mantener una parte de software particularmente compleja.

  • Al principio de cada rutina, resulta útil hacer comentarios estándar, repetitivos, que indiquen el propósito de la rutina, las suposiciones y las limitaciones. Un comentario repetitivo podría consistir en una breve introducción que explicara por qué existe y qué puede hacer.
  • Evite añadir comentarios al final de una línea de código.
  • Evite los comentarios recargados, como las líneas enteras de asteriscos. En su lugar, utilice espacios para separar los comentarios y el código.
  • Antes de la implementación, quite todos los comentarios temporales o innecesarios, para evitar cualquier confusión en la futura fase de mantenimiento.
  • Use frases completas cuando escriba comentarios. Los comentarios deben aclarar el código, no añadirle ambigüedad.
  • Vaya comentando al mismo tiempo que programa.
  • Evite comentarios superfluos o inapropiados, como comentarios divertidos al margen.
  • Use los comentarios para explicar el propósito del código. No los use como si fueran traducciones literales.
  • Haga siempre comentarios al depurar errores y solucionar problemas de codificación, especialmente cuando trabaje en equipo.
  • Haga comentarios en el código que esté formado por bucles o bifurcaciones lógicas. Se trata en estos casos de áreas clave que ayudarán a los lectores del código fuente.
  • Separe los comentarios de sus delimitadores mediante espacios.
  • Cada declaración de variable importante debe incluir un comentario en la misma línea que describa el uso de la variable que se declara.

Formato

El formato hace que la organización lógica del código sea más clara. Si toma el tiempo de comprobar que el código fuente posee un formato coherente y lógico, les resultará de gran utilidad a usted y a otros programadores que tengan que descifrarlo.

Siga las siguientes pautas para establecer el formato:

  • Evite albergar múltiples clases en un solo archivo.
  • Establezca un tamaño estándar de sangría (por ejemplo, cuatro espacios o una tabulación) y úselo siempre. Alinee las secciones de código mediante la sangría predeterminada.
  • Declare una sola variable por línea.
  • Agregue los namespaces en orden descendente empezando por los del sistema y terminado por los personalizados o de usuario.
  • Una clase debe estar definida en orden descendente de la siguiente manera: Variables Miembro, Constructores, Enumeraciones, Estructuras o Clases anidadas, Propiedades y por último los Métodos.
  • Utilice espacios antes y después de los operadores siempre que eso no altere la sangría aplicada al código: numero = 3; en vez de numero=3
  • Use espacios en blanco para organizar a su antojo secciones de código. De tal manera que se comprenda la segmentación del código. En casos donde lo amerite utilice regiones.
  • Cuando tenga que dividir una línea en varias, aclare que el código sigue en la línea de más abajo mediante un operador de concatenación colocado al final de cada línea, y no al principio.
  • Siempre que sea posible, no coloque más de una instrucción por línea, a excepción de los bucles.
  • Al escribir en HTML, establezca un formato estándar para las etiquetas y los atributos; como por ejemplo, las etiquetas siempre en mayúscula y los atributos en minúscula
  • Cuando escriba instrucciones SQL utilice mayúsculas para las palabras clave: SELECT, UPDATE, WHERE, FROM, etc.
  • Coloque las cláusulas SQL principales en líneas separadas, de modo que las instrucciones sean más fáciles de leer y editar.
  • Siempre utilice los tipos nativos de cada lenguaje y no los del CTS.
  • No compare strings con  “” use string.empty.
  • Evite comparar variables booleanas contra false o true.

 

if(puedeEliminarse=true)

Mejor use

If(puedeEliminarse)

 

Adicionales

  • Use programas para el control de Código Fuente.
  • Nunca declare una sentencia catch vacía.
  • Evite anidar bloques try/catch.
  • Ordene la captura de excepciones (catch) siempre en orden descendente desde la más particular hasta la más genérica.
  • Siempre que sea posible prefiera la validación al manejo de excepciones

Propuesta de Estándar de desarrollo o codificación (Primera Entrega) #programacion

Que es un Estándar de Codificación

Un estándar de codificación completo comprende todos los aspectos de la generación de código. Si bien los programadores deben implementar un estándar de forma prudente, éste debe tender siempre a lo práctico. Un código fuente completo debe reflejar un estilo armonioso, como si un único programador hubiera escrito todo el código de una sola vez. Al comenzar un proyecto de software, es necesario establecer un estándar de codificación para asegurarse de que todos los programadores del proyecto trabajen de forma coordinada. Cuando el proyecto de software incorpore código fuente previo, o bien cuando realice el mantenimiento de un sistema de software creado anteriormente, el estándar de codificación debería establecer cómo operar con la base de código existente.

La legibilidad del código fuente repercute directamente en lo bien que un programador comprende un sistema de software. La mantenibilidad del código es la facilidad con que el sistema de software puede modificarse para añadirle nuevas características, modificar las ya existentes, depurar errores, o mejorar el rendimiento. Aunque la legibilidad y la mantenibilidad son el resultado de muchos factores, una faceta del desarrollo de software en la que todos los programadores influyen especialmente es en la técnica de codificación. El mejor método para asegurarse de que un equipo de programadores mantenga un código de calidad es establecer un estándar de codificación sobre el que se efectuarán luego revisiones del código de rutinas.

Las técnicas de codificación incorporan muchos aspectos del desarrollo del software. Aunque generalmente no afectan a la funcionalidad de la aplicación, sí contribuyen a una mejor compresión del código fuente. En esta fase se tienen en cuenta todos los tipos de código fuente, incluidos los lenguajes de programación, de marcado o de consulta.

En general una técnica de codificación no pretende formar un conjunto inflexible de estándares de codificación. Más bien intenta servir de guía en el desarrollo de un estándar de codificación para un proyecto de software.

Generales

  • Para conservar recursos sea muy selectivo en la elección del tipo de dato, asegúrese que el tamaño de una variable no sea excesivamente grande. Por ejemplo en los ciclos for es mejor, en la mayoría de las veces utilizar un tipo de dato tipo short que int.
  • Mantenga el tiempo de vida de las variables tan corto como sea posible, esto es muy importante por ejemplo cuando se utiliza un recurso finito como una conexión a una Base de Datos.
  • Mantenga el scope de las variables tan corto como sea posible, esto sirve para evitar confusiones, mejorar la mantenibilidad y además minimiza la dependencia, es decir si por algún motivo se comete el error de borrar una variable es más fácil de encontrar el error si esta tiene un scope más pequeño.
  • Use los procedimientos y variables con un solo propósito. Evite crear procedimientos multipropósito que lleven a cabo una variedad de funciones no relacionadas.
  • Dentro de una clase, evite el uso de variables públicas, en cambio utilice procedimientos y propiedades que accedan a dichas variables (privadas), así provee una capa de encapsulación y brinda la posibilidad de validar valores de cambio sobre las mismas, antes de manipularlas directamente.
  • Cuando se trabaje en un entorno web distribuido (aldea web), tenga cuidado de almacenar información en variables de sesión ASP ya que el estado de sesión es almacenado siempre en una sola maquina, considere mejor almacenar dicha información en una base de datos.
  • No abra conexiones a datos usando credenciales específicas de usuario, ya que estas no podrán ser reutilizadas por el pool de conexiones.
  • Evite el uso de conversión de tipos o casting ya que esto puede generar resultados imprevistos, sobre todo cuando dos variable están involucradas en una sentencia, utilice el cast solo en situaciones triviales, cuando este no sea el caso asegure de comentar la razón por la cual lo hizo.
  • Use siempre rutinas de manejo de excepciones
  • Sea especifico cuando declare objetos que puedan generar colisión, por ejemplo si tiene dos métodos con el mismo nombre en diferentes namespaces escríbalos con el nombre completo incluyendo el del paquete.
  • Evite el uso de variables en el ámbito de aplicación (web).
  • Use siempre sentencias Select-Case en lugar de utilizar sentencias ifthen repetitivas.
  • Siempre que sea posible utilice polimorfismo en vez de cláusulas Select.

 

Patrón de Arquitectura por Capas. Componentes presentes en la Capa de Lógica de Negocios

Diseño de componentes de negocio

Los componentes empresariales pueden ser la raíz de las transacciones atómicas. Éstos implementan las reglas de negocio, y aceptan y devuelven estructuras de datos simples o complejos. Los componentes de negocio deben exponer funcionalidad de modo que sea independiente de los repositorios de datos y los servicios necesarios para realizar la tarea, y se deben componer de forma coherente desde el punto de vista del significado y transaccional.

Normalmente, la lógica de negocio evoluciona y aumenta, proporcionando funcionalidad y operaciones de mayor nivel que encapsulan la lógica preexistente. Si el proceso de negocio invoca a otros en el contexto de una transacción atómica, todos los procesos llamados deben garantizar que sus operaciones participan en la transacción existente de modo que las operaciones se deshagan en caso de que la lógica de negocio que realiza las llamadas se interrumpa. Si no puede implementar transacciones atómicas, se necesitará ofrecer procesos de compensación.

Algunas responsabilidades de los componentes de negocio incluyen:

  • Dependiendo de la arquitectura, permitir ser llamados desde las interfaces de servicio, flujos de negocio u otros componentes de negocio.
  • Validar entradas y salidas.
  • Exponer operaciones de compensación.
  • Dependiendo del diseño, realizar llamados a los componentes de la capa de acceso a datos, para obtener o actualizar los datos de la aplicación, o llamar servicios externos.
  • Llamar flujos de negocio u otros componentes de negocio

La siguiente figura muestra la interacción de un componente de negocios con los demás componentes de la arquitectura:

Diseño de flujos de negocio

Cuando los procesos empresariales requieren varios pasos o transacciones de ejecución larga, es necesario administrar el flujo de trabajo, controlando el estado de la conversación e intercambio de mensajes con diversos servicios según sea necesario. En la siguiente figura se muestra la interacción de un proceso orquestado de negocios, con las interfaces de servicios, los agentes de servicios y los componentes de negocios

 

Diseño de interfaces de servicio

En el caso que se desee exponer la funcionalidad de negocios como un servicio (siendo lo mas recomendado por permitir que el sistema desde su inicio sea integrable con otros), es necesario proporcionar un punto de entrada desacoplado de la implementación interna. Asimismo, puede que también necesite exponer funcionalidad similar a clientes diferentes con requisitos de autenticación, logging, transacciones o contratos de nivel de servicio (SLA) distintos.

Puede proporcionar un punto de entrada al servicio creando una interfaz de servicios. Una interfaz de servicios es una entidad de software implementada normalmente como una fachada que controla los servicios de mapeo y transformación para permitir la comunicación con un servicio y aplica un proceso y una política de comunicación.

Una interfaz de servicios expone métodos, a los que se puede llamar de forma individual o en una secuencia específica para formar una conversación que implemente una tarea de negocios. Se recomienda, que el mecanismo de comunicación con la interfaz de servicio implemente una conversación basada en mensajes (ej. SOAP o MSMQ), en lugar de una basada en RPC (DCOM). De esta manera se logra un desacople con los clientes. Se debe tener en cuenta a la hora de definir estos protocolos, los requerimientos de interoperabilidad con otras plataformas, la seguridad y sincronía de la comunicación. Los requisitos de formato de comunicación, esquema de datos, seguridad y proceso necesarios se determinan como parte de un contrato publicado por el servicio.

Este contrato proporciona la información que necesitan los clientes para localizar y comunicarse con la interfaz de servicios. La siguiente figura muestra como es visto un servicio en un entorno empresarial

Las siguientes son las principales responsabilidades de una interfaz de servicios:

  • Exponer la lógica de negocios a la capa de presentación, o servicios externos
  • Servir como raíz de las transacciones atómicas que envuelven las operaciones de negocio.
  • Servir como punto de captura y registro (logging) por defecto de cualquier excepción que haya surgido durante el llamado a los demás componentes de la cada de negocios y acceso a datos.
  • Implementar los controles de seguridad requeridos por las llamadas (autenticación, autorización y auditoria).
  • Implementar funciones de cache de datos con frecuente consulta.

 Si se necesita crear un sistema que pueda ser invocado a través de mecanismos (protocolos) diferentes, se debe agregar una fachada entre la lógica de negocios y la interfaz de servicios. Al implementar esta fachada, se puede consolidar el código relacionado con las políticas (como la autorización, la auditoría y las validaciones, entre otros) de modo que se pueda utilizar por parte de varias interfaces de servicios que traten con diversos canales.

Esta fachada ofrece una mayor facilidad de mantenimiento debido a que aísla los cambios en los mecanismos de comunicación de la implementación de los componentes empresariales, tal como se muestra en la siguiente figura de ejemplo.

Tomado con fines Educativos de la Guia de Patrones, Practicas y Arquitectura .NET, Autores:  Ernesto Marquina, Jose David Parra.  Microsoft Services.

Patrón de Arquitectura por Capas. Componentes presentes en la Capa de Presentación

Diseño de Componentes de Interfaz de Usuario

Las interacciones más complejas conllevan el diseño de componentes de proceso de interfaz que permiten organizar los elementos de la interfaz y controlar la interacción con el usuario. Los componentes de proceso de interfaz resultan especialmente útiles cuando la interacción del usuario sigue una serie de pasos predecibles, como al utilizar un asistente (Wizard) para realizar una tarea determinada.

Cuando un usuario interactúa con un elemento de interfaz de usuario, un evento es generado que llama código en una función controladora. Esta función, a su vez hace un llamado a los componentes de negocio, para implementar las acciones deseadas y obtener cualquier dato necesario que requiere ser mostrado. Finalmente, la función controladora actualiza la interfaz de usuario. De esta manera, estamos separando el código de la Vista y el Controlador. Esto ayuda mucho en el mantenimiento de esta capa.

Según el diagrama anterior, la Vista haría parte de los Componentes de Interfaz de Usuario, mientras que el controlador haría parte de los Componentes de Proceso de Interfaz. Las siguientes son las principales responsabilidades de los componentes de interfaz de usuario:

  • Comunicación con el usuario (entradas y visualización – rendering de los resultados)
  • Realizar el formateo de valores (como el formato adecuado de las fechas).
  • Interpretar los eventos y acciones del usuario, y llamar la función correspondiente del controlador.
  • Limitar entradas y validaciones de información. Por ejemplo, un campo Quantity puede limitar las entradas del usuario a valores numéricos.
  • Transformaciones simples sobre la información digitada por el usuario
  • Almacenamiento de datos en caché. En ASP.NET, se puede especificar el almacenamiento en caché de la salida de un componente determinado de la interfaz de usuario para evitar el continuo procesamiento del mismo.
  • Paginación de información. Es frecuente, especialmente en las aplicaciones Web, mostrar largas listas de datos como conjuntos paginados.
  • Personalizar el aspecto de la aplicación en función de las preferencias del usuario o el tipo de dispositivo de cliente utilizado (aplicaciones móviles).

Cliente Web o Cliente Windows?

Básicamente existen dos tipos de clientes en las aplicaciones empresariales, los que utilicen formas Web (Web Forms) y los que utilicen Formas Windows (WinForms). A continuación se muestra una tabla con las ventajas y desventajas de cada una de ellas y cuando pueden ser utilizadas:

Web Forms  WinForms 
 Despliegue automático  Siempre requiere que la primera y nuevas versiones sean instaladas en el disco de la maquina cliente. .NET incluye una característica llamada “SmartClient” que baja automáticamente las nuevas versiones de assemblies a la maquina desde un servidor Web central. Algunos puntos a tener en cuenta:

 El tamaño de los assemblies en .NET es muchísimo menor que en Visual Basic, lo que agilizaría la transferencia por la red.

 .NET a diferencia de COM, no requiere el registro de Dynamic Link Libraries (DLLs) o componentes, que anteriormente complicaban considerablemente la instalación en cliente.

 En el caso de no poderse bajar la nueva versión, la aplicación se inicia con la versión más reciente en disco.

 Recuerde que por la arquitectura de capas, solamente si fueron hechos cambios en la interfaz de usuario, será necesario actualizar la versión en el cliente.

 Según el punto anterior, la capa de presentación debe ser lo más delgada posible, con solo código de interfaz y validaciones simples. Pero con la autonomía suficiente, y así que no dependa completamente de los componentes de negocio (y por consiguiente de los tiempos de red).

 Solo requiere tener instalado previamente el Framework de .NET. La plataforma de hardware y software actual lo soporta sin problemas.

Cualquier interacción con el usuario requiere un viaje completo al servidor Web. Es completamente dependiente del servidor. Un modelo de eventos limitado, complica la programación en cliente (scripts). Por lo anterior, el tiempo de respuesta de la aplicación depende en todo momento de la red. Una interfaz de usuario con el mejor tiempo de respuesta y más fácil de programar
Por su modelo basado en servidor, la interacción con otras aplicaciones ejecutándose en la máquina de cliente es bastante complicada. Muy seguramente requiere el desarrollo de controles, lo que complica el deployment Fácil interacción con otras aplicaciones ejecutándose en la maquina cliente
La aplicación depende completamente de la red y el servidor. Lo que ocasiona un gran consumo del ancho de banca de la red. Muchas operaciones pueden ser desarrolladas localmente, lo que disminuye el consumo de red. Todo el tráfico de red se reduce a llamados remotos y datos
Manejo del estado del usuario se hace en el servidor El estado se almacena en cada cliente. Esto aumenta considerablemente la escalabilidad del sistema
Capacidades limitadas de impresión. Soporte completo a impresión y reportes

Acceso a componentes lógicos de acceso a datos desde la interfaz de usuario

Las interfaces de usuario de determinadas aplicaciones necesitan procesar los datos disponibles como consultas expuestas por los componentes de de acceso a datos. Un ejemplo muy común de este escenario se presenta cuando necesitamos llenar una lista (ListBox, DataGrid, ComboBox, etc.) con información que cambia muy poco (departamentos, ciudades, oficinas, etc.). En estos casos, sería poco eficiente encapsular el acceso a los datos a través de la capa de negocios (que añadiría ningún valor), y no permitir un acceso directo.

El acceso directo a los componentes de acceso a datos desde la interfaz de usuario parece contradecir el concepto de disposición en capas. No obstante, resulta útil en este caso considerar a la aplicación como un servicio homogéneo; se llama a la aplicación y ésta decide cuáles son los componentes internos más adecuados para responder a una solicitud determinada.

Esta decisión se puede tomar si se está dispuesto a acoplar los métodos y esquemas de acceso a datos con la semántica de la interfaz de usuario. Esta relación requiere el mantenimiento conjunto de los cambios de la interfaz de usuario y de los esquemas.

Diseño de componentes de proceso de interfaz

La interacción del usuario con la aplicación puede seguir un proceso predecible. Por ejemplo, puede que la aplicación comercial de ejemplo requiera que los usuarios escriban los datos de los productos, vean el precio total, escriban los detalles de pago y, finalmente, escriban la información relativa a la dirección del pedido. Este proceso conlleva la visualización y aceptación de la entrada de un número de elementos de interfaz de usuario, y el estado del proceso (los productos solicitados y los detalles de las tarjetas de crédito, entre otros) se debe mantener en la transición de un paso a otro del proceso. Para facilitar la coordinación del proceso de usuario y controlar el mantenimiento del estado requerido al visualizar varias páginas o formularios de la interfaz de usuario, es necesario crear componentes de proceso de interfaz.

La siguiente figura muestra los componentes de proceso de interfaz pueden ser compartidos por cada uno de las implementaciones de interfaz de usuario que tiene la aplicación.

Los componentes de proceso de interfaz se implementan normalmente como clases .NET que exponen métodos a los cuales pueden llamar las interfaces de usuario. Cada método encapsula la lógica necesaria para realizar una acción específica en el proceso de usuario. La interfaz de usuario crea una instancia del componente del proceso de interfaz y la utiliza para efectuar la transición a través de los pasos del proceso. El diseño de componentes de proceso de interfaz para su uso por parte de varias interfaces da lugar a una implementación más compleja, debido al aislamiento de los problemas específicos de los dispositivos.

Las siguientes son las principales responsabilidades de los componentes de proceso de interfaz:

  • Separan el flujo de la interacción del usuario de la implementación o dispositivo en el que ocurre.
  • Realizan el seguimiento del estado actual de la interacción del usuario.
  • Encapsulan el modo en que las excepciones pueden afectar al flujo de proceso de usuario.
  • Proporcionan un modo simple de combinar los elementos de la interfaz de usuario en los flujos de interacción del usuario sin que sea necesario volver a desarrollar el flujo de datos ni la lógica de control.

 En resumen, la separación de la funcionalidad de interacción del usuario en componentes de interfaz y proceso de interfaz conlleva las siguientes ventajas:

  • El estado de la interacción de usuario de ejecución larga se mantiene más fácilmente, lo que permite el abandono y la reanudación de la interacción, probablemente incluso utilizando una interfaz de usuario diferente. Por ejemplo, un cliente podría agregar varios elementos a un carro de compra utilizando la interfaz de usuario basada en el Web y, a continuación, llamar a un representante de ventas para completar el pedido.
  • Varias interfaces de usuario pueden utilizar el mismo proceso. Por ejemplo, en la aplicación comercial de ejemplo, se puede utilizar el mismo proceso de usuario para agregar un producto a un carro de compra tanto desde la interfaz de usuario basada en el Web como desde la aplicación basada en Windows Forms.

Tomado con fines Educativos de la Guia de Patrones, Practicas y Arquitectura .NET, Autores:  Ernesto Marquina, Jose David Parra.  Microsoft Services.

Componentes de un Patrón de Arquitectura por Capas

Los tipos de componentes identificados en el escenario de ejemplo son:

1.    Componentes de interfaz de usuario. La mayor parte de las soluciones necesitan ofrecer al usuario un modo de interactuar con la aplicación. En un ejemplo de aplicación comercial de ejemplo, un sitio Web permite al cliente ver productos y realizar pedidos, y una aplicación basada en Windows® permite a los representantes de ventas escribir los datos de los pedidos de los clientes que han telefoneado a la empresa. Las interfaces de usuario se implementan utilizando formularios de Windows Forms, páginas ASP.NET, controles u otro tipo de tecnología que permita procesar y dar formato a los datos de los usuarios, así como adquirir y validar los datos entrantes procedentes de éstos.

2.    Componentes de proceso de interfaz. En un gran número de casos, la interacción del usuario con el sistema se realiza de acuerdo a un proceso predecible. Por ejemplo, en una aplicación comercial, se podría implementar un procedimiento que permita ver los datos del producto. De este modo, el usuario puede seleccionar de una lista de categorías de productos disponibles y, a continuación, elegir uno de los productos de la categoría seleccionada para ver los detalles correspondientes. Del mismo modo, cuando el usuario realiza una compra, la interacción sigue un proceso predecible de recolección de datos por parte del usuario, por el cual éste en primer lugar proporciona los detalles de los productos que desea adquirir, a continuación los detalles de pago y, por último, la información para el envío. Para facilitar la sincronización y organización de las interacciones con el usuario, resulta útil utilizar componentes de proceso de interfaz de usuario individuales. De este modo, el flujo del proceso y la lógica de administración de estado no se incluye en el código de los componentes de interfaz de usuario, por lo que varias interfaces (Web, Windows, Móvil, etc.) podrán utilizar el mismo “motor” de interacción básica.

3.     Flujos de negocio. Una vez que el proceso de interfaz ha recopilado los datos necesarios, éstos se pueden utilizar para ejecutar un proceso de negocios. Por ejemplo, tras enviar los detalles del producto, el pago y el envío a la aplicación comercial, puede comenzar el proceso de cobro del pago y preparación del envío. Gran parte de los procesos de negocio conllevan la realización de varios pasos, los cuales se deben organizar y llevar a cabo en un orden determinado. Por ejemplo, el sistema empresarial necesita calcular el valor total del pedido, validar la información de la tarjeta de crédito, procesar el pago de la misma y preparar el envío del producto.  El tiempo que este proceso puede tardar en completarse es indeterminado, por lo que sería preciso administrar las tareas necesarias, así como los datos requeridos para llevarlas a cabo. Los flujos de trabajo de negocio definen y coordinan los procesos de negocio de varios pasos de ejecución larga y se pueden implementar utilizando herramientas de administración de procesos de negocios, como BizTalk Business Process Management u otras herramientas se encargan de automatizar flujos y procesos de negocio.

4.    Componentes de negocio. Independientemente de si el proceso de negocios consta de un único paso o de un flujo de trabajo organizado, la aplicación requerirá probablemente el uso de componentes que implementen reglas de negocio y realicen tareas de negocio. Por ejemplo, en la aplicación comercial, se deberá implementar una funcionalidad que calcule el precio total del pedido y agregue el costo adicional correspondiente por el envío del mismo. Los componentes de negocio implementan la lógica de negocio de la aplicación.

 5.    Agentes de servicios. Cuando un componente de negocio requiere el uso de la funcionalidad proporcionada por un servicio externo, tal vez sea necesario hacer uso de componentes que administren la semántica de la comunicación con dicho servicio. Por ejemplo, los componentes de negocio de la aplicación comercial descrita anteriormente podría utilizar un agente de servicios para administrar la comunicación con el servicio de autorización de tarjetas de crédito y utilizar un segundo agente de servicios para controlar las conversaciones con el servicio de mensajería. Los agentes de servicios permiten aislar las particularidades de las llamadas a varios servicios desde la aplicación y pueden proporcionar servicios adicionales, como el mapeo del formato de los datos que expone el servicio al formato que requiere la aplicación.

 6.    Interfaces de servicios. Para exponer lógica de negocios como un servicio, es necesario crear interfaces de servicios que soporten los contratos de comunicación (comunicación basada en mensajes, formatos, protocolos, seguridad y excepciones, entre otros) que requieren los clientes. Por ejemplo, el servicio de autorización de tarjetas de crédito debe exponer una interfaz de servicios que describa la funcionalidad que ofrece el servicio, así como la semántica de comunicación requerida para llamar al mismo. Las interfaces de servicios también se denominan fachadas de negocios.

 7.    Componentes de acceso a datos. La mayoría de las aplicaciones y servicios necesitan obtener acceso al repositorio de datos en un momento determinado del proceso de negocios. Por ejemplo, la aplicación empresarial necesita recuperar los datos de los productos de una base de datos para mostrar al usuario los detalles de los mismos, así como insertar dicha información en la base de datos cuando un usuario realiza un pedido. Por lo tanto, es razonable abstraer la lógica necesaria para obtener acceso a los datos (y la estructura como están estos almacenados) en una capa independiente de componentes de acceso a datos, ya que de este modo se centraliza la funcionalidad de acceso a datos y se facilita la configuración y el mantenimiento de la misma.

 8.    Entidades de negocio. La mayoría de las aplicaciones requieren el paso de datos entre distintos componentes. Por ejemplo, en la aplicación comercial es necesario pasar una lista de productos de los componentes de acceso a datos a los componentes de interfaz de usuario para que éste pueda visualizar dicha lista. Los datos se utilizan para representar entidades de negocio del mundo real, como productos o pedidos. Las entidades de negocio que se utilizan de forma interna en la aplicación suelen ser estructuras de datos, como DataSets de ADO.NET, DataReader o secuencias XML, aunque también se pueden implementar utilizando clases personalizadas que representan entidades del mundo real necesarias para la aplicación, como productos, pedidos, o clientes.

 9.    Verticales de seguridad, administración operacional y comunicaciones. La aplicación probablemente utilice también componentes para realizar la administración de excepciones, autorizar a los usuarios a que realicen tareas determinadas y comunicarse con otros servicios y aplicaciones.

Tomado con fines Educativos de la Guia de Patrones, Practicas y Arquitectura .NET, Autores:  Ernesto Marquina, Jose David Parra.  Microsoft Services.

Categorías de Patrones

Si hacemos una revisión cercana a patrones existentes podemos revelar que estos cubren diferentes rangos de escalas y niveles de abstracción. Algunos patrones ayudan a estructurar un sistema en subsistemas base. Mientras otros ayudan al afinamiento de subsistemas y componentes, o las relaciones entre estos. Mientras que otros ayudan en la implementación en aspectos de diseño particulares en un lenguaje de programación especifico. Los patrones también van desde aquellos independientes del dominio, como aquellos que desacoplan componentes que interactúan, hasta el manejo de aspectos específicos al dominio, como políticas de transacciones en aplicaciones de negocio, o el enrutamiento de llamadas en telecomunicaciones. Según lo anterior, se definen las siguientes tres categorías de patrones:

–          Patrones de Arquitectura

–          Patrones de Diseño

–          Patrones de Implementación (Idiomas)

Los Patrones de Arquitectura

Expresa un esquema fundamental de organización estructural para sistema de software. Donde provee una serie de subsistemas predefinidos, especificando sus responsabilidades, e incluye reglas y guías para organizar las relaciones entre ellos. Básicamente, un patrón de arquitectura es una plantilla para una arquitectura de aplicaciones. Estos especifican las propiedades generales a la estructura del sistema, y repercuten la arquitectura de sus subsistemas. La selección de un patrón de arquitectura es por lo tanto una decisión fundamental al desarrollar un sistema de software. El patrón Modelo-Vista-Controlador  (MVC) es uno de los ejemplos más conocidos de un patrón de arquitectura, y provee la infraestructura para sistemas interactivos. Por estas características, los patrones de arquitectura son utilizados durante la etapa de definición de arquitectura de un sistema.

Los Patrones de Diseño

Los subsistemas dentro de una arquitectura de software, al igual que sus interrelaciones, consisten normalmente de unidades arquitectónicas más pequeñas. Describimos estas unidades a través de Patrones de Diseño. Un Patrón de Diseño define un esquema de refinamiento de los subsistemas o componentes dentro de un sistema, o las relaciones entre estos. Este describe una estructura común y recurrente de componentes interrelacionados, que resuelve un problema general de diseño dentro de un contexto particular.

Los patrones de diseño trabajan a una escala intermedia. Son menores en escala que un patrón de arquitectura, pero logran ser independientes del lenguaje de programación. La aplicación de un patrón de diseño no tiene efectos sobre la estructura fundamental del sistema (arquitectura), pero puede tener una fuerte influencia sobre la arquitectura de un subsistema. Un ejemplo concreto de patrones de diseño es el de Singleton o Facade. Por lo anterior, los patrones de diseño son utilizados durante la fase de diseño de un sistema.

 Patrones de Implementación

Un patrón de implementación (también llamado Idioma ) es un patrón de bajo nivel específico a un lenguaje de programación. Este describe como implementar aspectos particulares de componentes o sus relaciones utilizando las características de un lenguaje dado. Los patrones de implementación representan el nivel más bajo de patrones, y manejan aspectos tanto de diseño como implementación, y son mayormente utilizados durante la fase de desarrollo de un sistema. Frecuentemente, el mismo patrón de implementación se ve diferente al ser implementado sobre lenguajes distintos, y algunas veces un patrón de implementación muy útil en un lenguaje no tiene sentido sobre otro. Por estas características, los patrones de arquitectura son utilizados durante la etapa de definición de arquitectura de un sistema.

 Patrón de Arquitectura por Capas

El patrón de arquitectura por capas es una de las técnicas más comunes que los arquitectos de software utilizan para dividir sistemas de software complicados. Esto se ve en arquitectura de hardware, redes (por ejemplo, FTP funciona encima de TCP, la cual a su vez funciona encima de IP, y esta sobre Ethernet). Al pensar un sistema en términos de capas, se imaginan los principales subsistemas de software ubicados de la misma forma que las capas de un pastel, donde cada capa descansa sobre la inferior. En este esquema la capa más alta utiliza varios servicios definidos por la inferior, pero esta última es inconsciente de la superior. Además, normalmente cada capa oculta las capas inferiores de las superiores a ésta. Aunque este último comportamiento algunas veces es válido obviar. La siguiente figura muestra un esquema básico de una arquitectura siguiendo este patrón.

 

Partir un sistema en capas tiene una cantidad importante de beneficios:

–          Se puede entender una capa como un todo sin considerar las otras.

–          Las capas se pueden sustituir con implementaciones alternativas de los mismos servicios básicos.

–          Se minimizan dependencias entre capas.

–          Las capas posibilitan la estandarización de servicios.

–          Luego de tener una capa construida, puede ser utilizada por muchos servicios de mayor nivel.

Sin embargo, un modelo de capas también trae consigo algunos inconvenientes que deben ser tenidos en cuenta en el diseño:

 –            No todo es encapsulado de la mejor manera en un modelo de capas. Como resultado se pueden generar algunas veces cambios en cascada.

–            Demasiadas capas pueden generar problemas de rendimiento.

Pero la parte más difícil de una arquitectura basada en este modelo es decidir que capas implementar y que responsabilidad debe tener cada una. A continuación la discusión se centra en describir las tres capas principales de un patrón de arquitectura por capas.

Capa de Presentación

Referente a la interacción entre el usuario y el software. Puede ser tan simple como un menú basado en líneas de comando o tan complejo como una aplicación basada en formas. Su principal responsabilidad es mostrar información al usuario, interpretar los comandos de este y realizar algunas validaciones simples de los datos ingresados.

Lógica de Negocios

También denominada Lógica de Dominio [FOWLER], esta capa contiene la funcionalidad que implementa la aplicación. Involucra cálculos basados en la información dada por el usuario y datos almacenados y validaciones. Controla la ejecución de la capa de acceso a datos y servicios externos. Se puede diseñar la lógica en la capa de negocios para su uso directo por parte de componentes de presentación o su encapsulamiento como servicio y llamada a través de una interfaz de servicios, que coordina la conversación con los clientes del servicio e invoca cualquier flujo o componente de negocio.

Lógica de Acceso a Datos

Esta capa contiene la lógica de comunicación con otros sistemas que llevan a cabo tareas por la aplicación. Estos pueden ser Monitores Transaccionales, otras aplicaciones, sistemas de mensajería, etc. Para el caso de aplicaciones empresariales, generalmente está representado por una base de datos, que es responsable por el almacenamiento persistente de información. Esta capa debe abstraer completamente a las capas superiores (negocio) del dialecto utilizado para comunicarse con los repositorios de datos (PL/SQL, Transact-SQL, etc.).

Tomado con fines Educativos de la Guia de Patrones, Practicas y Arquitectura .NET, Autores:  Ernesto Marquina, Jose David Parra.  Microsoft Services.

Ejemplo Introduccion a la Programacion Orientada a Objeto en .NET

Con la finalidad de entender todos los conceptos explicados en este blog sobre Introducción a la Programación Orientada a Objetos se les coloca a continuación un link con el código completo de un programa para hacerle tanto mantenimiento a las tablas de Alumnos e Instructores, como ejecutar el envío de notificaciones a ambos.

La estructura del programa cumple con el modelo en capas donde se separan claramente las entidades de negocio, las reglas, las capas de persistencia,  presentación.

Link Codigo Fuente:   http://dl.dropbox.com/u/8067930/MVA/MVAEscuela.zip

Link Script BD:  http://dl.dropbox.com/u/8067930/MVA/MVAEscuelaDB_Script.zip

Para finalizar la grafica del Diagrama de Componente para este ejemplo:

Ejemplo Polimorfismo

En los ejemplos anteriores pudimos analizar las Clases Alumno e Instructor.  En este ejemplo veremos que se desarrollo un formulario para enviar notificaciones.  En este caso tanto alumno como instructor se comportaran como persona.  Esto es lo que se conoce como Polimorfismo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Net.Mail;

using MVAEscuela.Core.BE;
using MVAEscuela.Core.BLL;

public partial class Notificacion : System.Web.UI.Page
{
    Alumno_BLL m_Alumno_BLL = new Alumno_BLL();
    Instructor_BLL m_Instructor_BLL = new Instructor_BLL();

    protected void Page_Load(object sender, EventArgs e)
    {
    }

    protected void Done_Click(object sender, ImageClickEventArgs e)
    {
        if (chkAlumnos.Checked)
        {
            Noixno.Common.CommonList<Instructor> Instructores = m_Instructor_BLL.GetAll(null);

            foreach (Instructor instructor in Instructores)
            {
                Notificar(instructor);
            }
        }

        if (chkInstructor.Checked)
        {
            Noixno.Common.CommonList<Alumno> Alumnos = m_Alumno_BLL.GetAll(null);
            foreach (Alumno alumno in Alumnos)
            {
                Notificar(alumno);
            }
        }
    }

    //Polimorfismo ya quede recibir un instructor o un alummo ya que ambos heredan de persona
    protected void Notificar(Persona persona)
    {
        string Cuerpo = @"<HTML><body><table border =’1′><tr><td>Estimado: " + persona.Nombre + "</td></tr> <tr><td>Estimado: " + Notificacion.Text + "</td></tr> </table></body></HTML>";
        MailMessage mail = new MailMessage();
        SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");

        mail.From = new MailAddress("server@noixnogroup.com");
        mail.To.Add(persona.CorreoElectronico);

        mail.Subject = " Notificacion :: MVA Escuela";

        mail.IsBodyHtml = true;
        mail.Priority = MailPriority.High;
        mail.Body = Cuerpo;

        SmtpServer.Port = 587;
        SmtpServer.Credentials = new System.Net.NetworkCredential("Server@noixnogroup.com", "AmericaA00*");
        SmtpServer.EnableSsl = true;

        try
        {
            SmtpServer.Send(mail);
        }
        catch (SmtpException ex)
        {
            info.Text = ex.Message;
        }
        catch (Exception ex)
        {
            info.Text = ex.Message;
        }  
    }
}

Ejemplo de Clase

Como había comentado en un post anterior, en programación orientada a objeto, una clase define las características y comportamientos comunes de los objetos, en otras palabras la clase es el molde para la creación de los mismos. En las Próximas líneas les presento un ejemplo de la Clase Alumno en .net

La clase alumno es una abstracción con los atributos,  comportamientos bases para nuestro sistema.

using System;
using Noixno.Common;

namespace MVAEscuela.Core.BE
{
    [Serializable]
    public partial class Alumno : Persona //Herencia
    {       
        #region Private fields, to hold the state of the ‘Alumno’ entity   
        private int m_IdAlumno;
        private DateTime m_FechaDeNacimiento;

        #endregion
        #region Public properties, to expose the state of the entity
        public int IdAlumno
        {
            get
            {
                return m_IdAlumno;
            }
            set
            {
                m_IdAlumno = value;
                IsModified = true;
            }
        }
        public DateTime FechaDeNacimiento
        {
            get
            {
                return m_FechaDeNacimiento;
            }
            set
            {
                m_FechaDeNacimiento = value;
                IsModified = true;
            }
        }

        #endregion
    }
}