martes, 22 de diciembre de 2015

Utilizando Clamav Antivirus en GNU Linux OpenSuse

Siempre ha sido un eje de debate si existen o no los códigos maliciosos (virus, gusanos, etc.) para GNU/Linux , sea cierto o falso, lo verdadero es que siempre es conveniente tener un buen antivirus instalado en el sistema y más si se se ocupa como servidor de correo o servidor de archivos para otros sistemas operativos, sin un antivirus estaremos esparciendo código malicioso por la organización sin darnos cuenta.

Un antivirus es un programa que detecta cierta actividad sospechosa en la computadora, como el acceso a un disco de almacenamiento, la firma de un código malicioso en memoria o un intento para borrar o modificar un archivo, etc.

Hoy día existen varias opciones de antivirus para Linux, siendo ClamAv antivirus (www.clamav.net) una de las más reconocidas y utilizadas, por ofrecer las siguientes características:

  • Open source GNU Public License version 2
  • Escaneo rápido (fast scanning)
  • POSIX compatible
  • Detecta aprox 1 millon de virus, gusanos y troyanos incluyendo los virus de macro de microsoft Office, malware, etc.
  • Escaneo dentro de archivos comprimidos. (zip,rar, 7zip, arj,tar,gzip,bzip2, sfx, cab, etc)

Los dos comandos básicos para empezar a utilizar este antivirus son freshclam y clamscan. El primero actualiza la base de datos de definiciones de códigos maliciosos y el segundo escanea los archivos en su búsqueda.

Lo primero que debe hacerse antes de escanear cualquier archivo o directorio, es actualizar la lista de definiciones de virus.

NOTA: Si un antivirus no tiene actualizada su lista de definiciones, es totalmente inservible.

Para actualizar las definiciones ejecutamos el siguiente comando como root

    # freshclam
  

como un usuario sin privilegios esto se ejecuta de la siguiente forma:

    $ sudo root freshclam
  

Bien ya una vez que actualizamos las definiciones podemos proceder a escanear con el comando clamscan de la siguiente manera:

   clamscan [options] [filename or directory]
  

Por ejemplo para escanear un archivo ejecutable de Windows llamado IPEYE.EXE utilizamos el siguiente comando:

   $ clamscan IPEYE.EXE
  

Cuando ClamAv encuentra un código malicioso en el archivo escaneado, muestra el nombre del código entre el nombre de este archivo y la palabra FOUND, tal como se muestra en la imagen.

Para escanear todos los archivos en el directorio actual, utilizamos el siguiente comando:

   $ clamscan
  

A manera de una guía rápida, aquí presento una lista de las opciones más útiles para utilizar ClamAV:

1) Para escanear todos los archivos desde la raíz, pero unicamente mostrar los archivos infectados y al detectar una amenaza hacer sonar una alerta.

    $ clamscan -r --bell -i /
   

2) para escanear todos los archivos dentro del directorio /home.

    $ clamscan -r /home
   

3) para escanear todos los archivos dentro del directorio /home/martin y mover los archivos infectados al directorio /home/martin/quarantine.

    $ clamscan -r --move=/home/martin/quarantine /home/martin 
   

4) para escanear todos los archivos del directorio /home/martin y eliminar los archivos infectados.

    $ clamscan -r /home/martin --remove
   

5) Para escanear todos los archivos dentro del directorio /home/martin y copiar los archivos al directorio /home/martin/quarantine.

    $ clamscan -r --copy=/home/martin/quarantine /home/martin
   

6) Para escanear los archivos línea a línea contenidos en un archivo de texto llamado: [files2scan.txt]

    $ clamscan -file-list=files2scan.txt
   

Es importante mencionar que ClamAV únicamente escaneara los archivos en donde el usuario tenga permisos, si se requiere un escaneo completo de todo el sistema se deberá ejecutar con una cuenta con permisos de superusuario.

Si tienes un virus no detectado por ClamAV incluso con la última actualización de sus definiciones, favor de envialo a la siguiente dirección: http://www.clamav.net/sendvirus

domingo, 13 de diciembre de 2015

Agregando el soporte para diagramas en SQL Server

Cuando se hacen ciertas operaciones sobre una base de datos, por ejemplo al restaurarla de un respaldo o recrearla con un script,etc. Para que después cuando se intente realizar un diagrama ER en el diseñador nos envié el siguiente mensaje:

Este mensaje se refiere sobre la propiedad que un usuario tiene sobre un schema (esquema), un schema solo puede tener un unico dueño en la base de datos. Y cuando se requiera otorgar el permiso de propiedad a un nuevo usuario , el usuario con el permiso anterior pierde su propiedad. Para cambiar la propiedad de un schema a un usuario se ejecuta el siguiente comando:

use [myDataBase]
go
ALTER AUTHORIZATION ON DATABASE::[myDataBase] TO [newUser] 

Aquí un ejemplo de como poner como dueño al usuario [sa] de una base de datos llamada [Books].

use [Books]
go
ALTER AUTHORIZATION ON DATABASE::[Books] TO [sa] 

