lunes, 26 de diciembre de 2016

Usando el control de validación CompareValidator ASP .NET - parte II

Como un complemento al primer ejercicio del control ASP .NET CompareValidator, aqui presento un segundo ejemplo que muestra como utilizar el control CompareValidator para comparar el valor de un control ASP.NET con un tipo específico de dato .NET (Currency, Date, Double, Integer, String) o bien comparar si teniendo dos valores: uno es menor o mayor al otro o si ambos valores son iguales.

Este segundo ejemplo consta de dos archivos: CompareValidatorSample2.aspx y CompareValidatorApp2.aspx.cs

Puedes descargar el código fuente aquí.

Fig 1 El ejemplo muestra la comparación de un valor contra un tipo específico de dato y la comparación del valor de un control contra el valor de otro control.

Fig 2 Comparando el valor de un control con un tipo específico de dato .NET.

Fig 3 Comparando el valor de un control contra el valor de otro control.

Algunas propiedades esenciales del control CompareValidator.

  • ControltoValidate: El control de donde obtendremos el valor a comparar
  • ControlToCompare: El control con el cual se compara el valor obtenido de la propiedad ControltoValidate
  • Display: Esta propiedad tiene 3 valores:
    1. Static: es la propiedad predeterminada, reserva un espacio suficiente en la página para mostrar el mensaje de error.
    2. Dynamic: el espacio para mostrar el mensaje no se reserva, cuando el mensaje se despliega se desplaza el contenido existente en la página.
    3. None: el mensaje no será desplegado en el lugar del control sino en el control ValidatorSummary si se localiza en la misma página.
  • Errormessage: el texto del mensaje que se desplegará si no se cumplen las condiciones.
  • Operator: La operación que efectuará el control en los valores de los campos, los valores son los siguientes:
    1. LessThan:El valor del ControlToValidate debe ser menor al valor del ControlToCompare.
    2. Equal: El valor del ControlToValidate debe ser igual al valor del ControlToCompare.
    3. NotEqual: El valor del ControlToValidate no debe ser igual al valor del ControlToCompare.
    4. LessThanEqual: El valor del ControlToValidate debe ser menor o igual al valor del ControlToCompare.
    5. GreaterThan: El valor del ControlToValidate debe ser mayor al valor del ControlToCompare.
    6. GreaterThanEqual: El valor del ControlToValidate debe ser mayor o igual al valor del ControlToCompare.
  • Type: El tipo de datos de los valores a comparar, los tipos de datos disponibles para este control son:
    1. Currency: Moneda
    2. Date: Fecha
    3. Double: Valor de punto flotante
    4. Integer: Entero sin punto decimal
    5. String: Cadena

miércoles, 21 de diciembre de 2016

Notas acerca de la recursión en C#

La recursión es una técnica de programación que se programa mediante un método que ya sea por iteración o por decisión resuelve un problema hasta llegar a un caso base , un método recursivo es un método que se llama así mismo ya sea directamente o indirectamente a través de otro método. Los enfoques recursivos para resolver problemas tienen varios elementos en común. El método en si sabe como resolver el o los casos más sencillos los llamados casos base.

Como un ejemplo ilustrativo, escribí un sencillo programa que contiene las funciones Fibonacci y factorial.

El programa se escribió en un proyecto Xamarin

Fig 1. El programa en el entorno de Xamarin

Para ejecutar el programa desde una consola de terminal, habilitar en el proyecto la opción "Run on external console"

Fig 2. Habilitando la opción "Run on external console"

Fig 3. El programa en ejecucción

lunes, 19 de diciembre de 2016

Usando los controles de validación ASP.NET IV (CompareValidator)

Otra de las tareas muy útiles al construir formularios para aplicaciones ASP.NET es poder comparar el valor de un control en el formulario con el valor de otro control, en estos casos se utiliza el control CompareValidator, este control también puede comparar el valor del control con un valor constante o si se requiere asegurarnos que ese valor sea del tipo de datos que nosotros necesitamos.

Como primer ejemplo de este control mostraré la una página ASP.NET con unos campos solicitando una contraseña y su confirmación.

Este primer ejemplo consta de dos archivos: CompareValidatorSample.aspx y Samples.ASP.CompareValidatorApp.aspx.cs.

Fig 1 Utilizando el control CompareValidator para confirmar contraseñas.

Fig 2 Si las contraseñas no son idénticas el control muestra un mensaje.

Fig 3 Si las contraseñas coinciden, se envían los datos al servidor.

miércoles, 14 de diciembre de 2016

Enumeraciones con C#

Un tipo de datos de enumeración enum es usado para definir un conjunto de elementos constantes, este tipo de datos se usan para agrupar constantes y en programas de opción múltiple. Las enumeraciones pueden ser de cualquier tipo de datos (integer, short, long) excepto el tipo de datos char.

Un breve ejemplo:

Ahora con esta enumeración podemos hacer un programa que tenga el siguiente método:

La ejecucción del programa producirá la siguiente salida.

Fig 1. La ejecucción del ejemplo de enumeraciones

domingo, 4 de diciembre de 2016

Entendiendo las expresiones lambda (lambda expressions) en C#

Introducción

La programación imperativa es uno de los paradigmas de computación mas ampliamente utilizados por la mayoría de lenguajes de programación de alto nivel debido al gran soporte académico y comercial y a que los programas son relativamente independientes del tipo de computadora donde se ejecutan porque los lenguajes de programación deben abstraer las operaciones del modelo de maquina para la cual se diseñaron.

La programación imperativa se basa en el modelo de la máquina de Von Neuman, del cual la mayoría de las computadoras personales y estaciones de trabajo tienen elementos comunes.

Aunque menos utilizado existe otro paradigma que a diferencia del imperativo se basa en las matemáticas (aplicación de funciones) con el cual igualmente podemos expresar operaciones computacionales de forma mas compacta y abstracta, este paradigma se conoce como programación funcional.

Uno de los muchos elementos del paradigma funcional que .NET incluye desde la versión 3.0 son las expresiones lambda (lambda expression).

Programación Funcional

Los conceptos básicos de la programación funcional datan de 1956 a 1958 con el trabajo de Jonh McCarthy en el desarrollo y diseno de LISP (List Processor), este lenguaje esta basado en el calculo lambda que sento las bases de los lenguajes funcionales, características como:

  • Recursión: se utiliza para para realizar operaciones repetitivas, no utiliza la iteración.
  • Funciones de primer orden: las funciones tienen el mismo nivel que cualquier otro elemento del lenguaje,pueden aplicarse a valores, evaluarse, regresar un valor y ser parámetros de otras funciones.
  • No requiere asignación: el computo se realiza aplicando funciones a los argumentos.
  • Garbage collector: Se reclaman los objetos que no están siendo utilizado por el programa.
  • Tipado dinámico (Dynamic typing): La comprobación del tipo se realiza en tiempo de ejecución, los valores tienen tipos, pero las variables no.

El paradigma funcional se basa en el concepto matemático de función, que la mayoria de los lenguajes de programación imperativos y funcionales comparten y cuya definición es

(1)Una función f es una regla que asigna a cada elemento x de un conjunto A exactamente un elemento llamado f(x) de conjunto B

Donde la programación funcional marca su diferencia con la imperativa es que para la programación funcional cada programa es equivalente a esta definición, donde x es el argumento o dominio de f mientras que y es el rango de f o la salida sea los programas son cajas negras donde solo importa el que se esta computando y no el como se esta computando que es el caso de la programación imperativa.

En resumen cuando se programa de forma funcional se piensa más en expresiones y su significado que en una secuencia de operaciones en memoria.

Tipos Delegate y métodos anónimos

Desde sus primeras versiones .NET introdujo el objeto delegate (delegado) que es un tipo particular de objeto (un delegate deriva de la clase base System.Delegate), que puede encapsular la referencia a un método estático o de una instancia como si fuera un mecanismo de callback(devolución de llamada) similar a los apuntadores de función de C y C++ pero con la importante diferencia de que proporciona un tipado seguro (type-safety) para evitar errores en tiempo de ejecución y que puedan detectarse en tiempo de compilación si la función no coincide con la firma del método al que hace referencia.

Esto posibilita en un contexto de programación orientada a objetos que los métodos pueden recibir como argumentos otros métodos además de tipos primitivos y de referencia. Veamos un ejemplo para ilustrar estos conceptos con C#.

En versiones anteriores a C# 2.0 (1.1,1.0) los delegate se utilizaban como parámetros, veamos el siguiente ejemplo que se compone de dos clases:

  1. La clase Temp.cs que es la clase que encapsula las operaciones.
  2. La clase Program.cs que es la clase principal que asigna los métodos al delegado.

Ejemplo 1.1 Uso de métodos como parámetros en C# 1.1 (descargar archivo aquí).

Observamos que los métodos que implementan la funcionalidad deben declararse de una manera completamente procedural e imperativa.
public static double GetCelsius(double fahrenheit)
  {
   return (fahrenheit - 32) * (5 / 9D);
  }

  public static double GetKelvin(double fahrenheit)
  {
   return fahrenheit + 460;
  }

Las versiones posteriores de C# al incorporar los métodos anónimos se acerca más a la programación funcional al asociar un bloque de código a un delegate sin necesidad de tener toda su implementación en un método sino dentro de la misma declaración del objeto, como se muestra en el siguiente código que es el mismo código anterior pero usando métodos anónimos.

Ejemplo 1.2 Uso de métodos como parámetros utilizando métodos anónimos (descargar archivo aquí).

Aquí observamos la diferencia con respecto al código anterior del Ejemplo 1.1.

    Console.WriteLine("{0} Fahrenheit = {1:0.00} Celsius", x, ApplyF(x,
    delegate (double fahrenheit)
   {
    return (fahrenheit - 32) * (5 / 9D);
   }));
   Console.WriteLine("{0} Fahrenheit = {1:0.00} Kelvin", x,
   ApplyF(x,
            delegate (double fahrenheit)
   {
    return fahrenheit + 460;
   }));

Expresiones Lambda (Lambda Expressions)

Las expresiones lambda provienen del cálculo lambda (lambda calculus) desarrollado por Alonzo Church en los años 1930’s como una notación para representar todas las funciones computables equivalentes a una máquina de Turing, todos los lenguajes funcionales pueden ser vistos como una variante sintáctica del cálculo lambda.

Las expresiones Lambda son útiles para sintetizar funciones con pocos parámetros que regresan algún valor, esta expresión consiste básicamente en una regla de sustitución que expresa tal cual una función o sea un mapeo de los elementos del conjunto dominio a los elementos de un codominio por ejemplo en la siguiente expresión:

        cuadrado : integer → integer donde cuadrado(n) = n²
    