Al ejecutar con éxito este comando ya es posible instalar el soporte para diagramas en SQL Server y crear un nuevo diagrama.

miércoles, 25 de noviembre de 2015

Utilizando los controles Kendo UI DatePicker y TimePicker

Otro par de controles muy útiles incluidos en la suite de controles Kendo UI, son los controles Kendo UI DatePicker y TimePicker con estos controles se logra que las interfaces web tengan una apariencia intuitiva y muy profesional como si se tratase de una aplicación de escritorio (Desktop).

Kendo UI DatePicker

Este control proporciona una manera muy intuitiva para la selección de una fecha, tiene un campo de texto en donde puedes teclear la fecha deseada o bien seleccionarla de un calendario dropdown que aparece al momento de activar el control, como muestro en la siguiente imagen.

Kendo UI DateTimePicker

Este control es similar al DateTimePicker, permite teclear horas y segundos o bien seleccionarlo de una lista de las horas del día, como muestro en la siguiente imagen.

Ahora como ejemplo del uso de estos controles pondré el código de un formulario que tiene un control DatePicker, un DateTimePicker y unos radiobuttons que configuran la fecha y la hora de los controles según la opción seleccionada. La configuración de este ejemplo es igual a la configuración utilizada para el ejemplo de este post.. Aquí el código fuente JavaScript (dateTimeSample.js):

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

Al ejecutarlo en el navegador lo veremos como en la siguiente imagen

Observamos como los controles datePicker y dateTimePicker cambian sus valores según la opción seleccionada en los radiobuttons. En la imagen al seleccionar la opción “yesterday”

Al seleccionar la opción “Last 24 hours” vemos el resultado en la siguiente imagen

Enlaces relacionados:

domingo, 18 de octubre de 2015

Utilizando el Kendo UI Grid de Telerik con JQuery

Uno de los conjuntos de controles que he encontrado con más frecuencia en los desarrollos profesionales de sistemas son sin duda el conjunto de los controles Telerik, Telerik ofrece una amplia gama de controles para diseñar la interfaz gráfica de usuario o GUI (Graphical User Interface) en diferentes frameworks de .NET como: WPF, ASP.NET, Windows Form o Silverlight.

Voy a mostrar una breve utilización básica del kendo UI Grid con un formulario que hace una petición mediante JQuery a un servidor web en este caso Apache.

Paso 1:
Voy a crear un directorio de trabajo llamado “KendoUISamples” debajo de ~/public_html que es el directorio predeterminado por OpenSuSe para ser el sitio web del usuario, todo lo que está dentro de ese directorio se publica en Apache con la siguiente dirección: http://127.0.0.1/~martin/

Paso 2:
Dentro de ese directorio voy a crear un archivo de texto llamado "Authors.js" que contendrá los siguientes datos en formato JSON:

   [
  {"Id" : "1",  "Name" : "George", "LastName": "Orwell",
  "BirthDate" : "1903-01-25","Gender" : "true" },
  {"Id" : "2",  "Name" : "Norman", "LastName": "Mailer",
  "BirthDate" : "1976-01-31","Gender" : "true" },
  {"Id" : "3",  "Name" : "Richard","LastName": "Dawkins",
  "BirthDate" : "1941-03-26","Gender" : "true" },
  {"Id" : "4",  "Name" : "Doris",  "LastName": "Lessing",
  "BirthDate" : "1919-10-22","Gender" : "false" },
  {"Id" : "5",  "Name" : "Stephen","LastName": "Hawkins",
  "BirthDate" : "1942-01-08","Gender" : "true" },
  {"Id" : "6",  "Name" : "Carl",   "LastName": "Sagan",
  "BirthDate" : "1934-11-09","Gender":"true" },
  {"Id" : "7",  "Name" : "William","LastName": "Gibson",
  "BirthDate" : "1948-03-17","Gender":"true" },
  {"Id" : "8",  "Name" : "Arthur", "LastName": "C. Clarke",
  "BirthDate": "1917-12-16","Gender":"true" },
  {"Id" : "9",  "Name" : "Leonard","LastName": "Mlodinow",
  "BirthDate": "","Gender":"true" },
  {"Id" : "10", "Name" : "Grary",  "LastName": "Booch",
  "BirthDate": "1955-02-27","Gender":"true" },
  {"Id" : "11", "Name" : "James",  "LastName": "Rumbaugh",
  "BirthDate": "1947-08-22","Gender":"true" },
  {"Id" : "12", "Name" : "Ivar",   "LastName": "Jacobson",
  "BirthDate": "1939-09-02","Gender":"true" }
  ]
      
Estos datos servirán para ser el DataSource del control Kendo UI Grid que voy a mostrar. El directorio de trabajo se verá como en la siguiente imagen:

Paso 3:

Descargamos el HTML5 Boiler template (ver este post) y lo descomprimimos dentro del directorio de trabajo para que se genere la estructura básica de un proyecto Front-End HTML5, se verá una estructura como en la siguiente imagen

Paso 4:
Copiamos los archivos css y js de JQuery y Kendo UI Telerik a los directorios css y js que están en el directorio de trabajo para tener una estructura como la que se muestra en la imagen

Paso 5:
Completamos el código del archivo [index.html] con las siguientes líneas dentro de las etiquetas <head> y </head> para incluir a los archivos css y js de JQuery y Telerik para que que queden de la siguiente manera:

 <head>  
   <meta charset="utf-8">  
   <meta http-equiv="x-ua-compatible" content="ie=edge">  
   <title>Kendo Grid example 1.0</title>  
   <link rel="stylesheet" href="css/kendo/kendo.common.min.css">  
      <link rel="stylesheet" href="css/kendo/kendo.bootstrap.min.css">  
      <script src="js/jquery-1.11.3.min.js"></script>  
      <script src="js/kendo.all.min.js"></script>  
      <script src="js/kendo.aspnetmvc.min.js"></script>  
   </head>  
En este paso se llaman a los archivos css y js de Jquery y Telerik respectivamente.

Paso 6:
Inmediatamente después de la etiqueta agregamos el siguiente código para crear los controles del formulario en donde están contenidos el control Kendo UI Grid y el botón que hará la petición.

 <p>  
 <ul>  
      <li><div id="grid"></div></li>  
      <li><div><button id="btnButton">Get data from server</button></div></li>  
 </ul>  
 </p>  

Paso 7:
Ahora viene la parte más importante de la página, en donde se escribe toda su funcionalidad, aquí iniciamos los controles DataSource, Kendo Grid y agregamos el evento del botón que realiza la petición al servidor.

 <script>  
      $(document).ready(function()  
      {  
           //init the kendo UI control  
           $("#grid").kendoGrid(  
                {  
                     height: 366,  
                     width: 300,  
                     pageable: false,  
                     sortable: false,  
                     columns: [  
                          { field: "Id", title: "id"},  
                          { field: "Name", title: "name"},  
                          { field: "LastName", title: "lastName"},  
                          { field: "BirthDate", title: "birthDate"},  
                     ]  
                });  
           //Attach the function to button  
           $("#btnButton").click(function(){  
                var url = "http://127.0.0.1/~martin/KendoUISamples/Authors.js";  
                var data = [];  
                $.getJSON(url,data,function(data,status){  
                          var dataSource = new kendo.data.DataSource({  
                               type: "json",  
                               data: data  
                          });  
                          dataSource.read();  
                          var grid = $("#grid").data("kendoGrid");  
                          grid.setDataSource(dataSource);  
                     }).error(function()  
                     {  
                     alert("some errors ")  
                     });  
                });  
      });  
  </script>  

Al abrir la página, y pulsar el botón se vera el siguiente resultado:

Aquí esta el código completo de la página:

 <!doctype html>  
 <html class="no-js" lang="">  
   <head>  
   <meta charset="utf-8">  
   <meta http-equiv="x-ua-compatible" content="ie=edge">  
   <title>Kendo Grid example 1.0</title>  
   <link rel="stylesheet" href="css/kendo/kendo.common.min.css">  
      <link rel="stylesheet" href="css/kendo/kendo.bootstrap.min.css">  
      <script src="js/jquery-1.11.3.min.js"></script>  
      <script src="js/kendo.all.min.js"></script>  
      <script src="js/kendo.aspnetmvc.min.js"></script>  
   </head>  
   <body>  
           <p>  
                <ul>  
                     <li><div id="grid"></div></li>  
                     <li><div><button id="btnButton">Get data from server</button></div></li>  
                </ul>  
           </p>  
           <script>  
      $(document).ready(function()  
      {  
           //init the kendo UI control  
           $("#grid").kendoGrid(  
                {  
                     height: 366,  
                     width: 300,  
                     pageable: false,  
                     sortable: false,  
                     columns: [  
                          { field: "Id", title: "id"},  
                          { field: "Name", title: "name"},  
                          { field: "LastName", title: "lastName"},  
                          { field: "BirthDate", title: "birthDate"},  
                     ]  
                });  
           //Attach the function to button  
           $("#btnButton").click(function(){  
                var url = "http://127.0.0.1/~martin/KendoUISamples/Authors.js";  
                var data = [];  
                $.getJSON(url,data,function(data,status){  
                          var dataSource = new kendo.data.DataSource({  
                               type: "json",  
                               data: data  
                          });  
                          dataSource.read();  
                          var grid = $("#grid").data("kendoGrid");  
                          grid.setDataSource(dataSource);  
                     }).error(function()  
                     {  
                     alert("some errors ")  
                     });  
                });  
      });  
  </script>  
   </body>  
 </html>  

lunes, 5 de octubre de 2015

Utilizando el HTML 5 Boiler template