Se reduce a una notación que produce una función anónima donde los únicos símbolos son la letra lambda (λ) y el punto (.).

    λn.n²

En la mayoría de los lenguajes funcionales las funciones anónimas son valores representados por la palabra reservada lambda, como el caso de LISP.

Lambda (n)(**n)

Aunque C# no utiliza los símbolos de la notación matemática lambda, el operador lambda es => que significa “tiende a” o “va hacia a”, la estructura de una expresión lambda en C# es:

(Argumentos de entrada) => (salida al procesarlos)
En caso de únicamente una variable la sintaxis es:
(x) => (x*x)
En caso de múltiples argumentos la sintaxis es:
(x,y,z) => ()

Aquí es importante saber que es el tipo delegate que dicta el tipo de los parámetros de entrada y de salida.

Ejemplo 1.3 Métodos como parámetros utilizando expresiones lambda.

Observamos que de los métodos anónimos a las expresiones Lambda, nos queda una sintaxis más legible y compacta.


ApplyF(x, (fahrenheit) => ((fahrenheit - 32) * (5 / 9D))));
ApplyF(x, (fahrenheit) => (fahrenheit + 460)));

Al ejecutar todos los programas observamos que el resultado es el mismo en cada uno, lo que cambio fue únicamente la sintaxis.
Fig 1. El resultado del código usando delegados.

Conclusión

Para los nuevos retos en el desarrollo de software, es importante que los lenguajes de programación incorporen características de un paradigma de programación diferente a ellos para extender sus capacidades y así poder expresar algoritmos de una manera compacta y más concisa esto da como resultado un código más legible.

domingo, 27 de noviembre de 2016

Utilizando DNS (Domain Name System) en .NET con C#.

Cualquier dispositivo conectado a una red TCP/IP siempre tiene asignado un identificador único de 32 bits que se le conoce como dirección IP (IP Address) o dirección de red. Esta dirección es jerárquica y consta de cuatro octetos (valores de 8 bits) que se dividen en dos partes: la primera parte identifica a la red y la segunda identifica los hosts (cualquier dispositivo conectado) en esa red. Las dos partes son requeridas para formar una dirección IP.

Fig 1. Una dirección IP V4 jerárquica.

Cada dirección IP identifica solamente a un único dispositivo en una red TCP/IP como Internet, aunque es una ventaja para las máquinas esto representa un problema para los humanos, ya que sería muy difícil para una persona recordar cada una de los computadoras que utiliza por su dirección IP.

Debido a que la gente asocia mucho mejor nombres para las cosas, los diseñadores de Internet inventaron el DNS (Domain Name System) que es una manera de asociar nombres que la gente puede recordar con la dirección IP de una máquina.

DNS (Domain Name System)

Antes del DNS los dispositivos dependían de un único archivo de texto (/etc/hosts) como una tabla de hosts, para asociar los nombres de los sistemas en direcciones IP, a mediano plazo esta solución era ineficiente para mapear los nombres de hosts en direcciones, además de que no existía ninguna técnica para distribuir automáticamente la información acerca de los dispositivos recientemente agregados.

Por el contrario, DNS en lugar de depender de una sola gran tabla, es un sistema jerárquico de bases de datos distribuidas que no depende de una base de datos centralizada para resolver los nombres de hosts obteniendo las direcciones IP ya que DNS distribuye su información a través de miles de servidores de nombres. En la parte superior de la jerarquía DNS, un grupo de servidores raíz sirven a un dominio raíz.

Usando Domain Name System con las clases de .NET

.NET proporciona varias clases para apoyar la interacción con servidores DNS, las más comunes son:

IPAddress: representa tal cual una dirección IP, la dirección misma esta disponible como la propiedad Address, y se convierte en su formato decimal con el método .ToString() también realiza la operación inversa con el método Parse() el cual recibe el formato decimal como argumento. Además de estos métodos esta clase también tiene constantes estáticas que regresan las direcciones especiales Loopback y Broadcast.

IPHostEntry: encapsula toda la información referente a un dispositivo, lo más utilizado de esta clase es:

  1. HostName: regresa una cadena con el nombre del dispositivo.
  2. AddressList: regresa un arreglo de objetos IPAddress con las direcciones IP asignadas al dispositivo.
  3. Aliases: contiene un arreglo de alias asociados a un dispositivo.

Dns: hace posible la comunicación con el servidor DNS predeterminado para la traducción de un nombre a su dirección IP o direcciones IP asociadas. Esta clase difiere de las clases IPAddress y IPHostEntry porque esta clase tiene la habilidad de comunicarse con servidores DNS para obtener información. Lo más utilizado de esta clase es:

  1. GetHostName: Obtiene el nombre de host del dispositivo local.
  2. GetHostEntry: Resuelve una dirección IP o un nombre de host y regresa un objeto IPHostEntry con un arreglo de direcciones IP (objetos IPAddress).
  3. GetHostAddresses: Regresa un arreglo de direcciones IP (objetos IPAddress)

Como ejemplo de la utilización de estas clases escribí el siguiente programa que emula la funcionalidad de la utilidad nslookup, en esta caso utilizando las clases de .NET en una interfaz gráfica en GTK#.

Fig 2. El programa obteniendo una dirección tipo A del host www.mit.edu.

Fig 3 El programa obteniendo una dirección tipo C del host www.rt.com.

Fig 4 Obteniendo una lista de direcciones IP clase C del host www.yahoo.com.

En el código de la aplicación primero se distingue entre una dirección IP y el nombre de un host, según esta distinción se obtiene una clase IPHostEntry o bien un arreglo de clase IPAddress, al invocar el método GetHostEntry en el primer caso o el método GetHostAddress en el segundo.

En el primer caso se obtiene el arreglo de IPAddress de la propiedad AddressList en el segundo solamente se recorre y se imprime dicho arreglo.

Nota: El :NET Framework desde la version 1.1 soporta IPV6 a través de las clases que se encuentran en el ensamblado System.Net.

sábado, 12 de noviembre de 2016

Entendiendo la programación de Sockets UDP con GTK# y .NET

UDP (User Datagram Protocol) es un protocolo de datagramas, no orientado a la conexión mucho más sencillo, poco fiable y de alto rendimiento, que a diferencia de TCP no incluye todas características para garantizar la entrega de paquetes, tales como recuperación de fallas, chequeo de errores o control de flujo. Debido a estas características UDP debe utilizarse en casos específicos, donde se asuma que el rendimiento es mejor que la fiabilidad:

  1. Cuando se transmite una pequeña cantidad de datos en periodos muy cortos de tiempo.
  2. Aplicaciones de “consulta y respuesta”, que trasmiten una consulta y esperan una respuesta inmediata.
  3. En sistemas de compresión para la transmisión de audio y video que pueden aceptar cierta cantidad de corrupción o perdida de paquetes.
  4. Algunas aplicaciones tienen su propio mecanismo de entrega de transporte, así que no necesitan de una capa de transporte. Estas aplicaciones usaran UDP mas eficientemente que TCP.

Por su rendimiento, UDP es recomendable en aplicaciones en donde es aceptable que algunos paquetes se pierdan durante la comunicación, como video streaming de video o algún protocolo multicasting como DNS.

La cabecera UDP tiene solo 4 campos: puerto origen, puerto destino, longitud y checksum. Los campos origen y destino tiene la misma funcionalidad que se tienen en la cabecera TCP. La longitud del campo especifica la longitud de la cabecera UDP y el campo checksum permite la revisar integridad del paquete.

Fig 1 Los campos del paquete UDP.

La clase UDPClient

La clase UdpClient es responsable de manejar mensajes punto a punto (point-to-point) y multicasting con el protocolo UDP; la clase UdpClient utiliza endpoints, esta clase puede ser construida inicialmente con el parámetro de un host o bien este parámetro puede especificarse durante el método Send().

Tambien proporciona un método Receive() que bloquea el hilo de ejecución hasta que un datagrama es recibido.

La clase UdpClient es una pequeña interfaz comparado a la clase TcpClient. Esto refleja la simple naturaleza de este protocolo en comparación con TCP. Mientras que ambas clases TcpClient y UdpClient utilizan un Socket internamente, la clase UdpClient no contiene un método para regresar un flujo de red (stream) para escribir y leer, en lugar de eso tiene un método Send() que acepta un arreglo de bytes como parámetro, mientras el método Receive() recibe un arreglo de bytes.

Fig 2 Miembros esenciales de la clase UDP Client.

Metodo o propiedad Descripción
Receive Recibe un datagrama UDP que fue enviado por una máquina remota.
Send Envia un datagrama UDP a una máquina remota.
Client Obtiene el socket subyacente que utiliza la clase.

Ejemplo de una comunicación entre un clientes y un servidor UDP

Es importante entender que en un modelo de comunicación sin conexión como UDP la comunicación se limita estrictamente a un modelo de petición/respuesta, que se lleva de la siguiente manera:

Fig 3 Modelo de comunicación petición/respuesta

Cada petición es un arreglo de bytes se salida procedente del cliente. Este arreglo de bytes se envía al servidor mediante TCP/IP, donde se convierte en la entrada del servidor. La respuesta entonces es el arreglo de bytes que salen del servidor para actuar como la entrada del cliente. Debido a la simpleza de este modelo, presenta las siguientes limitaciones:

  • Falta de conexión continua
  • Falta de fiabilidad
  • Seguridad insuficiente

Para mostrar como trabaja la comunicación entre un cliente y un servidor UDP utilizando la clase UdpClient escribí dos programas: un servidor y un cliente UDP. Ambos programas utilizan una interfaz de usuario (GUI) en GTK# para comunicarse entre ellos.

Fig 4 Ejemplo de un time server UDP con una GUI GTK#

Fig 5 Ejemplo de un cliente UDP con una GUI GTK#

Pasos para la construcción de un servidor UDP GTK#

El servidor UDP envía la fecha y la hora actual de la máquina a los clientes que se conecten en su número de puerto, durante los minutos que el servidor se encuentre activo, ambos el número de puerto y los minutos son especificados por el usuario en la pantalla.

El proyecto del servidor se compone de dos clases:

  1. La clase MainWindowServer.cs es la clase que construye la GUI del programa, obtiene los parámetros: número de puerto y minutos de ejecución del subproceso servidor, informa acerca de su estado o las posibles excepciones.
  2. La clase Program.cs es la clase principal que donde se ejecuta el servidor.

Para construir un servidor UDP se requieren de los siguientes pasos:

1) Crear una objeto UdpClient que al construirse sin argumentos se le asigna un número de puerto de la IP local.

    UdpClient udpClient = new UdpClient();

2) Construir un objeto IPEndpoint asociando una IP para este ejemplo utilice la dirección local y el número de puerto donde se conectara para enviar la respuesta (response) del servidor.

    IPEndPoint IPremoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"),serverPort);

3) Utilizar la clase Encoding para convertir el texto de la respuesta en un arreglo de bytes UTF8, y enviarla por la red con el método Send().

    byte[] data = Encoding.UTF8.GetBytes(response.ToString());
    udpClient.Send(data,data.Length,IPremoteEP);

Pasos para la construcción de un cliente UDP GTK#

El cliente UDP solicita un petición al número de puerto del servidor, recibiendo la respuesta como una matriz de bytes, la convierte a una cadena y la muestra en la pantalla.

El proyecto del cliente UDP GTK# se compone de 2 clientes:

  1. 1. La clase MainWindow.cs es la clase que construye la GUI del cliente, solicita los parámetros: numero de puerto y dirección IP para configurar la comunicación, maneja los eventos para recibir la respuesta del servidor y mostrar el resultado en pantalla o las posibles excepciones.
  2. 2. La clase Program.cs es la clase principal donde se ejecuta el cliente

Para construir un cliente UDP se requieren de los siguientes pasos:

1) Se crea un objeto UdpClient y se le especifica como parámetro el número de puerto al cual se enlazará.

    UdpClient client = new UdpClient(portToReceive);

2) Se crea el IPEndPoint para recibir la matriz de bytes con los parámetros IPAddress.Any (Indica que el servidor debe escuchar por clientes en todas las interfaces de red) y el número de puerto cero (para solicitar números de puertos dinámicos).

    IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);

3) Se obtiene el arreglo de bytes del IPEndPoint

    byte[] data = client.Receive(ref anyIP);

4) Se convierte el arreglo de bytes a una cadena

    text = Encoding.UTF8.GetString(data);

5) Una vez obtenido el mensaje se debe cerrar el Socket

    client.Close();

A continuación unas imágenes del cliente y del servidor comunicándose entre si.

Fig 6 Configurando el servidor de fecha y hora

Fig 7 Ejecutando el servidor de fecha y hora

Fig 8 Ejecutando el cliente GTK# Udp

Fig 9 Obteniendo la respuesta de servidor UDP

viernes, 9 de septiembre de 2016

Entendiendo la programación de Sockets con GTK# y .NET

¿Qué son los sockets?

Los Sockets o mejor dicho los Berkeley Sockets (BSD IPC) son la combinación exclusiva de una dirección IP y un numero de puerto TCP que habilita a los servicios (procesos en ejecución) de una computadora el poder intercambiar datos a través de la red. Los servicios de red utilizan los sockets para comunicarse entre los equipos remotos. Por ejemplo el siguiente comando:

        $ telnet 192.168.1.14 80
      

Este comando solicita una conexión desde un puerto aleatorio en el cliente (por ejemplo: 5643) al puerto 80 en el servidor (que es el puerto asignado para el servicio HTTP). Con la siguiente figura (fig 1) se ilustra a detalle este esquema denominado cliente-servidor.

Fig 1 Una comunicación utilizando números de puerto para transmitir datos.

Históricamente los sockets son una API (Application Programming Interface) de programación estándar utilizada para construir aplicaciones de red que vienen desde el sistema UNIX BSD. Esta interface de programación para la capa 4 del modelo OSI (OSI Model Layer 4) permite a un programador tratar una conexión de red como un flujo de bytes que puede escribirse o leerse sin demasiada complejidad. Con un socket se pueden realizar siete operaciones básicas:

  1. Conectarse a una máquina remota.
  2. Enviar datos.
  3. Recibir datos.
  4. Cerrar una conexión.
  5. Escuchar para los datos entrantes.
  6. Aceptar conexiones desde maquinas remotas en el puerto enlazado.
  7. Enlazarse a un puerto.

Los Sockets pueden ser orientados a la conexión (Stream Socket) o no (Message-based Socket).

Los Stream Sockets son ideales para transmitir grandes volúmenes de información de manera confiable. Una conexión Stream Socket se establece mediante el mecanismo three-hand shake de TCP, los datos se transmiten y cada paquete se revisa para asegurarse de la exactitud en la transmisión.

Los Datagram Sockets son apropiados para transferencias de datos cortas, rápidas y sin necesidad de un chequeo de errores. Los desarrolladores de aplicaciones los prefieren por ser rápidos y muy fáciles de programar.

Fig 2 Tipos de Socket

El Framework .NET posee las clases de alto y bajo nivel que encapsulan la funcionalidad de un Socket (tanto TCP como UDP) para construir aplicaciones de red con relativa facilidad y sin preocuparse por todo el intricado mecanismo de comunicación que necesitaría muchas líneas de código. La siguiente lista describe las clases principales:

  • NetworkStream: Una clase derivada de la clase Stream representa el flujo de datos de entrada o de salida desde la red.
  • TcpClient: Crea conexiones TCP de red para conectarse a un socket de servidor.
  • TcpListener: Se utiliza para escuchar peticiones de red TCP.
  • UdpClient: Crea conexiones UDP de red con posibilidad de multicasting.
  • Socket: Es una clase de bajo nivel que envuelve a la implementación winsock, las clases TcpClient, TcpListener y UDPClient utilizan esta clase para sus operaciones, se puede afirmar que la clase Socket tiene las operaciones de estas clases más otras funcionalidades mucho más avanzadas y de más bajo nivel.

Pasos para la construcción de un Servidor TCP GTK#

Un servidor TCP siempre está ejecutándose de forma continua hasta que recibe una solicitud de conexión por parte de un cliente, cuando se recibe esta solicitud, el servidor establece una conexión con el cliente y utiliza dicha conexión para el intercambio de datos. Si los programas se comunican a través de TCP los datos que se procesan se envían y se reciben como flujo de bytes.

Para demostrar estos conceptos escribí dos programas: el de un servidor y el de un cliente TCP. Ambos utilizan una interfaz de usuario (GUI) en GTK# para comunicarse entre ellos mediante mensajes de texto.

Fig 3 Ejemplo de un servidor TCP con una GUI GTK#.

Fig 4 Ejemplo de un cliente TCP con una GUI GTK#.

Pasos para la construcción de un Servidor TCP GTK#

El proyecto del servidor TCP GTK# se compone de 2 clases:

  1. La clase MainWindowServer.cs es la clase que construye la GUI del programa, maneja los eventos para enviar los mensajes al cliente y las excepciones o mensajes que el programa notifique.
  2. La clase Program.cs es la clase principal que donde se ejecuta el servidor.
Para construir el servidor TCP se requieren de los siguientes pasos:

1) Crear un objeto IPEndpoint que asocia una dirección IP y un número de puerto.

IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any,6000);

2) Crear un objeto TcpListener que reciba como argumento un objeto IPEndpoint. (Aquí el objeto TcpListener oculta la intricada programación de un Server Socket para una facilidad en la programación)

listener = new System.Net.Sockets.TcpListener(ipEndPoint); 

3) Iniciar el objeto TcpListener para que escuche las peticiones.

listener.Start();

4) Se utilizar un ciclo para que el Server Socket escuche o espere indefinidamente hasta recibir una petición, cuando el servidor recibe la petición crea una conexión hacia el cliente y regresa un objeto Socket del ensamblado System.Net.Sockets.Socket.

connection = listener.AcceptSocket();

5) Se obtiene el flujo de comunicación del Socket.

System.Net.Sockets.NetworkStream socketStream = 
new System.Net.Sockets.NetworkStream(connection);

6) Finalmente se asocia el flujo de comunicación del Server Socket con un escritor y un lector binario para transferir y recibir datos a través del flujo de comunicación.

using(writer = new BinaryWriter(socketStream))
{
using(BinaryReader reader = new BinaryReader(socketStream))
{
//the stream goes here 
}
}

Es muy importante que una vez que se finaliza la comunicación con el cliente cerrar el flujo y la conexión mediante con el método Close de cada uno de los objetos.

socketStream.Close();
connection.Close(); 

Pasos para la construcción de un cliente TCP GTK#

El proyecto del cliente TCP GTK# se compone de 2 clases:

  1. La clase MainWindow.cs es la clase que construye la GUI del cliente, maneja los eventos para recibir y enviar los mensajes al servidor, y mostrar las excepciones o mensajes que ocurran.
  2. La clase Program.cs es la clase principal del cliente

Para construir el cliente TCP se requieren de los siguientes pasos, algunos son idénticos a los que se escribieron para el servidor:

1) Crear un objeto IPEndpoint que asocia la dirección IP y el número de puerto del servidor, generalmente estos datos son fijos ya que los servidores se configuran para tenerlos de manera estática. (en este ejemplo utilice una sola máquina como servidor y como cliente)

  IPEndPoint localEndPoint = 
  new IPEndPoint(IPAddress.Loopback,6000);
  

2) Se crea un Socket de cliente y se conecta al puerto del servidor.

  client.Connect(localEndPoint);
  

3) Se obtiene el flujo de comunicación del Socket

  output = client.GetStream();
  

4) Se crean los objetos lector y escritor para trabajar con el flujo de comunicación.

   using(writer = new BinaryWriter(output))
   {
    using(reader = new BinaryReader(output))
    {
//the stream goes here 
    }
  }
  

Finalmente cuando se termina la comunicación con el servidor, se cierra el flujo de datos y la conexión con el método Close de cada objeto.

    output.Close();
    client.Close();
  

La clase TcpFlags

Ambos proyectos utilizan la clase TcpFlags, la cual pretende ilustrar básicamente como son las banderas TCP (aquí más detalles de las TCP Flags) que utiliza la capa de transporte (layer 4) para manejar la comunicación entre dos máquinas.

A continuación unas imágenes del cliente y servidor comunicándose entre si.
Fig 5 Enviando un mensaje desde el cliente al servidor.

Fig 6 Recibiendo el mensaje del cliente.

Fig 7 Enviándole un mensaje al cliente desde el servidor.

Fig 8 Desconectándose del servidor.

lunes, 8 de agosto de 2016

La navaja de Ockham o principio KISS en el desarrollo de software

La navaja de Ockham o el principio de parsimonia es el principio metodológico ideado por William of Ockham (1285-1347) filósofo nominalista que se utiliza para “cortar” o "rasurar" todo aquel conocimiento que no provenga de los datos de los sentidos, es decir invalidar los conceptos que no sean comprobables por la experiencia misma.

La formulación correcta de Ockham es:

No hay que multiplicar los entes sin necesidad (entia non sunt multiplicanda praeter necessitaem).