El HTML 5 Boilerplate es como dicen sus autores (The web's most popular front-end template) o sea una plantilla que contiene una estructura básica para construir el front-end de cualquier aplicación web que utilice como base de su construcción HTML5, CSS y JavaScript.

Una vez descargado el comprimido de este enlace, solamente se descomprime y ya está listo para utilizarse en cualquier proyecto web.

Aquí una imagen de la estructura de la plantilla, una vez extraída.

Como se muestra, tiene todo lo necesario para empezar: directorio css y js para las hojas de estilo y archivo JavaScript respectivamente, hasta un archivo index y 404 listos para personalizarse según las necesidades.

Si se desea conocer la documentación, hay que ir a este sitio.

sábado, 29 de agosto de 2015

Entendiendo el paso de variables a métodos en C# con ref, params y out.

En C# existen dos formas de pasar variables como parámetros a un método: por valor (Passing by value) que es la forma predeterminada y por referencia (Passing by reference, Passing by address). La definición del parámetro de un método consiste en el tipo de dato, el nombre del parámetro y si son más de uno se separan por coma como en los siguientes códigos:

  int method(string p)
  int method(string p, int q, bool r, float t);
  

Paso por valor (Passing by value)

Esta es la forma predeterminada en la que los métodos reciben los parámetros. Esto quiere decir que cuando un parámetro se recibe dentro del método, se crea una copia temporal de los datos, esta copia temporal actúa como una variable dentro del método con la que se realizan operaciones, sin afectar la variable original y una vez que el método termina su ejecución, la copia temporal es destruida, por lo tanto los cambios en el parámetro no afectan el valor de la variable original. Estos conceptos se observan mejor con el siguiente programa:

Este programa intercambia el valor de unos enteros en donde se inicialmente se les asigna un valor, esos enteros después pasan como parámetros, se ejecuta el método y las variables conservan su valor inicial. Aquí muestro la siguiente salida:

Paso por referencia (Passing by reference)

Hay 3 modificadores de parámetros en C# que sirven para pasar por referencia una variable a un método y estos son:

  1. ref
  2. out
  3. params

Utilizando ref

Cuando se pasan las variables como parámetros por referencia, el parámetro es en realidad una referencia a la dirección de memoria de la variable que se recibe, por lo que los cambios hechos al parámetro afectan a la variable original. Para pasar un parámetro por referencia, se antepone a la definición del parámetro la palabra reservada ref. Para ilustrar este concepto utilizo el programa del ejemplo anterior que intercambia dos valores enteros, pero con la modificación de pasar las variables por referencia (con ref) al método no por valor. Aquí el código:

Al ejecutar este programa se produce el intercambio de variables que realiza el método swap, porque ya no trabaja con copias locales sino con las variables globales.

Aquí el método swap con el modificador ref usado en la declaración de variables del método.

static void Swap(ref int number1, ref int number2)
    {
    int temp = number1;
    number1 = number2;
    number2 = temp;
    }

También se debe utilizar el modificador con sus argumentos al invocarlo.

Swap(ref a, ref b);

Utilizando params

En los ejemplos anteriores el número de parámetros está fijo en la declaración del método. Sin embargo, C# soporta el uso de un arreglo de parámetros (parameters array), la palabra reservada params permite pasar cualquier número variable de parámetros hacia un método sin necesidad de declararlos como un arreglo. Esta instrucción solo se requiere en la declaración del método. Con el siguiente programa muestro el uso de params para calcular el promedio de un arreglo de números y para armar una cadena.

Este programa produce la siguiente salida.

Utilizando output parameters

Un método de forma predeterminada solo puede devolver un valor mediante la instrucción return, al menos que se utilicen los output parameters (parámetros de salida), con esta característica pueden devolver tantos valores de salida como parámetros de salida tengan, no es necesario asignar valores a esos parámetros afuera del método sino se debe asignar el valor dentro del método que los va a utilizar o de lo contrario el compilador marcara un error.

Para utilizar los output parameters se debe anteponer la palabra reservada: out en la declaración de cada parámetro. Como se muestra en el siguiente código:


static void SetEnviromentProperties(out string currentDirectory,
    out string machineName,
    out string osVersion,
    out string userName,
    out int exitCode)

Bien con el siguiente programa mostraré el uso de esta característica.

Al ejecutar el programa, se vera la siguiente salida:

Al ejecutarse el método SetEnviromentProperties sus correspondientes argumentos también deben tener la palabra reservada out, para que dentro del método se les asigne el valor correspondiente.


static void SetEnviromentProperties(out string currentDirectory,
    out string machineName,
    out string osVersion,
    out string userName,
    out int exitCode)

Finalmente hay que recordar que un método que define output parameters DEBE asignar un valor a los parámetros out antes de que el método termine de ejecutarse, de lo contrario el compilador marcara un error.

sábado, 22 de agosto de 2015

Instalando Oracle JRE y JDK en Open SuSe 13.2

Por cuestiones de dependencias no pude instalar los archivos jdk-8u45-linux-x64.rpm y jre-8u45-linux-x64.rpm respectivamente, aunque yo no trabajo con Java, en Linux es una dependencia importante para OpenOffice y DbVisualizer así como para muchos otros programas, por lo sino es posible hacerlo con los RPMS entonces recomiendo una instalación manual, siguiendo los siguientes pasos en OpenSuse 13.2:

1) Se descargan del sitio de Oracle los archivos jre-8u45-linux-x64.tar.gz y jdk-8u45-linux-x64.tar.gz en vez de los rpm.
2) Debajo del directorio /usr se crea el directorio java.(como root)