La navaja funciona de la siguiente manera: cuando se nos ofrecen dos o más hipótesis en igualdad de circunstancias para explicar un determinado fenómeno, es razonable aceptar la hipótesis más simple o sea la que incluye menos supuestos no probados.

En otros campos del conocimiento la navaja de Ockham se utiliza para eliminar objetos o tipos de objetos que no aportan o cambian en nada las particularidades efectivas de las cosas. En informática a la navaja de Ockham se le conoce como el principio KISS, siglas que significan:

Keep It Simple, Stupid! (Mantenlo simple, estúpido)

Aplicando el KISS al desarrollo de software tenemos que pequeño y sencillo es mejor que grande y complejo. En pocas palabras, entre más pequeño sea el número de componentes o de código involucrado en un proyecto menor será la cantidad de errores o problemas asociados al mantenimiento. Lo que incrementa la probabilidad de una entrega exitosa a tiempo.

Hay un principio de la filosofía UNIX que ejemplifica la aplicación de un principio KISS:

*“En lugar de tener pocos programas grandes, cada uno tratando de hacer muchas cosas, el sistema UNIX proporciona muchas herramientas simples que pueden combinarse para realizar un amplio rango de cosas.”
*Rosen Kenneth, Rosinki Richard, UNIX System V release 4. An introduction. Second Edition, Mc Graw Hill

Algunos ejemplos del KISS en el desarrollo de software son:

  • No intentes complicar el modelo de base de datos agregando entidades que nada aportan al negocio funcional. Solo agrega las entidades que requieren una persistencia.
  • No toda la persistencia necesita estar en una base de datos, hay ocasiones en que los archivos de texto plano son la mejor opción para el rendimiento.
  • No requieres un RDBMS para guardar una agenda de contactos.
  • No intentes optimizarlo si ni siquiera funciona o no esta terminado.
  • La complejidad de los algoritmos o el número de capas que se agreguen a una arquitectura son inútiles si estos no resuelven los requerimientos funcionales, y al serán ignorados por los usuarios finales.

Hay una frase que también es un claro ejemplo de este principio:

Premature optimization is the root of all evil. (la optimización prematura es la raíz de todos los males)

--Sir Charles Anthony Richard Hoare, inventor del algoritmo Quicksort.

Hay que aclarar que la navaja de Ockham no sostiene que la hipótesis más simple sea la correcta, sino sencillamente que es la que tiene más probabilidades de ser la correcta.

martes, 2 de agosto de 2016

Entendiendo TCP Control Flags (los bits de control TCP)

El protocolo TCP (Transport Control Protocol) proporciona la comunicación orientada a la conexión entre dos sistemas utilizando características tales como: Three-way handshake, reconocimientos, y números de secuencia. Adicionalmente a esas características TCP tiene 6 banderas de control (control flags) o bits de bandera que se usan para dominar la funcionalidad de las conexiones, los 6 bits que son utilizados durante el ciclo de la conexión son: Urgent (URG), Acknowledgment (ACK), Push (PSH), Reset (RST), Synchronize (SYN) y Finish (FIN).

La posición de cada uno de los bits es una bandera para indicar si una funcionalidad TCP está habilitada o deshabilitada, poniendo el valor del bit en 1 es ON, si es 0 significa OFF.

A continuación la descripción de cada uno de los bits por su correspondiente posición:

Urgent (URG): Se utiliza para notificarle a un sistema que el paquete tiene datos urgentes dentro del campo TCP que reconocen una actividad urgente o con prioridad, por ejemplo cuando un usuario presiona la combinación CTRL-BREAK, el resultado de este bit le indica a TCP que estos datos deben tomar precedencia sobre la transmisión de datos y enviarse inmediatamente.

Acknowledgment (ACK): El bit de reconocimiento se utiliza por uno de los sistemas para indicar el reconocimiento de un paquete TCP de otro sistema. Esto indica que hay un numero de reconocimiento en el campo de reconocimiento que se envía como respuesta a un petición SYNC.

Push (PSH): Este informa a TCP de entregar los datos inmediatamente hacia la capa superior sin almacenarlos en el buffer.

Reset (RST): Indica que una conexión TCP debe reiniciar la conexión, quizás debido a un error.

Synchronize (SYN): El bit de sincronización se utiliza para solicitar la conexión TCP con otro sistema. Una solicitud de conexión tiene SYN = 1 y ACK = 0.

Finish (FIN): Este bit se utiliza para terminar la conexión en un sistema, indica que el emisor no tiene más datos que enviar. La desconexión es simétrica.

Fig 1 TCP Header (la cabecera TCP).

Flags (UAPRSF)
  • U (1 = Urgent pointer valid)
  • A (1 = Acknowledgement field value valid)
  • P (1 = Push data)
  • R (1 = Reset connection)
  • S (1 = Synchronize sequence numbers)
  • F (1 = no more data; Finish connection)

sábado, 30 de julio de 2016

Entendiendo TCP Three-way Handshake

TCP (Transport Control Protocol) es un protocolo orientado a la conexión, lo que significa que establece la conexión, maneja el intercambio de datos y termina la conexión. Este protocolo establece una serie de pasos para establecer la conexión.

Para entender la programación con sockets TCP, es esencial conocer los pasos de la comunicación entre dos sistemas o mejor dicho entre un cliente y un servidor. A esta forma de establecer comunicación se le conoce como three-way handshake.

Fig 1 TCP Three-way handshake.

El proceso three-way handshake/call setup/virtual circuit setup es una única secuencia de tres paquetes de datos se intercambian al comienzo de una conexión TCP entre dos sistemas, la secuencia es la siguiente:

1-. En el primer paso del three-way handshake el cliente reserva un puerto para establecer la comunicación y envía un paquete SYN a la máquina objetivo que especifica la dirección IP, el puerto y un número de reconocimiento. El paquete SYNC tiene un número de secuencia (SEQ) asociado en este caso x. El número de secuencia es utilizado para rastrear los paquetes de datos que se transfieren entre el cliente y el servidor. La longitud del paquete enviado por el cliente tiene una longitud 0 (LENGTH = 0), esto indica que el paquete no tiene datos.

Fig 2 Primer paso: el paquete SYNC del cliente.

2-. En el segundo paso, el servidor responde con un paquete SYNC ACK, este paquete ACK es el reconocimiento que el servidor hace del paquete que recibió de parte del cliente. El número ACK adjuntado en el paquete tiene un valor del resultado de la suma de la secuencia (SEQ) del paquete 1 más la longitud del primer paquete. Aunque la longitud del paquete 1 es 0 este cuenta como un paquete por eso el ACK number = (cliente + 1). Este reconocimiento notifica al cliente que el paquete 1 fue recibido por el servidor. También el paquete SYN + ACK enviado por el servidor tiene un número de secuencia con valor y este número se utiliza para rastrear los paquetes enviados por el servidor.

Fig 3 Segundo paso: el paquete SYNC+ACK del server.

3-. El cliente reconoce la recepción del paquete del servidor. El número de ACK es un incremento del número de secuencia enviado por el servidor en el paso 2 o sea (y + 1), también el cliente también actualiza el número de secuencia que es la suma del número de secuencia que en el cliente envió en el primer paso más 1 o sea (x+1). Es importante recordar que cada uno, tanto el cliente y el servidor tienen su propio número de secuencia.

Fig 4 Tercer paso: el paquete ACK del cliente.

Una vez que el three-way handshake ha sido completado, se establece una comunicación bi-direccional sobre la conexión.

La importancia entre las aplicaciones basadas en TCP es que TCP soporta características tales como:

  • El re-ordenamiento de paquetes.
  • La repetición de los paquetes perdidos.
  • El reconocimiento de paquetes.
  • Un flujo de control.
Estas características son importantes para las aplicaciones basadas en mensajes.

La forma en que three-way handshake ayuda a sincronizar la conexión entre dos sistemas, emplea números de secuencia (SEQ) y reconocimiento (ACK) para indicar la transmisión de datos y la recepción. Las banderas (flags) de TCP controlan el flujo de sesión y es técnicamente de lo que se aprovechan los escaneadores de puertos por ejemplo. Son esas banderas las que se utilizan para recolectar información de los puertos.

Los números de puerto a diferencia de las direcciones IP no son únicos, aunque sean únicos para el sistema. Estos elementos forman los End Points entre sistemas. Mientras el sistema cliente utiliza números de puerto de manera aleatoria, los servidores en cambio utilizan números de puerto fijos, para facilitar la comunicación con varios sistemas. El RFC 1700 es un documento de consulta indispensable si se requiere información adicional acerca de los números de puerto asignados.

domingo, 24 de julio de 2016

Notas acerca de los riesgos en un proyecto de software

¿Qué es un riesgo?

No importa que tan bien se hagan los planes, siempre surgirán problemas inesperados. En ningún proyecto hay garantías, incluso la actividad más trivial conlleva problemas inesperados. En cualquier momento puede ocurrir algo que desvié el resultado de una actividad. Es un evento o condición incierta que, si se produce, tiene un efecto positivo o negativo en los objetivos del proyecto.

Factores de riesgo en un proyecto

  • Requerimientos excesivos
  • Falta de involucramiento del usuario o del cliente
  • Subestimación de la naturaleza dinámica o de la complejidad del proyecto
  • Costos o calendarios no realistas
  • Ineficiente administración de proyectos
  • Deficiencias en cada una etapas del ciclo de vida
  • Utilización de procesos o tecnologías inmaduras o no adecuadas para la medida del proyecto
  • Pobre capacitación

Algunos de los problemas que ocasionan los riesgos

  • Baja calidad en los productos de software
  • Retraso en el calendario
  • Perdidas en los costos
  • Moral baja

Características de un riesgo bien analizado

  • Tiene umbrales definidos claramente
  • La probabilidad e impacto estimados son realistas
  • Su plan de mitigación y de contingencias debe ser claro y efectivo
  • La responsabilidad de su monitoreo y control, está claramente asignada a uno o varios responsables

Existen los riesgos positivos

No todos los riesgos son negativos. Algunos eventos o condiciones pueden ser de ayuda para el proyecto por ejemplo: Alguna descuento en los costos de capacitación, encontrar un componente que ahorre tiempo de construcción, etc. Si esto sucede sin duda se le conocerá como una oportunidad, sin embargo desde la perspectiva de la administración de proyectos se le catalogará como riesgo.

Pasos para manejar un riesgo

    22
  • Evitarlo: Una de las mejores maneras para manejar un riesgo es evitarlo, si es posible hacer todo lo posible para que no suceda.
  • Mitigarlo: Si no es posible evitar el riesgo, deben tomarse acciones para disminuir los efectos que se originen cuando el riesgo se transforme en un problema.
  • Transferirlo: Buscar la ayuda de otra instancia que tenga la capacidad para mitigarlo o desaparecerlo.
  • Aceptarlo: Cuando no puede evitarse, mitigarse o transferirse deberá de aceptarse para no caer en la frustración y el desanimo.

lunes, 18 de julio de 2016

Entendiendo conceptos básicos de Threads con GTK#

Históricamente el soporte para las operaciones en paralelo u operaciones concurrentes en los lenguajes de programación no era común, la mayoría de lenguajes de programación proporcionaban dicho soporte como primitivas del sistema operativo que eran muy difíciles de programar y de mantener.

Fue hasta las décadas de los 70’s y 80’s del siglo XX que el departamento de defensa de los Estados Unidos construyo el lenguaje de programación Ada que entre sus capacidades permite a los programadores especificar la programación en paralelo.

Una de las técnicas mas populares para la programación concurrente son los hilos (Threads) esta técnica se basa en el principio de la multi-programación propia de los sistemas operativos modernos.

¿Qué es un Thread?

Un thread es la unidad básica de ejecución de un programa. En otras palabras, es la unidad más pequeña de ejecución para la cual un procesador reserva tiempo de procesador. Es otra forma de que varias actividades se ejecuten al mismo tiempo con el objetivo de paralelizar el código e incrementar el rendimiento de un programa, por eso a los threads se les conoce como procesos livianos (lightweight processes), ya que estos corren en paralelo como si fueran procesos aunque todos se ejecutan dentro de un mismo proceso que comparten recursos críticos tales como la memoria y el CPU. Un thread se compone de:

  • Un Thread ID similar al Process ID.
  • Un contador de programa.
  • Un conjunto de registros.
  • Una pila.

A diferencia de un proceso los hilos comparten recursos como la sección de datos, la sección de código, los descriptores de archivo o las señales entre otras.

Beneficios de la programación multithread

  • El Multithreading (multihilado) permite a un proceso ejecutar múltiples tareas en paralelo. A cada tarea se le otorga su propio hilo de control, lo que ofrece los siguientes beneficios:

  • Rendimiento: Porque todos los Threads se ejecutan dentro de un mismo proceso, el proceso no desperdicia recursos en hacer una copia de él mismo. Los costos de copiar procesos fork y de ejecutar threads varían según el sistema operativo, aun así los threads son menos consumidores de recursos.

  • Simplicidad: Los hilos son mucho más sencillos de programar y de mantener que los procesos.

  • Compartir la memoria global: Como los hilos se ejecutan en un mismo proceso, cada hilo comparte el mismo espacio de direcciones de la memoria global del proceso.

  • Portabilidad: Definitivamente los hilos son más portables que los procesos fork u otros mecanismos de programación concurrente.

  • Capacidad de respuesta: Es posible que un hilo se mantenga haciendo una actividad, por ejemplo de descarga de un archivo mientras que otro puede continuar con una actividad de E/S, aquí se puede programar un esquema basado en el bloqueo de un hilo a nivel individual.

Estados de un Thread, su ciclo vital

Todo hilo debe cumplir con un ciclo de vida, este ciclo de vida comienza con un Thread en el estado Unstarted (inactivo) que es cuando se inicia, el hilo permanecerá en ese estado hasta que se invoque su método Start (Inicia) y así pasar al estado Running (en ejecución) que es cuando el sistema operativo le asigna un procesador, cuando esta en ejecución el hilo ejecuta todas las actividades que están en su delegado ThreadStart hasta terminarlas, una vez terminadas estas actividades pasa al estado Stopped (detenido) ya en este estado termina su ciclo, aunque un hilo puede pasar a este estado sin terminar sus actividades si se invoca su método Abort (abortar).

Otros estados para un hilo son:

  1. Blocked (Bloqueado) cuando el hilo tiene problemas en operaciones de E/S en donde necesita esperar por un recurso disponible.
  2. WaitSleepJoin cuando se le pide al hilo que no se ejecute un determinado tiempo.
  3. Suspend en este estado el hilo se interrumpe hasta que alguien invoque a su método Resume para regresar a la ejecución; en estos estados los hilos no pueden utilizar un procesador así se encuentre uno disponible.

Como nota adicional los métodos Suspend y Resume se encuentran obsoletos por lo que esta funcionalidad se implementa con la clase Monitor.

Para demostrar los conceptos básicos como la creación, el arranque y paro de un Thread he escrito el siguiente código como un ejemplo de como se escribe la creación de uno y la invocación de sus métodos Start() y Abort() respectivamente.

El siguiente programa es una sencilla animación en GTK# que dibuja rectángulos con un color diferente cada determinado tiempo utilizando las clases de dibujo de los ensamblados System.Drawing y gtk-dotnet. Este programa tiene dos botones: play y stop. El botón play inicia la animación en tanto que el botón stop detiene la animación.

Fig 1 Programa GTK# de una animación con un Thread.

  • 1-. La clase program que es la clase inicial del programa que tiene al método Main(string[] args)
  • 2-. La clase MainWindow que contiene la interfaz gráfica del programa aquí se crea el Thread y se controla su comportamiento por medio de los botones.
  • 3-. La clase ColorBoxesCanvas que se encarga de dibujar las figuras de la animación.

Para escribir el ejemplo creamos un proyecto en Monodevelop, creamos las clases, escribimos el código en cada clase correspondiente y compilamos. La solución debe verse como en la siguiente imagen:

Fig 2 Los archivos de la solución en Monodevelop.

Una vez compilada la solución la ejecutamos como se verá como en la siguiente imagen:

Fig 3 El programa al iniciar de su ejecución.


El programa muestra dos botones: play y stop, al oprimir el botón play se ejecuta el método Run()

 protected void Run(object sender,System.EventArgs e)
  {
   worker = new Thread(canvas.Repaint);
   canvas.KeepRunning = true;
   worker.Start();
   controlButtons[0].Visible = false;
   controlButtons[1].Visible = true;
   lblStatusBar.Text = "Running thread ID: " + Thread.CurrentThread.ManagedThreadId
    + " at " + DateTime.Now.ToLongTimeString();
  }

Dentro de este método se crea un objeto Thread llamado worker al que se le pasa el delegado canvas.Repaint como argumento al constructor del objeto. Este delegado especifica la acción que realizará el subproceso durante su ciclo de vida, para este ejemplo el delegado es un método void que no recibe argumentos. Aquí el hilo permanece en estado Unstarted hasta que se llama a su método Start(), ejecutando este método el hilo pasa al estado Running y devuelve el control del programa al proceso que invoco al método Start().

Fig 4 El programa al presionar el botón play y llamar al método Start().

Una vez en estado running el Thread puede pasar al estado Stopped o Aborted cuando termina la ejecución del delegado ThreadStart, esto indica que el subproceso terminado la tarea. Un hilo en ejecución puede forzar entrar al estado Stopped cuando se invoca al método Abort(), después de invocar este método el subproceso se detiene.

 protected void Abort(object sender, System.EventArgs e)
  {
   if (worker.IsAlive)
   {
    worker.Abort();
    controlButtons[0].Visible = true;
    controlButtons[1].Visible = false;
   }
   lblStatusBar.Text = "Stopping thread ID: " + Thread.CurrentThread.ManagedThreadId
    + " at " + DateTime.Now.ToLongTimeString();
  }
Fig 5 El programa al presionar el botón stop y llamar al método Abort()

jueves, 30 de junio de 2016

Q&A Preguntas y respuestas acerca de la administración del sistema UNIX

¿Cuál es la función del administrador de un sistema UNIX?

El administrador de un sistema UNIX es el responsable de configurar y mantener el sistema funcionando correctamente.

¿Qué debe entender el administrador de un sistema para realizar sus responsabilidades adecuadamente?

Entender el hardware y el software del sistema, así como (y esto es lo más importante) las necesidades de los usuarios.

¿Cuales son las responsabilidades de un administrador de sistemas UNIX?

Responsabilidad del Hardware, Software y hacia los usuarios.

Además del conocimiento en Hardware y Software ¿qué otras habilidades son necesarias para un buen administrador de sistemas UNIX?

El conocimiento de un lenguaje de programación Scripting.

¿Cuales son los campos del archivo /etc/password?

  1. user name
  2. encrypted password
  3. user id
  4. group id
  5. comment field
  6. login directory
  7. startup program

¿Cuales son los campos del archivo /etc/group?

  1. group name
  2. password
  3. group id
  4. group list

¿Cuál es la diferencia entre el archivo /etc/profile y .profile?

¿Para qué sirve el comando wall?

¿Para qué sirve el archivo /etc/motd.?

¿Para qué sirve el comando dmesg?

¿Cuál es la diferencia entre un archivo de bloque (block) y un archivo de caracteres (character)?

¿Qué es un archivo de dispositivo?

¿Para qué sirve el comando ln?

¿Cómo se controla el run-level (niveles de arranque) de un sistema UNIX?

¿Cuál es el propósito del archivo /etc/inittab ?

¿Cómo se obtiene el actual run-level del sistema?

¿Cuál es la diferencia entre apagar el sistema con shutdown -h o con reboot -halt?

¿Para qué sirve el comando fsck?

¿Para qué sirve el archivo /etc/fstab?

¿Qué es el root access (ingresar como superusuario)?

¿Cuál e s la diferencia entre memoria física y memoria virtual?

¿Para que sirven los comandos pwck y grpck?

miércoles, 29 de junio de 2016

¿Qué son los Internet Standards: RFCs?

Para saber más acerca de una parte fundamental de Internet como lo es la familia de protocolos TCP/IP existen documentos que explican a detalle las funcionalidades de cada uno de ellos. Estos documentos se conocen como RFCs (Requests For Comments).