# mkdir /usr/java
3) Se copian/mueven los archivos descargados al directorio creado anteriormente.

4) Se descomprimen los archivos, de preferencia en el siguiente orden:

  1. tar -zxvf jre-8u45-linux-x64.tar.gz
  2. tar -zxvf jdk-8u45-linux-x64.tar.gz

Al descomprimirse se crea el árbol de archivos del jre y jdk respectivamente.

Bien, ahora sigue un paso crucial que es agregar los recién descomprimidos jre y jdk de Oracle al directorio

/etc/alternatives
. En mí caso desinstalé todas las versiones de openjdk que tenia en OpenSuse y de manera predeterminada me asigno el siguiente:
/usr/lib64/jvm/jre-1.5.0-gcj/bin/java 
como la máquina virtual. Esto porque al parecer existe software que necesita por fuerza una máquina virtual.

5) Así como ya existe una máquina virtual predeterminada y lo que quiero es usar la máquina virtual de Oracle, ejecuto los siguientes comandos para registrar la máquina virtual en el directorio

/etc/alternatives
.

update-alternatives --install /usr/bin/java java /usr/java/jre1.8.0_45/bin/java 1 
update-alternatives --install /usr/bin/java java /usr/java/jdk1.8.0_45/bin/java 0

6) Ahora ejecuto el comando:

update-alternatives --config java

Si todo sale correctamente OpenSuse mostrará la siguiente pantalla:


En este punto seleccionamos la máquina virtual que necesitemos utilizar, en mí caso seleccioné la opción 2 que es el JRE de Oracle.

Si todo sale bien al ejecutar el comando:

java -version

Mostrará el siguiente resultado, mostrando la versión correspondiente a la JVM de Oracle.


Como último detalle hay que agregar al entorno la variable JAVA_HOME, esto en mí caso lo hice agregando las siguientes líneas al archivo .profile

JAVA_HOME = /usr/java/jdk1.8.0_45
export JAVA_HOME

En mí caso lo hice apuntando al jdk en vez del jre, esto lo hice para instalar netbeans posteriormente.

Más información en los siguientes enlaces:

lunes, 17 de agosto de 2015

Entendiendo DataContract y DataMember de WCF con GTK# y MonoDevelop

Un contrato se define como: “un acuerdo entre partes que se debe de cumplir de manera obligada por cada una de ellas”, los contratos deben ser claros, definidos y sin ambigüedad para no dar lugar a una mala interpretación.

Windows Communication Foundation WCF utiliza este mismo concepto para definir un acuerdo entre clientes y servicios de un ambiente SOAP, en este contexto el contrato WCF define:

  • Las operaciones soportadas por el servicio.
  • Los parámetros y los tipos de datos que regresan las operaciones.
  • La estructura de los tipos de datos complejos que se pasan.
  • Errores que pueden ocurrir al ejecutar una operación.

Hay que recordar que los ambientes SOA son heterogéneos, por eso es recomendable que el contrato este separado de la implementación y que esa implementaciòn evite tipos específicos de su tecnología ya que esto podría causar problemas de portabilidad para comunicarse con un cliente que este implementado con una tecnología diferente.

Los contratos en el contexto SOA proporcionan todo el metadata necesario para comunicarse con el servicio, el metadata describe: tipos de datos, operaciones, patrones de intercambio de mensajes y el protocolo de transporte que se utiliza.

WCF define tres principales tipos de contrato:

  • Service contract: Define las operaciones que el servicio tendrá disponibles para que los clientes puedan invocar mediante una petición request.
  • Data contract: Define la estructura de los datos que serán incluidos en el intercambio de los mensajes que van y vienen del servicio al cliente y viceversa.
  • Message contract: Habilita el control de los headers (encabezados) que utilizan los mensajes y como son utilizados por el servicio.

WCF utiliza el protocolo SOAP (Simple Object Access Protocol) como el formato de mensajería para las operaciones, cada operación desde el service contract (contrato de servicio) se vuelve un elemento en el cuerpo del mensaje cuando la operación es invocada.

En la definición de la operación se especifican los datos que son intercambiados entre el cliente y el servicio cuando la operación es invocada, como ejemplo la siguiente operación createAuthor para agregar un autor a una base de datos:

            [OperationContract]
        string CreateAuthor (string Firstname,
            string Lastname,
            DateTime Birthdate,
            bool Gender); 
        

  • Los parámetros de entrada en la operación definen los contenidos del cuerpo del mensaje enviado desde el cliente al servicio.
  • El valor de retorno en la operación define los contenidos del cuerpo del mensaje enviado desde el servicio al cliente.

De manera predetermina el runtime de WCF toma la responsabilidad de convertir los tipos simples de .NET a tipos SOAP y viceversa, definiendo los tipos simples como:

  • Primitivos como enteros y cadenas.
  • Tipos compuestos simples (struct) como DateTime
  • Tipos basados en XML como un XmlElement
  • Colecciones
  • Enumeraciones