Los RFCs son una colección de borradores y textos que abarcan desde documentos de interés general hasta detalladas especificaciones de los protocolos estándares como HTTP, FTP o NNTP, etc. Para que un documento propuesto sea publicado como una especificación estándar necesita ser aprobado por e l IESG (Internet Engineering Steering Group https://www.ietf.org/iesg/) del IETF (Internet Engineering Task Force https://www.ietf.org/). Una cosa importante: todos los estándares de Internet son RFCs pero no todos los RFCs son estándares.

¿Cómo se desarrolla un estándar RFC?

Todos los estándares RFCs propuestos comienzan cuando una persona o un grupo tiene una propuesta y construye un prototipo. Si este prototipo funciona y se vuele popular más allá del grupo que lo desarrolló. La IETF forma un grupo de evaluación de la propuesta para documentar el protocolo en un borrador de Internet (Internet Draft) este borrador es modificado frecuentemente hasta que la propuesta llegue a una madurez técnica aceptable.

El proceso de creación de un RFC no es rápido, ya que el proceso es rígido y normalizado por lo que se tienen demoras considerables. Este proceso es delicado, ya que la IETF debe moldear la especificación para que funcione en Internet sin tener conflicto con los protocolos que ya están funcionando.

Claro que en este proceso hay excepciones, como por ejemplo: el protocolo HTTP que en 1996 no había alcanzado el status experimental pero como al IESG le gusto tanto que le asignó de inmediato un número RFC y lo publicó como un RFC experimental después de algunos cambios.

Existen también aspectos jurídicos que es necesario considerar. Muchos borradores contienen algoritmos y tecnologías que podrían tener una patente o una protección de copyright. El proceso para convertir un borrador en un RFC consta de los siguientes pasos:

1-. Diseñar y organizar el borrador.

Cualquiera puede redactar una propuesta y enviarla para un análisis. En ocasiones puede ser una empresa que envía un documento que se convierte en borrador para volverse un RFC, pero son los grupos de trabajo de la IETF los que inician la mayoría de borradores.

2-. Analizar el borrador.

El IESG analiza el borrador presentado para decidir si merece un análisis técnico. En algunos casos, el EISG crea un grupo técnico para analizar el documento por si el estándar propuesto pudiera afectar el funcionamiento de Internet. Este grupo analiza técnicamente el borrador y evaluá sus efectos sobre la configuración de Internet ya establecida.

3-. Publicar el borrador.

Una vez concedida la aprobación inicial, el IESG autoriza la publicación del documento como estándar propuesto para toda la comunidad. Los borradores tienen una validez de seis meses. Durante este periodo el grupo puede modificar, reemplazar o incluso eliminar el borrador ya que los borradores carecen de status oficial.

4-. Revisar el borrador.

A medida que la gente estudia y comenta el borrador su contenido se modifica. En este periodo, el IESG y la comunidad de Internet evaluá los cambios y el impacto de la propuesta. Si los efectos son muy drásticos entonces el IESG podría ampliar el periodo de evaluación o bien devolverlo al principio del proceso de evaluación de estándares. Estas idas y vueltas provocan que algunos documentos tarden años o meses de retraso para recorren el proceso RFC.

5-. Conseguir la aceptación del borrador

Una vez que el borrador paso el periodo de análisis y si la IETF decide aprobar el borrador entonces este se convierte en un RFC. La RFC se dirige al editor del RFC y con autorización de la ISOC (Internet Society http://www.internetsociety.org/) para que el editor del RFC publique las RFC y es el responsable del último análisis de los documentos. Una vez aceptado se le asigna un número de STD y se convierte en un RFC STD. Cuando se publica una nueva versión de un RFC, la anterior recibe la categoría de Obsolete.

El éxito de un RFC dependerá que tan bien ese estándar funcione en la presencia de vendedores, inversores capitalistas y entusiastas que buscan tecnologías particulares para sus proyectos.

Además del proceso de desarrollo, un RFC tiene un requerimiento de nivel. Los posibles requerimientos de nivel son:

Required: los RFCs de esta categoría deben estar en todas las máquinas de Internet. Hay muy pocos protocolos en esta categoría. IP (RFC 791) por ejemplo es uno, incluso protocolos importantes como TCP o UDP están en la categoría recommend. Los protocolos que están en categoría son axiales para el funcionamiento de las máquinas en Internet.

Recommended: estos RFCs deben ser implementados por todos los los hosts de Internet que no tengan una razón para no implementarlo. RFCs por ejemplo: como TCP,UDP ,SMTP, Telnet, etc. Están en esta categoría.

Elective: estos RFCs pueden estar implementados por decisión propia para quien desee usar el protocolo. Por ejemplo: el del protocolo MIME ( RFC 1521) tiene este estatus.

Limited Use: estos RFCs deberían ser implementados en ciertas situaciones especiales, que no es indispensable para la mayoría de hosts.

Not recommended: los RFCs de esta categoría no deben ser utilizados por nadie.

Historic: un status para identificar RFCs que están clasificados como obsoletos.

Informational: en esta categoría hay dos grupos de RFC: El primer grupo define protocolos que están ampliamente utilizados pero no fueron desarrollados dentro del conjunto normal de pasos de un estándar de Internet y no han estado dentro del proceso formal de estandarización. Un buen ejemplo de esto es el Network File System (NFS) de Sun que está descrito en el RFC 1813. El segundo grupo de RFCs proporciona información como manuales de usuario pero no documenta un protocolo.

Enlaces:

domingo, 29 de mayo de 2016

¿Qué es el análisis postmortem en un proyecto de software?

En el contexto de los proyectos de desarrollo de software, un análisis Postmortem es el proceso de revisar la historia del proyecto para entender cómo cada uno de los eventos contribuyo al éxito o fracaso del proyecto.

En resumen: es el análisis retrospectivo realizado por todos los miembros del equipo de trabajo una vez que el proyecto concluye, sea exitosa o no esta conclusión.

Al realizar este análisis se busca identificar los aspectos positivos aplicados en el proyecto para que puedan repetirse, así como plantear soluciones y mejoras de los aspectos negativos, asimilando la experiencia para que no vuelvan a repetirse. Todo ello se conoce de forma simple como Lecciones Aprendidas.

Beneficios

Realizar un análisis de las experiencias buenas y malas adquiridas en el proyecto, es necesario para:

  • Identificar los aspectos que pueden mejorarse en proyectos futuros.
  • Obtener las experiencias de todos los involucrados en el proyecto, concentrando opiniones , puntos de vista y generando conclusiones en grupo.
  • Formar una base de conocimientos de “Lecciones Aprendidas” para que sean conocidas, revisadas y consideradas en otros proyectos con características similares.
  • Si hay un proyecto nuevo los recursos nuevos que tengan acceso a las lecciones aprendidas no tendrán justificación para repetir los mismos errores que se cometieron en sus proyectos anteriores.
  • Aplicar las lecciones aprendidas al proceso de estimación de un proyecto de software proporciona un par de beneficios, en principio, ayuda a la organización a prevenir desarrollar proyectos que no generan ganancias. Segundo, se orilla a que la estimación sea más precisa y exacta ya que la organización podría emplear un presupuesto inflado. Cuando la organización tiene confianza en sus estimaciones, es una organización más competitiva.

Actividades

  1. Aplicar cuestionario Postmortem.
  2. Realizar la reunión Postmortem.
  3. Registrar lecciones aprendidas.

Aplicar cuestionario Postmortem esta actividad se realiza para obtener las experiencias de los recursos que participan en algún momento en el proyecto y que por algún motivo salen antes de que este concluya. En la ejecución de esta actividad participan: el responsable del proyecto quien se asegura de que todos los recursos que salen antes de que el proyecto concluya, apliquen el cuestionario y el miembro del equipo de trabajo que sale del proyecto se requiere que conteste el cuestionario. Los cuestionarios que se recopilen serán revisados por el responsable del proyecto para concentrar las experiencias obtenidas y resumirlas en la presentación Postmortem.

Realizar la reunión postmortem Los datos del proyecto que deben considerarse en esta presentación, son:

  • Datos generales del proyecto
  • Evaluación del alcance
  • Evaluación de la planeación
  • Evaluación de la capacitación
  • Evaluación de la calidad
  • Evaluación del proceso
  • Oportunidades y conocimientos adquiridos
  • Evaluación de la percepción del cliente

Registrar lecciones aprendidas: aquí se obtiene un resumen de las lecciones identificadas por todos los miembros del equipo de trabajo para clasificarlas y registrarlas en el repositorio de lecciones aprendidas de la organización.Registrar lecciones aprendidas: aquí se obtiene un resumen de las lecciones identificadas por todos los miembros del equipo de trabajo para clasificarlas y registrarlas en el repositorio de lecciones aprendidas de la organización.

Consideraciones

Al ejecutar esta actividad es muy importante tomar en cuenta los siguientes aspectos:

  • Planear las actividades necesarias para ejecutar el proceso postmortem en todos los proyectos.
  • La reunión postmortem debe ejecutarse inmediatamente al concluir el proyecto.
  • Es necesario contar con las aportaciones de todos los recursos que en algún momento se vieron involucrados en el proyecto.
  • Deben exponerse los aspectos positivos y negativos registrados en el proyecto.
  • Calificar al proyecto, no a las personas.
  • Realizar recomendaciones que complementen las lecciones aprendidas.
  • Los datos obtenidos en la presentación postmortem son utilizados en la presentación de cierre del proyecto.

Cuestionario Postmortem

La recopilación de las experiencias adquiridas por todos los recursos que participaron en algún momento en el proyecto se realiza a partir de la aplicación del cuestionario Postmortem en el caso de los recursos que participaron hasta el cierre del proyecto. A continuación un ejemplo de las secciones de un cuestionario Postmortem

1.Datos generales

[Aquí describe tu participación dentro del proyecto]

  1. Nombre completo:
  2. Rol:
  3. Periodo de participación: [Total o parcial, especifique el periodo en el que permaneció en el proyecto, este será total si participo en todas las fases del proyecto, será parcial si solo participo en una fase del proyecto]
  4. Jefe inmediato/ Rol:[Especifique el nombre del jefe inmediato y su participación]

2. Evaluación de la planeación

[Sección dedicada a describir la percepción respecto a la planeación de actividades en el proyecto, poner las razones en cada respuesta]

  1. ¿Existieron diferencias entre el número planeado de artefactos/productos contra el real?
  2. ¿Se presentó alguna diferencia entre el tiempo planeado contra el real?
  3. ¿Existe alguna diferencia entre las disciplinas en las que se tiene planeada tu participación y en las que realmente participaste?

3. Evaluación de la Capacitación

[Aquí se pone la percepción respecto a las actividades de entendimiento del negocio]

  1. ¿Recibiste la capacitación técnica necesaria para realizar tus funciones?
  2. ¿Consideras que recibiste la capacitación necesaria del conocimiento del negocio de acuerdo a tu perfil?

4. Evaluación de la calidad

[Aquí indica los productos que fueron generados durante el proyecto, pudiendo ser documentos, código, modelos o diagramas]

5. Evaluación del Proceso

[Sección dedicada a evaluar el proceso de desarrollo de software] En un proyecto similar, qué acciones, actitudes y decisiones tendrían que ser diferentes y cuáles podrían repetirse en cuanto a:

  1. La capacitación para el proyecto.
  2. Las disciplinas ejecutadas en el proyecto.
  3. Las herramientas utilizadas para el proyecto.
  4. La infraestructura con la que contó el proyecto.
  5. La administración del proyecto.

NOTA: Hay que tener en cuenta que los cuestionarios Postmortem pueden variar de acuerdo a la organización o a la metodología que se utilice.

martes, 24 de mayo de 2016

Cómo utilizar el control Kendo UI NumericTextBox

El control Kendo UI NumericTextBox está diseñado para dar formato numérico y limitar los datos de entrada de los controles INPUT únicamente a los rangos que se especifiquen según sea especificado en la configuración del control.

Entre los formatos que este control puede manejar se encuentran las siguientes:

  • Monedas
  • Porcentaje
  • Números enteros
  • Números con precisión

Además si se utiliza el control con la sentencia kendo.culture este control puede dar formato de acuerdo al lenguaje y a las propiedades especificas de cada región o cultura.

Bien ahora mostraré un código en donde se verán todas las propiedades de este control, en este ejemplo se muestran 6 controles Kendo NumericTextBox, 4 de ellos configurado para mostrar cantidades monetarias, 1 de ellos configurado para mostrar cantidades enteras y el último para mostrar una cantidad porcentual.

Fig 1 La ejecución de la página con 6 controles NumericTextBox.

Introduciendo los valores, observamos como los controles le dan formato numérico a las entradas de datos.

Fig 2 Primer ejemplo: Introduciendo las cantidades numéricas.

Fig 3 Completando las entradas numéricas del primer ejemplo.

Fig 4 Un segundo ejemplo, introduciendo las cantidades numéricas.

Fig 5 Un segundo ejemplo, completando las entradas numéricas.

Como primer paso hago la iniciación de los controles, con la sintaxis:

Aquí algunas de las propiedades que utilizo en los controles de este ejemplo:

  • format: Especifica el tipo de formato que se usará en la cantidad numérica. Su valor predeterminado es numérico “n”.
  • spinners: Con esta propiedad se muestran las flechas de incremento/decremento del control.

Algunos de los eventos que utilizo:

  • change: Este evento se ejecuta cuando el valor del control se cambia.

martes, 10 de mayo de 2016

Utilizando el bloque try/catch en SQL Server para manejar errores

Desde la versión 2005 de Sql Server se incorpora el bloque try/catch para el manejo de errores en el código T-SQL, esta característica similar a la que tienen los lenguajes .NET consiste de dos partes:


BEGIN TRY
 --Sentencias T-SQL de funcionalidad
END TRY

y el bloque CATCH
BEGIN CATCH
 --Sentencias T-SQL para el manejo de error
END CATCH

Cuando se genera un error dentro del bloque TRY, inmediatamente el flujo del programa continua en el bloque CATCH donde el error se procesa de diferentes maneras, sino se genera un error el flujo se salta el bloque CATCH y continua hasta terminar el programa.

Dentro del bloque CATCH puedes utilizar las siguientes funciones del sistema para obtener información del error.

  • ERROR_LINE() - El número de línea que causo el error o donde se ejecutó la orden RAISERROR.
  • ERROR_MESSAGE() - Un texto resumen que indica la naturaleza de error.
  • ERROR_SEVERITY() - Regresa la severidad del error.
  • ERROR_STATE() - Regresa un valor entero que regresa NULL si se ejecutó afuera de un bloque CATCH.
  • ERROR_NUMBER() - Regresa el número de error que causo el error. Esta función regresa el número de error cuando se ejecuta adentro de un bloque CATCH, sino se ejecuta dentro un bloque CATCH regresa NULL.
  • ERROR_PROCEDURE() - regresa el nombre del store procedure o trigger donde ocurrió el error.
  • ERROR_PROCEDURE() - Regresa NULL si el error no ocurre dentro de un STORE PROCEDURE, si se ejecuta dentro de un STORE PROCEDURE o TRIGGER regresa entonces el nombre del STORE PROCEDURE o TRIGGER.

Una de las recomendaciones para la utilización del bloque TRY/CATCH es poner una sentencia ROLLBACK TRANSACTION en el bloque CATCH para que en caso de transacciones parciales se conserve la integridad de la información.

Bien a continuación un ejemplo de como programar un bloque TRY/CATCH en T-SQL:

Cuando se ejecuta este código con el número 25 positivo el programa se ejecuta correctamente y no generará una excepción :

Fig 1 Ejecutándose con un número positivo no genera excepción.

En cambio si se ejecuta con un entero negativo se lanzará una excepción que el bloque CATCH procesará correctamente.

Fig 2 Ejecutándose con un numero negativo genera excepción.

Consultando el catalogo sys.messages

Se puede consultar el catalogo sys.messages para ver la lista completa de números de error y sus correspondientes mensajes con la siguiente sentencia:

SELECT *FROM sys.messages ORDER BY message_id
Fig 3 Consultando el catalogo sys.messages para ver la lista completa de errores y mensajes.

miércoles, 4 de mayo de 2016

Entendiendo los arreglos en C#

Una de las estructuras de datos básicas en C# son los arreglos, los arreglos son estructuras que contienen elementos del mismo tipo relacionados y de longitud fija. Estas estructuras conservan la misma longitud una vez que se crean; pero esto puede cambiar si a la variable asignada se le asigna un nuevo arreglo con una longitud diferente, a continuación muestro unos ejemplos de como declarar un arreglo:

      int[] array= new int[6];
      int[] array2= {0,1,2,3,4,5};
      var array3 = new int[6]{0,1,2,3,4,5}; 
    

Los elementos de un arreglo pueden ser primitivos, objetos u otros arreglos. Aqui algunos ejemplos: un arreglo con primitivos, objetos y arreglos.

      string[] array4 = new string[6];

            Point[] array5 = new Point[6];

            int[][] jaggedArray = {
                new int[] {0,1},
                new int[] {2,3,4},
                new int[] {5,6}
            }; 
    

Para identificar a un elemento dentro de un arreglo se utiliza la posición del elemento dentro del arreglo, a esta posición se le conoce como el índice del elemento. Es importante recordar que para el primer elemento de cualquier arreglo su índice es zero y que el índice siempre es un entero no negativo.

Cuando se crea un arreglo y a sus elementos no se les proporciona un valor predeterminado entonces cada elemento se crea con su valor predeterminado: 0 para los elementos numéricos, false para los boolean y null para las referencias. La longitud de un arreglo se obtiene con la propiedad Length. Los elementos de un arreglo pueden recorrerse utilizando una iteración for utilizando un indice o bien con una instrucción foreach, la instrucción foreach itera entre los elementos desde el índice 0 hasta el final del arreglo. La instrucción foreach se recomienda para el recorrido de arreglos de solo lectura sin alteración del valor de los elementos, en operaciones donde no se requiere utilizar el indice o bien para los arreglos de tipo objetos.

El siguiente programa con el algoritmo Bubblesort muestra con más claridad las propiedades de los arreglos:

Al ejecutar este programa se mostrará el siguiente resultado:

jueves, 14 de abril de 2016

Libros de programación en JavaScript

Libros de programación en JavaScript para descargar, consultar en línea o con un precio accesible.

Para ver el catálogo completo a este enlace jsbooks.revolunet.com

viernes, 18 de marzo de 2016

Entendiendo kendo UI DataSource de Telerik con JavaScript

El control DataSource es uno de los componentes centrales en la suite de controles Kendo UI de Telerik ya que es el componente que proporciona el acceso a fuentes de datos para el resto de los controles de la suite, entre las fuentes de datos que soporta el control se encuentran los formatos JSON, XML y Odata, estas fuentes de datos pueden estar de forma local o remota respectivamente.

Uno de los controles que más se complementa de la funcionalidad del DataSource es sin duda el control Grid, ya que no solo obtiene los datos del DataSource, sino que además el comportamiento del Grid se ve influido por la configuración que el DataSource le proporcione.

A continuación enumeraré las opciones para la configuración del DataSource que utilicé en este ejemplo:

Transport Esta opción describe la configuración del endpoint en donde se encuentran los datos se configuran opciones como: URL, HTTP Verb, Data Type, etc.
Transport.Read Se utiliza cuando se van a solicitar los datos desde una ubicación remota como un web service o server.
PageSize El número de registros por página.
Schema El diseño lógico de los datos.
Schema. Data Se establece la estructura que contiene los datos recibida como respuesta desde un servidor remoto.
Schema.Total El número total de registros que contiene la estructura de datos recibida como respuesta desde un servidor remoto.

En el siguiente programa de ejemplo, utilizo la propiedad transport del DataSource para obtener el archivo authors.txt que se encuentra en el URL: “http://127.0.0.1/~martin/SamplesKendo/authors.txt” (este archivo se encuentra en un Apache Web Server), y los datos contenidos están en formato JSON como se muestra a continuación:

Fig 1 El archivo authors.json.

Una vez teniendo el archivo de datos, la configuración del DataSource queda como en el siguiente código JavaScript

Esa es la parte JavaScript que tiene la funcionalidad, a continuación el código de la página HTML completa.

Al ejecutar el código se produce el siguiente resultado:

Fig 2 Databinding con el control DataSource.

Fig 3 Paging con DataSource y Grid.

Fig 4 Last record con DataSource y Grid.

lunes, 22 de febrero de 2016

Utilizando el comando netstat en Linux

netstat muestra el status y la información de las conexiones de red de varios tipos y ver que puertos TCP y UDP esta escuchando la computadora, utilizar el comando netstat con las opciones -lut.

      $netstat -lut
    
Fig 1 netstat con la opción -lut.

Ahora si se quiere ver rápidamente el status de las interfaces:

      $netstat -i 
    
Fig 2 netstat con la opción -i.

Aquí pongo la tabla que describe el significado de cada columna:

Columna Significado
Iface Nombre de la interface
MTU Maximum Transfer Unit – El máximo número de bytes que un paquete puede contener
RX-OK, TX-OK Número de paquetes libres de errores: recibidos (RX) o transmitidos (TX).
RX-ERR, TX-ERR Número de paquetes del errores
RX-DRP, TX-DRP Número de paquetes descartados
RX-OVR,TX-OVR Número de paquetes perdidos debidos a un overflow.
FLG A = multicast recibido, B = broadcast permitido, D= depuración encendida, L = loopback interface (notice the flag en lo), M = todos los paquetes recibidos, N= tramas evitadas, 0 = no ARP en esta interface, P = punto a punto interface, R = interfaz esta corriendo, U = interfaz está arriba.

Otra forma muy útil para revisar que de donde vienen las conexiones es:

      $ netstat -tupn
    
Fig 3 La salida de netstat con la opción -tupn.

Aquí una lista de cada uno de los párametros más comunes en el uso de netstat
-t --tcp Muestra las conexiones socket TCP
-u --udp Muestra las conexiones socket UDP
-p --program Muestra el PID y el nombre de los programas al que los sockets pertenecen
-n --numeric Muestra la dirección IP numérica en vez de determinar el host y el puerto.

jueves, 4 de febrero de 2016

Entiendo Angular: Un primer acercamiento

AngularJS es un framework open source escrito en JavaScript que sirve para implantar el patrón MVC del lado del cliente, lo que permite que puedan contruirse aplicaciones Web del tipo AJAX, por su poder expresivo se utiliza en la mayoría de proyectos SPA (Single Page Application).

Qué es SPA?

SPA (Single page Application) es una aplicación en la cual se tiene una página principal como contenedor y varias vistas contenidas dentro este contenedor que pueden refrescarse independientemente de la página principal evitando así hacer una petición de toda la página completa, lo que ayuda a hacer eficiente el ancho de banda sobretodo en aplicaciones móviles.

Las ventajas de Angular son:

  • Proporciona la capacidad de crear SPA de una manera clara y mantenible
  • Le proporciona una capacidad de data binding al HTML, lo que proporciona una experiencia responsiva al usuario.
  • El código hecho con Angular se puede probar mediante pruebas unitarias (Unit Testing)
  • Utiliza la inyección de dependencias para la separación de responsabilidades.
  • Proporciona componentes reutilizables ya que las vistas son páginas HTML y la lógica de procesamiento se lleva a cabo por los controllers (controladores) escritos en JavaScript.
  • Angular es compatible entre la mayoría de las plataformas (Android, IOS) y navegadores.
  • Puede combinarse con otras bibliotecas para JavaScript por ejemplo: Kendo UI y Jquery.

Hay dos conceptos básicos para empezar con Angular, uno es el $scope y el otro es la utilización de directives (directivas), para ejemplificar su uso, mostraré una página que despliega un lista de filósofos de cada país la cual es posible filtrar al escribir el nombre en un control INPUT.

¿Qué es el scope?

Una buena separación de aspectos no permite que la lógica de negocio se mezcle con la vista, así que todo el procesamiento se realiza mediante el controlador el cuál es el que enlaza los datos hacia la vista. Una parte integral para trabajar con angular es el llamado scope que en realidad es un alias para el ViewModel es decir el componente que permite que se comuniquen la vista y el controlador.

Aquí el código fuente del archivo MenuAngular.js el cuál contiene el JSON y la declaración del controller.

Aquí el código fuente de la página HTML:

¿Qué son las directives?

Son atributos HTML que llaman funciones pertenecientes al framework para extender de manera dinámica la funcionalidad del elemento HTML al cual pertenecen, esta es la manera básica de crear elementos HTML específicos para la aplicación, encapsular estructuras DOM complejas o manipular las hojas de estilo.

A continuación una breve descripción de las directivas que se utilizaron en el ejemplo:

  • ng-app: Esta directiva sirve para incluir e iniciar AngularJS y que se pueda utilizar en un página HTML. Generalmente esta directiva va en la etiqueta BODY o en HTML.
              <!doctype html>
    <html ng-app="App">
            
  • ng-controller: Esta directiva indica que controlador se va a utilizar en esa página o vista. Angular nos permite tener múltiples instancias de el mismo controlador en la aplicación, permitiéndonos reutilizar un montón de código.
        <body ng-controller="SimpleCtrl">      
            
  • ng-repeat: Con esta directiva se puede enumerar o iterar en una lista de objetos similar a recorrer un de un arreglo con la instrucción foreach de algunos lenguajes de programación. Adicionalmente a esta directiva le agrego la directiva filter:Name la cuál establece el filtro de búsqueda dentro del arreglo, en este caso el filtro es el valor de la variable enlazada con ng-model.
              <ul>
                        <li ng-repeat="menu in menus">{{menu.Name}}
                        <ul ng-repeat="submenu in menu.Children | filter:Name">
                            <li>{{ submenu.Name }}</li>
                        </ul>
                        </li>
                    </ul>
            
  • ng-model: Esta directiva sirva para enlazar el valor de una variable a un control HTML, generalmente se utiliza con los controles INPUT.
              <td><label for="inputSearch" class="control-label">Search:</label></td>
                    <td><input type="text" id="inputSearch" class="field-value" ng-model="Name"/></td>
            

Las siguientes imágenes muestran la página en su ejecución.
Fig 1 La página HTML en ejecución.

Fig 2 Ejemplo de una búsqueda con una coincidencia.

Fig 3 Una búsqueda con dos coincidencias.

sábado, 9 de enero de 2016

Utilizando NLog con MonoDevelop en .NET

Para cualquier aplicación de software a nivel producción es indispensable tener un componente que escriba los eventos más significativos en una bitácora. Esta acción que se conoce como logging (escribir en la bitácora) se define técnicamente como:

“Una forma sistemática y controlada para obtener el estado de una aplicación en tiempo de ejecución.”

Pensando en esto, los diseñadores de .NET incorporaron un mecanismo de logging de forma predeterminada dentro del ensamblado System.Diagnostics, en clases como Trace, TraceListener, Swicth y todas sus clases derivadas. Aunque el empleo de estas clases es efectivo, no deja de ser rudimentario y carecer de muchas funcionalidades que terminan siendo un límite.

Teniendo en cuenta esto, en el ecosistema .NET han surgido a lo largo de los años una cantidad de componentes propietarios y opensource para el logging de aplicaciones. Dentro de ese conjunto hay un componente que se destacado y es del que trataré de resumir en este tutorial: Nlog.

¿Qué es NLog?

Nlog (http://nlog-project.org/) es un componente open source de logging para .NET, que entre sus características se encuentran:

  • Muy fácil de configurar.
  • Extremadamente personalizable con plantilla (layouts)
  • Altamente extensible

Hay tres características que se deben conocer antes de empezar su utilización:

  1. Targets: Se utilizan para enviar los mensajes hacia otro destino, entiéndase aquí un archivo, una base de datos, un email, la consola, un webservice, etc.
  2. Layouts: Con los comandos de layout podemos definir la estructura o el molde de como acomodar la información escrita en un determinado target.
  3. Levels: Es una forma de asignar una prioridad al mensaje, los niveles permitidos son los siguientes:
    1. Fatal: Sucedió algo que causo que el todo el sistema entero falle, se debe detener la ejecución.
    2. Error: Un problema ha ocurrido pero no es fatal, el sistema puede seguir funcionando.
    3. Warn: Un problema ha ocurrido, pero puede ser recuperable.
    4. Info: Mensajes de información muy útiles como cambios de estado, login/logout, etc.
    5. Debug: Se utiliza durante el desarrollo del sistema.
    6. Trace: Para indicar el inicio y final de una rutina.

Como un primer acercamiento a su utilización, escribí una aplicación de consola en C# que solicita una cadena de conexión, con esta cadena trata de conectase a una base de datos PostgreSQL, si la cadena de conexión no es correcta se utiliza Nlog para enviar la excepción a consola, si logra conectarse solicita una consulta SELECT para ejecutar y mostrar los resultados en la consola. Aquí de nuevo si ocurre una excepción utiliza Nlog para notificarla.

1-. Ejecutar Monodevelop y seleccionar un proyecto de consola y nombrarlo como HelloNlog

Fig. 1 crear un proyecto llamado HelloNlog

2-. Dentro del Solution Explorer has click con el botón derecho y has click en Add Packages , entonces aparecerá la pantalla Add Packages, ya en esa pantalla usa el buscador para encontrar el paquete Nlog, y seleccionar los paquetes: Nlog, Nlog Configuration y Npgsql respectivamente, presionar el botón Add Packages para agregar los ensamblados al proyecto.

Fig. 2 seleccionar los paquetes Nlog y Nlog Configuration

3-. Ahora que ya se tiene una estructura en la solución como se muestra en la siguiente imagen:
Fig. 3 la estructura de la solución con los ensamblados.

4-. Agregar al proyecto una clase llamada NloggerWrapper
5-. Bien ahora hay que completar el código de la clase Program.
6-. Antes de ejecutar la solución es muy importante editar el archivo Nlog.conf para agregar targets (objetivos), layouts (disposición) y rules (reglas). Aquí el código del archivo Nlog.conf del proyecto.

Targets

En este archivo de configuración defino tres targets, el primero hacia un archivo, el segundo hacia una consola con salida de color y el último hacia una consola de salida normal.

Para ver completa la lista de targets consultar el enlace: https://github.com/NLog/NLog/wiki/Targets

Layouts

Por cierta comodidad y porque así es la manera predeterminada de ver la información, puse los layouts de la siguiente manera:

Se especifica un layout por cada uno de los targets Para más información de los layouts ver el siguiente enlace: https://github.com/NLog/NLog/wiki/Layout-Renderers

Rules

Ahora la configuración para las rules, aquí con el '*' le indico que ese nivel se use para todos los logs, únicamente en los niveles Error y Fatal escriban hacia el target llamado fileLog que es el target que escribe hacia un archivo de texto, en la segunda regla indico igual que para todos logs, los niveles Trace se escriban hacia el log llamado consoleLog que tiene la salida normal de consola y por último le indico que para los niveles Warn y Info escriban hacia el log de la consola con colores.

Para más información de las reglas ver el siguiente enlace: https://github.com/nlog/NLog/wiki/Configuration-file#rules

8-. Antes de ejecutar el programa, en el Solution Explorer haz click derecho sobre la solución después haz click en options, aparecerá la ventana Project Options ahí seleccionar las opciones run on external console y pause console output.
Fig. 4 opciones para ejecutar el proyecto.

Bien al ejecutar el programa este solicita una cadena de conexión desde el inicio:
Fig. 5 el programa solicita una cadena de conexión.

Errores como si la cadena de conexión no tiene un formato correcto, el servidor Postgresql esta abajo o no existe la base de datos, etc. Son encerrados dentro por un bloque try/catch y enviados al método LogException para que Nlog utilice el level correspondiente y lo mande hacia el target. Aquí el código del método LogException dentro de la clase NLoggerWrapper

    public static void LogException(Exception ex)
  {
   if (ex is ArgumentException)
    logger.Warn (ex.Message);
   else
   if (ex is NpgsqlException)
    logger.Error (ex.Message);
   else
    logger.Fatal (ex.Message);
  }
En este código dependiendo del tipo de excepción utiliza un nivel (level) de Nlog para escribir.
Fig. 6 el programa con Nlog muestra las excepciones en la consola con color..

Fig. 7 excepción atrapada por Nlog que se muestra en color.

Cuando uno de los target como en este ejemplo esta dirigido a escribir en archivo se puede revisar la creación del archivo y posteriormente su contenido.

Fig. 8 la creación de los archivos log con el target File.

Fig. 9 el formato de los archivos log.

Fig. 10 la ejecucción del programa sin errores