Sin embargo para tipos mas complejos como las clases o los tipos de datos definidos por el usuario es recomendable que se programe manualmente el mecanismo de serialización/ desealización y esto se logra definiendo un DataContract para ese tipo de dato.

En síntesis, para que un tipo de dato complejo sea serializado por el serializador de WCF se le debe aplicar un atributo DataContract a la definición de la clase y aplicar un atributo DataMember a cada uno de los campos que necesiten ser serializados sean estos un miembro de datos o una propiedad, los campos a los que no se les aplique el atributo DataMember son ignorados por el serializador.

Como ejemplo de los atributos DataContract y DataMember definimos una clase Author que encapsula los parámetros de entrada de una nueva versión de la operación createAuthor.

Ahora la versión de la operación createAuthor

            
        [OperationContract]
        string CreateAuthor (Author a); 
        

Adicionalmente podemos agregarle las siguientes propiedades al atributo DataContract:

  • Name: Define el nombre del tipo que se genera en el metadata. Por default se utiliza el nombre del tipo.
  • NameSpace: Define el namespace utilizado en el esquema. Por default utiliza “http://tempuri.org”

De igual modo podemos agregar las siguientes propiedades al atributo DataMember:

  • Name: Define el nombre que se utilizará en la generación del metadata. Por default es el nombre del campo.
  • IsRequired: Campo requerido, arroja una excepción si este campo no está cuando ocurra la deserialización.
  • EmitDefaultValue: Le dice al serializador que incluya el valor por default del campo cuando ocurra la serialización.
  • Order: Indica la posición del campo en la secuencia de serialización.

Ejemplo de una aplicación GTK# y un servicio WCF

Ahora un ejemplo funcional de una aplicación GTK# que hace uso de un servicio WCF para insertar y obtener registros de una tabla de autores en una base de datos PostgreSQL, aquí esta el esquema de la tabla. (Para más información de una solución WCF en Monodevelop consultar Introducción a WCF con GTK# y MonoDevelop)

A continuación el código del store en PL/SQL para insertar un registro

Bien ahora una vista de la solución en el explorador de soluciones de Monodevelop.

La solución se llama Samples.WCF.AuthorsCatalog y tiene los siguientes proyectos:

  • Samples.WCF.AuthorsCatalog: Este proyecto contiene la entidad Author que es la clase que es serializada por el runtime para intercambiar los datos entre la aplicación GTK# y el servicio WCF.
  • Samples.WCF.AuthorsCatalogService: Este es el proyecto del servicio WCF, contiene la clase AuthorsDataHelper que es la que se comunica con la base de datos, la clase AuhorServiceImplementation que es la implementación del servicio y la interface IAuthorServiceContract que es el contrato del servicio.
  • Samples.WCF.AuthorServiceHost: Este proyecto contiene una aplicación de consola que es el hosting para el servicio WCF.
  • Samples.WCF.GUIAuthorsCatalog: Este proyecto contiene al cliente GTK# que tiene una GUI (Graphical User Interface) que utiliza la clase proxy para comunicarse con el servicio WCF.

El proyecto Samples.WCF.AuthorsCatalog ejemplifica la aplicación de los atributos DataContract y DataMember con el código de la siguiente clase:

Esta clase sirve como argumento de petición y de respuesta en el contrato y por consecuente en la implementación del servicio como muestro en el código fuente del contrato y de la implementación que se encuentran en el proyecto [Samples.WCF.AuthorsCatalogService]. Aquí esta el código fuente del contrato del servicio IAuthorServiceContract:

Ahora el código fuente de la implementación AuthorServiceImplementation:

Para ejecutar la solución primeramente ejecutamos el programa de consola [Samples.WCF.AuthorServiceHost.exe] que activa el proceso que alberga el servicio WCF, el ejecutable se encuentra dentro del directorio “bin” debajo de la ruta Samples.WCF.AuthorsCatalog/Samples.WCF.AuthorServiceHost/bin/Debug. con el siguiente comando:

            $ mono Samples.WCF.AuthorServiceHost.exe
        

Ahora ejecutamos la solución desde MonoDevelop.

Podemos probar la aplicación al agregar un par de autores, como se muestran en la siguientes imágenes, después de ingresar cada autor pulsamos el botón refresh grid

Cada uno de estos eventos se manejan a tráves de la clase proxy que se genera con el siguiente comando aplicándolo a la dll del servicio.

            $svcutil /out:AuthorServiceReference.cs  Samples.WCF.AuthorsCatalogService.dll
        

Conclusión

WCF proporciona facilidades para tomar el control de la serialización de datos. Sin embargo, hay que entender que entre más control manual tomes de tus servicios estos tenderán a ser menos interoperables.

lunes, 20 de julio de 2015

Entendiendo los diagramas de casos de uso (use cases diagrams)

Aunque los casos de uso son descripciones de la funcionalidad del sistema que deben existir en forma textual (Ver esta entrada). Estos son usualmente acompañados por diagramas que capturan detalles como los nombres de los casos de uso, los límites de los sistemas, los actores y las relaciones entre ellos. El estándar UML proporciona notación para cada uno de estos detalles.

Estos diagramas siempre se dibujan desde la perspectiva de la organización sin distinguir entre procesos automáticos y manuales, hay que tener presente que los diagramas de caso de uso son la vista estática del sistema.

Lista de los elementos generales para un diagrama de casos de uso:

Actor: Un actor representa un rol ejecutado por una persona externa, por un proceso o por cualquier cosa que interactue con el sistema.

Caso de uso (use case): Un caso de uso es un clasificador que representa una unidad de funcionalidad proporcionada por un sistema, un subsistema o una clase que puede intercambiar mensajes entre las acciones del sistema y uno o más actores.


Paquete (package): Sirve para la agrupación de elementos, puede contener otros paquetes.

Límite (System Boundary): El limite del sistema consiste de todos los casos de uso que están relacionados con el dominio del sistema.

Asociación (association): La participación de un actor en un caso de uso, instancias del actor e instancias del caso de uso se comunican una con otra.

Extend: Esta relación desde un caso de uso A a un caso de uso B indica que una instancia de un caso de uso B puede ser aumentado por el comportamiento especificado en A.

Include: Este relación se utiliza para indicar que un caso de uso es una subrutina de otro caso de uso.

Los casos de uso son organizados de forma jerárquica con las relaciones: extend, e include.

Una herramienta muy buena para hacer diagramas es visual paradigm, hay versiones para Windows, Mac y Linux, se puede descargar una versión community edition del sitio.

viernes, 10 de julio de 2015

Entendiendo los casos de uso (use cases)

Los casos de uso (use cases) son unos artefactos muy recomendados para el entendimiento, descripción, documentación y trazabilidad de los requerimientos funcionales de un sistema. Hacer un modelo de casos de uso es un primer paso en el análisis de requerimientos para describir el comportamiento del sistema desde la perspectiva de los actores y los objetivos a realizar con él. Ivar Jacobson el creador de los casos de uso los describe de la siguiente manera:

Un caso de uso son todas las maneras en las que se usa un sistema para lograr una meta particular para un usuario particular. Si juntamos el conjunto de todos los casos de uso te da todas las maneras útiles para usar el sistema, e ilustra el valor que el sistema proporciona

El modelo de casos de uso es una de las vistas del modelo de arquitectura 4+1 de Philippe Kruchten, como en la siguiente imagen, el modelo de casos de uso es la quinta vista (+1).

Los casos de uso se emplean en muchos procesos de ingeniería de software entre todos ellos dos de los más ampliamente utilizados son: MSF (Microsoft Solution Framework) y RUP (Rational Unified Process).

Aunque ambos procesos cumplen el mismo objetivo (proyectos de software con éxito) cada uno de ellos ubica el modelo de casos de uso de forma un poco distinta.

En MSF se tienen 5 fases:

  • Envisioning (Visualizar)
  • Planning (Planear)
  • Developing (Desarrollar)
  • Stabilizing (Estabilizar)
  • Deploying (Despliegue)

Los casos de uso (algunas veces en MSF los nombran usage cases en vez de use case), estos se crean en la fase Planning en la etapa de diseño conceptual (Conceptual Design).

En RUP se tienen 4 fases:

  • Inception (Inicio)
  • Elaboration (Elaboración)
  • Construction (Construcción)
  • Transition (Transición)

En RUP el modelo de casos de uso se crea durante la fase de inicio. en la disciplina de requisitos.

A un caso de uso informalmente se le conoce como una colección de escenarios. Un escenario es una secuencia especifica de acciones e interacciones exitosas y erróneas entre actores y el sistema bajo diferentes condiciones de operación.

A los escenarios también se le conocen como instancias de casos de uso.

Formatos para casos de uso

Los casos de uso de caja negra son la clase más común ya que no describen el funcionamiento interno del sistema sino sus responsabilidades, especifican la interacción entre el sistema y el mundo exterior en este contexto el mundo exterior se refiere a los actores, un actor en este contexto es alguien que interactua con el sistema.

Las responsabilidades del sistema en este tipo de casos de uso describen siempre que es lo que hace el sistema sin decidir como lo hace (esto le corresponde al diseño). Los tipos de casos de uso son:

  1. Formato breve (brief): Es la historia del uso del sistema en un solo párrafo, por ejemplo:

    Crear una nueva cita: una persona entra al sitio del sistema en el menú de creación de citas, el sistema despliega la pantalla de creación de citas solicitando los siguientes datos: fecha, hora, servicio solicitado, nombre, apellido, teléfono de casa, teléfono celular, email. La persona ingresa los datos y ejecuta la acción guardar. El sistema valida los datos, una cita fue creada en el sistema.

  2. Formato casual (casual version): es un un formato informal que cubre varios escenarios, este es el más ampliamente utilizado. Ejemplo:

    Historial de versiones
    Fecha Descripción Autor
    Noviembre 6, 2002 Initial draft Heidi Steen
    Titulo (Title): Creación de una cita
    Identificador (ID): UC1
    Breve descripción (Summary): Este caso de uso inicia cuando la persona entra al menú creación de citas del sistema, el sistema ingresa los siguientes datos: fecha, hora, servicio, nombre, apellido, email, teléfono de casa, teléfono celular. Entonces ejecuta la acción guardar entonces el sistema hace la validación y la cita es creada.

    Actores/Actors (no siempre son seres humanos, pueden ser otros sistemas informáticos o procesos se incluye el propio sistema):

    Persona, sistema médico

    Precondiciones/Preconditions (establecen lo que siempre debe cumplirse antes de iniciar el caso de uso, se asume que son verdaderas):

    1. La persona tiene acceso a Internet
    2. La persona entro en el sitio de la aplicación
    3. Los catálogos esta online y trabajan bien.

    Postcondiciones/Postconditions (establecen que debe cumplirse cuando el caso de uso termina con éxito):

    Se creo la cita en la base de datos del sistema.

    Flujo básico/Basic flow: (por lo regular no incluye ninguna condición o bifurcación, se incluyen interacción entre actores, validaciones y cambios de estados)

    Actor Sistema
    1-. La persona entra a la aplicación y elije crear una nueva cita.
    2-.El sistema solicita los siguientes datos: fecha, hora, servicio, nombre, apellido, email, teléfono de casa y teléfono celular.
    3-.La persona ingresa todos los datos solicitados y ejecuta la acción de guardar.
    4-. El sistema recibe la petición, realiza la validación de los datos si no existe un error entonces crea una la cita en la base de datos y despliega un mensaje de éxito.
    5-. La persona ha creado una nueva cita.

    Flujos alternos/Alternate flows/extensions (indican los otros escenarios de éxito, las bifurcaciones del flujo básico se registran poniendo el número del paso):


    3a Ingresa solo los datos requeridos.

    3a1. La persona ingresa solo los datos mínimos requeridos: fecha, hora, servicio, nombre, apellido y al menos uno de los teléfonos: home phone y cel phone.


    Flujos de excepción: (Exception flows: Indican los escenarios de fallo, esta sección también puede incluirse dentro de los flujos alternos)

    3b Selecciona una fecha anterior a la fecha actual.

    3b1. El sistema envía el mensaje “No se permite una fecha anterior a la actual”


    4b. Faltan campos requeridos

    4b1 El sistema envía el mensaje indicando los campos requeridos que faltan.


    Requerimientos no funcionales/Non functional requirements:(aqui van los atributos de calidad que se relacionan con el caso de uso)

    • El modulo de citas debe ser visible desde cualquier dispositivo móvil.
    • La interfaz de usuario debe funcionar en cualquier navegador.
    • El tiempo de respuesta para guardar no debe sobrepasar los 10 segs.

  3. Formato completo (Fully Dressed): como ejemplos de este tipo de formatos, visitar el sitio usecases.org

Elementos gráficos

El formato de casos de uso tiene una sección para prototipos gráficos (opcionales en algunas ocasiones) llamada “Pantallas del prototipo” en caso de que el sistema tenga GUI.

Por ejemplo el prototipo del ejemplo quedaría mas o menos así:

Una excelente herramienta para realizar prototipos es el proyecto pencil pencil es un proyecto open-source que incluye versiones para Linux, MacOSX y Windows.

Escritura del caso de uso en estilo esencial (Olvidarse de la GUI)

La idea de No considerar la interfaz de usuario sino concentrase en la intensión según el libro Writing effective use cases de Alistair Cockburn se deben de evitar los detalles de la GUI, recomienda hacer la narración a nivel de las intenciones del usuario y las responsabilidades del sistema suena lógico ya que el GUI cambia con más frecuencia que los procesos de negocio EBP (Elementary Business Process). La definición de EBP según el libro Applying UML and patterns de Craig Larman es:

Una tarea realizada por una persona en un lugar, en un instante, como respuesta aun evento del negocio, que añade un valor cuantificable para el negocio y deja los datos en un estado consistente.

Hay que ser claros lo esencial de los casos de uso son historias y narrativas, el producto de esta técnica son documentos de texto, los diagramas y prototipos son únicamente un complemento.

domingo, 10 de mayo de 2015

Error de MonoDevelop "MonoDevelop.GnomePlatform 5.0"

Después de instalar MonoDevelop utilizando el repositorio del sitio Monodevelop.com para OpenSuse, al intentar ejecutar la aplicación me aparecio esta pantalla.

Este error ya me había aprecido con una versión anterior de Monodevelop y Opensuse, al parecer es debido a una dependencia que no esta instalada.

Si vemos el error a detalle, se lanza por la falta de una dependencia , el nombre de esa dependencia es:

  libgnomeui
  

En OpenSuse se instala esta dependencia utilizando el instalador y desinstalador de software de YAST, una vez seleccionando el paquete que contiene la dependencia e instalandola el error se corrige.

Después de la instalación de la dependencia tendremos una versión funcionando y sin error de MonoDevelop.