domingo, 20 de diciembre de 2015

CapicuaGen: Proyecto de generador de codigo

Me encuentro estos días por comenzar mi proyecto de fin de master en "Investigación en ingeniera de software". Después de mucho debatir el tema decidí hacer un producto orientado a la generación automática de código, y a la construcción de software desde un enfoque generativo. ¿Que quiere decir esto? Bueno básicamente que construiremos un software, cuya misión es construir otro software, o mas exactamente el código de dicho software. El generador de código que voy a hacer se llamara CapicuaGen, nombre que elegí de forma aleatoria entre varias opciones, y espero, quizás, publicarlo como GPL (o otra licencia afín). En los siguientes meses iré publicando los avances que vaya haciendo en este tema y según sea posible el código fuente, quizás en GitHub.

Para comenzar, publico la propuesta del proyecto, sobre la que voy a comenzar a construir.

Situación actual


Durante la creación de sistemas empresariales, es común que se den las siguientes circunstancias:

  • Software muy parecido a desarrollos anteriores, pero lo suficientemente diferente para impedir que se reúse software y librerías de una forma clara y consistente.
  • Cortos tiempo de desarrollo.
  • Numero de recursos limitados (tanto económicos como humanos).
  • Equipos que atacan varios frentes que no tiene que ver con el sistema a desarrollar en cuestión (los recursos desarrollando o soportando varios sistemas a la vez).

El resultado de toda esta combinación de factores causa los siguientes problemas en el desarrollo de un sistema:

  • Lentitud en el desarrollo.
  • Retrasó en los tiempos de entrega.
  • Elevación de costos.
  • Multitud de horas extras realizadas por el equipo, lo que a su vez en la motivación de este.
  • Sacrificios en la calidad del sistema, lo que a su vez lleva a fallos en el sistema.

Como conclusión impactamos aspectos relativos al producto en si, como la calidad y el tiempo de entrega, y por otro lado impactamos en el equipo de personas que trabaja en el sistema.

Objetivos


Los objetivos a conseguir son los siguientes:

  • Agilizar la construcción de un sistema a partir del uso de generadores de código, que creen de manera adecuada las características comunes de cada sistema, ensamblándola apropiadamente.
  • Reducir la programación manual de un sistema a los elementos particulares que así lo requieran, esto es, aquellos elementos que son exclusivos del sistema y por lo tanto no están incluidos en otros sistemas.

Con el cumplimiento de estos dos objetivos se espera satisfacer las siguientes necesarias:

  • Aumento de la calidad del software al generarse en parte de forma automática. Los fallos detectados se podrían corregir en los elementos generadores y aplicar automáticamente al código de los sistemas.
  • Los codificadores no perderían tiempo realizando tareas repetitivas y se concentraría en las tareas que realmente da valor al sistema, y no en aquellas que se duplican sistema tras sistema.
  • Reducción de tiempo de desarrollo, en base a la generación de código automático, lo cual a su vez reduce el número de hora extras a desarrollar por un sistema.

Propuesta


Se realiza la siguiente propuesta de solución:

  • Es necesario detectar las características (features) comunes a un sistema, y las posibles variaciones de dichas características.
  • El análisis de dichas características detectadas y sus posibles variaciones, serán incorporados dentro de un generador de código, llamado Generador de características.
  • Los generadores de características serán los encargados de crear el código fuente que implementan las mencionadas características en base a una configuración sobre su variabilidad.
  • Los generadores de características deben ser independientes unos de otros, aunque pueden tener una serie de interfaces con las que exponer servicios a otras características, con el menor acoplamiento posible (debe ser lo más independientes posible).
  • La configuración de la variabilidad debe ser lo más versátil posible, si en una primera versión se uso XML, se intentara usar Ruby como lenguaje de configuración, parecido a la configuración de los archivos RakeFile o a un archivo podFile de CocoaPods.
  • Igualmente la generación de un sistema se llevara a cabo mediante la agrupación de varios generadores de características, que interactúan entre sí, para crear el código de dicho sistema.
  • La configuración, tanto del sistema, como de la variabilidad del sistema deben hacerse a través de una interfaz grafica que facilite dicha tarea.
  • Cuando se genera el código de un sistema, es necesario considerar que el sistema no puede generarse en un 100% de forma automática, por lo que habrá una parte del sistema que será creada automáticamente, y otra parte que lo creara el programador. Es importante que el generador reconozca la parte creada manualmente por el codificador y no sea reemplazado su código en ninguna circunstancia.
  • La creación de generadores de características en sí, es construida de forma manual, y se crean en parte a base de plantillas de código y analizadores de código, realizados en Ruby
  • Estos generadores de características una vez creados, podrán ser usados por varios programadores, con lo que se creara un repositorio centralizado en los que los programadores puedan subir sus generadores de características, o bajar los generadores de característica creados por otros programadores, algo parecido a las gemas de Ruby.
  • Hay que considerar que el generador de características, genera código, esa es su funcionalidad, es decir en ningún caso son librerías o framework a usar en nuestro código, sin embargo el código generador si puede usar librerías o framework externos.
  • Unos de los objetivos de generar el código, es aumentar la calidad del sistema, haciendo que el código generador implemente patrones de software, así como estándares y mejores prácticas de programación.
  • Hay que considerar que si tenemos un sistema generado con una versión de un generador de características y descargamos una nueva versión de las características podemos volver a generar el código y aprovechar las nuevas mejoras y cambios de esta versión.

martes, 1 de diciembre de 2015

Regla N°10 de la Ingeniería de Software: Si no es sencillo está mal hecho


El desarrollo de un software tiende a complicarse… a complicarse mucho. Se complica sacar el proyecto a tiempo, se complica las relaciones con el equipo de trabajo, con los proveedores o con los recursos. Debemos mantener esa complejidad bajo control, teniendo en la mente que todo lo que hagamos cumplir la regla "Si no es sencillo, está mal hecho".

La sencillez muchas veces se confunde. Sencillez no quiere decir fácil, es casi siempre lo contrario. Es difícil hacer las cosas sencillas. Casi siempre invertir en sencillez es un proceso costoso al principio y ventajoso al final del proyecto. El objetivo de esta regla es conseguir sistemas que estén guiados por la sencillez.

Para considerar un sistema sencillo debe cumplir las siguientes características:

  • Sencillo de entender.
  • Sencillo de explicar.
  • Sencillo de mantener.


Algunos consejos para conseguir sencillez son los siguientes:

  • Usa programación orienta a objetos: No veas un sistema como un flujo que va desde un punto ‘A’ a un punto ‘B’, sino como entidades que se relaciones entre ellas, e intercambian información.
  • Cada vez que uses una sentencia if, preguntante si no está organizando el código para evitar usar herencia (donde cada parte de if y el else debiera ser una clases hija con determinadas características).
  • Usa patrones de software: Son formas comprobadas de resolver determinados problemas, son extensamente conocidos, y son válidos tanto para incorporarlos en nuestros sistemas, como campo de estudio acerca de su sencillez.
  • Vuelvo a hacer: La primera vez que resolvemos un problema posiblemente no sea de la forma más sencilla posible, sin embargo ya tendremos una imagen clara del problema, si no estamos convenidos que la solución es lo suficientemente sencilla, es mejor rehacerla con la experiencia que ya tenemos. El problema de la complejidad es que crece como una bola de nieve, por eso es mejor rehacer partes de las que no estamos seguros de su sencillez.
  • Enfócate en hacer módulos que hagan muy pocas cosas pero que lo hagan muy bien.
  • Reúsa código: Casi todos los entornos y lenguajes de programación, como Java, Ruby o .NET, tienen repositorios de librerías, muchas excelentes, que resuelven muchas problemas comunes. Es bueno conocerlas y usarlas.
  • Pero no hagas tu código dependiente de librerías externas, encapsula apropiadamente las librerías para sea sencillo su reemplazo en caso que sea necesario.
  • Hablando de patrones, usa el patrón fascade (fachada), dicho patrón encapsula en funcionamiento de sistemas complicados, exponiéndolos con una interfaz mucha más sencilla. Este patrón es extremadamente útil cuando nos comunicamos con sistemas viejos, librerías en otros lenguajes o simplemente con elementos que no son sencillos, ni claros, pero no podemos modificarlos, ya sea porque no tenemos el código fuente, o porque se sale del ámbito de nuestro desarrollo. El patrón fascade lo expondrá para nosotros de una forma sencilla, y la complejidad del código a consumir no será contagiada a nuestro código.
  • Haz sistemas que no dependan de la implementación interna de otros sistemas (o módulos): Los sistemas se comunican por interfaces definidas, pero dichas interfaces debe ser independiente de sus respectivas implementaciones, es decir se debe poder cambiar la implementación sin afectar a las interfaces, ni a los sistemas con los que se consumen.


miércoles, 28 de octubre de 2015

Cuestión de confianza III: ¿Dónde están los malos?

Los “malos”, son personas individuales, o mafias que se dedican a buscar sujetos o entidades vulnerabilidades para poder obtener nuestros datos personales o financieros, con intención de lucrase con ellos. En algunos caso puede que no exista lucro, solo existe el afán de hacer daño, de perjudicar o de exponer información de nuestra vida que nos hacen sensibles a ataques futuros, como datos sobre nuestra salud, dinero o familia.

Ahora bien, ¿Dónde están los malos?

Hay una reglar sencilla para tener claro que elementos debemos proteger, por que allí están los intrusos. La regla es:

¡¡¡Los malos están en todas partes!!!

  • Están del lado del Usuario: Pueden usar técnicas de ingeniería social, tener acceso a los medios de autentificar del usuario, o atacar directamente la computadora de la víctima.
  • Están en las comunicaciones: O bien analizándolas o falseándolas para que pensemos que estamos operando directamente con nuestros servidores o sitios web, cuando no es así.
  • Están en el servidor: Empleados que tiene acceso a información privada o secreta, y que solo se confía en su "buena" fe para que no usen sus privilegios de forma maliciosa o bien software pernicioso que explota la información directamente de los servidores bancarios.
  • Están en lo servidores adicionales: Además de lo mencionado anteriormente, es posible que aplique solo la seguridad en los puntos de entrada de la red, y se deje toda una intranet desprotegida, confiando en que estamos protegidos de ataques del exterior. La seguridad se debe incluir en cada uno de los elementos de nuestra infraestructura.

miércoles, 21 de octubre de 2015

Cuestión de confianza II: Factores de autentificación.


La autentificación es una de las partes más delicadas de implementar en un sistema, básicamente consiste en asegúranos que la persona que se contacta a nuestro sistema es quien dice ser, pero no solo eso sino que los usuarios puedan garantizar que se están conectando a nuestro sistemas y no a ningún otro que se haga pasar por este.

Acerca de los factores de autentificación


Los factores de autentificación son maneras de clasificar los métodos posibles en los que basar la autentificación a nuestros sistemas.

  • Factor 0: Algo la empresa que ofrece el servicio conoce y el usuario debiera conocer. Se aplica, por ejemplo, haciendo preguntas por teléfono, en el que el operador telefónico conoce las preguntas (mediante un script), pero no las repuestas (o por lo menos no todas, porque su veracidad debe ser resulta por el  sistema informático). Es importante que el usuario sea el que inicie la comunicación telefónica siempre y en ningún caso contestar preguntas cuando es el usuario el que recibe la llamada del teléfono, puesto que no sabemos quién nos está llamando realmente, lo cual podría ser un fraude para conseguir nuestros datos personales. En lo general conviene evitar este tipo de autentificación, aunque generalmente no es posible porque necesitamos una atención personalidad.
  • Factor 1: Algo que el usuario conoce y que proporciona para acceder a su servicios, es esta categoría entran los password y los NIP, que deben estas compuestos con una fortaleza mínima, y que idealmente no conoce la institución, pero conoce los medios posibles de validarlo (por ejemplo con password encriptados no reversible, como SHA512).
  • Factor 2: Contraseñas dinámicas generadas por medios electrónicos, aquí entra el papel de los Token,  los cuales son dispositivos hardware (o aplicaciones moviles) que en base al tiempo, generan  un número (exclusivo para el usuario) que sirve para que autorice una operación en el sistema (y solo una), una vez que la ha autorizado, necesitara un nuevo número de token, para nuevas operaciones. Esto es "Algo que tiene el usuario", en este caso el dispositivo físico
  • Factor 3: Medios biométricos (“Algo que el usuario es”), Alguna característica física propia del cliente en si, como su huella dactilar, o patrones en la retina, etc.

Lo recomendable es usar un doble factor de autentificación. Combinamos un factor de seguridad, junto con otro, lo más común es combinar el factor 1 (contraseña), con el factor 2 (token).

De esta forma aunque alguien se adueñe de nuestras contraseñas, será incapaz de realizar ninguna operación en nuestro sistema por no poseer el número de token que le da acceso.

Todo esto en la práctica: Ejemplo con Gmail



Google ofrece un sistema de autentificación en dos pasos, que consiste de un sistema en el uso de la contraseña del usuario de una cuenta de Google, y adicionalmente un Token, que puede ser un token  basado en el tiempo o basado o un Token SMS.

Se activa desde la configuración de GMAIL



Se activa mediante un Token SMS que llega al celular registrado


Una vez autentificados nos pedirá que indiquemos la pantalla


Y mediante la lectura de un QR, queda instalada la clave simétrica en un celular



Desde este momento podremos usar la autentificación en dos pasos:



Ventajas de este token:

  • Es gratis
  • Se basa en estándares y algoritmos públicos

Desventajas:

  • Está pensado para los productos de Google, o aquellos que usan sus servicios.

jueves, 8 de octubre de 2015

Cuestión de confianza I: Criptografía


Es curioso como casi todos los elementos en los que se basa en internet se crearon de una manera más o menos insegura en la que cada elemento viajaba por la red si ningún tipo de protección, libres para que cualquiera pudiera leer su contenido. Esto fue así, hasta que entro en juego la criptografía.

Muchas veces la gente no es consciente de la información personal, privada y secreta que viaja a través de sus computadoras o celular, o si lo es no le da importancia requerida. El tema es que es realmente importancia limitar el acceso a nuestra información, porque nunca sabemos que consecuencia podría tener que un extraño acceda a nuestro teléfono, nuestras fotos o mensajes, lo que para nosotros es inofensivo para otras personas abren posibilidades de extorsión o estafas en contra nuestra.

La criptografía garantica que solo nosotros (u otras personas autorizas) puedan acceder a nuestra información, de forma que sepamos que lo que sale de nuestros dispositivos, está debidamente protegida, y es confidencial.

La criptografía es un conjunto de técnicas y métodos en que los que un mensaje origen (o en claro) con información confidencial, se convierte en otro sin aparente significado y que puede viajar por medios no seguros, con la tranquilidad de que el mensaje original no podrá ser descubierto, sin aplicar los correspondiente métodos criptográficos sobre el mensaje original.

La criptografía existe desde hace muchos siglos, siempre asociada al envió de mensaje secretos entre dos partes. Algunos sistema de criptografía antiguos, se basan en la ocultación del método criptográfico. En los sistemas criptográficos modernos, el método de inscripción es público (o podría serlo sin comprometer la seguridad) y al mismo tiempo poseen una clave de encripción que debe ser secreta, y que si la cual aunque tengamos el algoritmo y el mensaje cifrado, no conseguiremos tener el mensaje original.

Una excepción al tema de claves de encripción son los algoritmos de hash donde la información se encripta de forma no reversible, sin necesidad de una clave o llave de encripción, en una cadena de longitud fija tal que así:

Original: “ESTE ES MI PASSWORD”

Este es el hash creado: ed85e76ecad699fdb1bfa36876f35e665a3105750f0af9c4d6bbfc80a3b664a1

Debido a que es imposible partir del hash y llegar al original, Esta es la forma ideal para almacenar password, ya que incluso cuando la base de datos de los usuarios se viera comprometida (por ejemplo que se robara) no supondría un problema, porque no se podrían averiguar los password.

Al margen la autentificación anterior, se dan principalmente dos tipos de criptográfica.

Criptografía simétrica


Tanto el recepto del mensaje encriptado, como la persona que encripta, usan la misma clave de encripción para realizar sus operaciones. Algoritmos que lo usa son por ejemplo AES (Rijndael).

Las ventajas de este método son:
  • Es la practica tiene una velocidad aceptable
  • Es muy seguro

Las desventajas:
  • La principal desventaja es que un usuario genera la clave y tiene que pasársela a otro usuario, lo cual podría comprometer la conexión desde un inicio

El hecho que compartan la misma clave, es un problema, el único que tiene este tipo de criptográfica, porque ¿Cómo se hace que el usuario final y destino tengan la misma clave?, solo enviando la clave por un medio que sea seguro, para garantizar que nadie más la tiene, pero precisamente necesito intercambiar la llave porque no tengo un medio seguro para enviar información.

Criptografía asimétrica


Consta de dos claves, en lugar de una, llamadas clave privada y clave pública, la clave pública sirve para encriptar, y es de libre acceso, la clave privada para desencriptar y solo la tiene una persona (la que genero las claves). Además la privada sirve para firmar mensajes y garantizar que la persona que la usa es el dueño de la clave.

En la práctica funciona así: Una persona genera (a través de un algoritmo) una clave privada y pública (que se complementan entre sí), se queda para si la clave privada, y distribuye la clave pública (a quien desee), a partir de ese momento, quien desee mandarle un mensaje encriptado, puede hacerlo usando la clave pública, y solo el podrá desencintarlo usando la clave privada. Igualmente si él quiere mandar un comunicado y garantizar su autenticidad, podrá firmarlo con su llave privada, y todo aquel que tenga la llave publica, podrá validar su origen.

Algoritmos que implementan esta tecnología son por ejemplo RSA o DSA.

Las ventajas de estos algoritmos son:
  • Seguridad en cuanto al custodio de las claves (nunca se difunde la clave privada)
  • Seguro en cuanto los mecanismo de inscripción

Las desventajas:
  • Increíblemente lento

En esta criptografía se resuelve el problema de la llave compartida, puesto que al haber dos llaves, se puede distribuir libremente la llave pública (a cualquier persona) para encriptar, y la permanecer debidamente custodiada la llave privada para desencriptar. Así por ejemplo dos personas (o entes), pueden iniciar una comunicación segura, simplemente intercambiando sus llaves públicas y usando sus llaves privadas para desencriptar.

Debido a que la criptografía asimétrica es realmente lenta, en lugar de encriptar un mensaje completo, se genera una llave simétrica aleatoria, con la que se encripta el mensaje y se envía el mensaje encriptado y adjunto con la llave simétrica encriptada (ahora sí) con la llave asimétrica publica, lo cual garantiza la velocidad y la confidencialidad.

Certificados digital


Cuando recibimos un mensaje firmado con una llave privada, podemos validar su autenticidad con nuestra llave pública. Esto quiere decir que podemos garantizar que la persona que tiene la llave privada es la se está comunicado, con nosotros, puesto que debe coincidir con la llave publica que nos proporcionó.

Hay que agregar que la firma es diferente por cada mensajes, por lo que garantiza no solo que el mensaje fue enviado por quien tiene la llave privada, sino además que el mensaje no ha sido modificado en el cambio.

Un detalle importante es que solo garantiza eso, es decir que el mensaje fue firmado con la llave privada, pero no garantiza que esa firma electrónica pertenezca a una persona en particular. La firma podría ser de cualquier persona, y haberse generado en cualquier momento.

Para garantizar además que la firma privada pertenece a una determinada persona o entidad, se usan los certificados, que bien pueden identificar a una persona o a un ente como una empresa o un banco.

Pero, ¿En que consiste exactamente un certificado? Imaginemos que yo quiero comunicarme (a través de una computadora) con otra persona o entidad, por ejemplo una tienda. Con el uso de llaves públicas (y privada) garantizo que la comunicación es confidencial entre ambos, pero de ninguna forma garantizo que esa llave pertenezca a la tienda, pero igualmente imaginemos que existe un tercer elemento, un ente en el que confiamos los dos (la tienda y el usuario), que garantice que esa llave privada pertenece a la tienda, ¿Cómo lo puede hacer? Dando por supuesto que yo confió en el tercero, que se llama entidad certificadora, esta firma (con su propia llave privada), la llave publica y demás información de la tienda, posterior a que valide la identidad de la tienda (mediante documentos, escrituras, registros de empresa, visitas en persona). En este punto ya tenemos un certificado, que contiene la llave pública, y que está firmado por alguien en el que confiamos que ha validado correctamente la identidad de la tienda, de esta forma queda ligada la identidad con la llave pública.

¿Quién son esas entidades certificadoras y por qué confiamos en ella? Son grandes empresas cuyo servicio es precisamente ese garantizar la identidad de entes y personas, y son aceptadas a nivel mundial como VERISIGN, o incluso gobiernos o entidades gubernamentales que realizan dicha función.

¿Cuál es proceso para generar un certificado?

  1. Se genera un par de llaves (pública y privada)
  2. Se realiza una petición de generación de certificado en base a la clave pública, y a los datos de la empresa (y los host que queremos certificar).
  3. Se envía la petición a una entidad certificara, que realizara los pasos necesarios para garantizar que somos la empresa para la cual estamos pidiendo los certificados, y una vez garantizado nos expedida dicho certificado.
  4. En nuestro servidor podemos unir la llave privada con el certificado, y en base a eso configurar nuestros servidores para que lo usen apropiadamente

Nuestro clientes al conectarse a nuestros servidores descargaran el certificado (con la llave publica), y al estar firmado por la entidad certificadora (en la confiamos), asumiremos que el servidor al que nos estamos conectando es el correcto. Igualmente si no está firmado o lo está por alguien en que no confiamos seremos advertidos de esta situación, y estará en nuestra decisión continuar la comunicación con dicho servidor.

¿Qué ocurre cuando queremos generar un certificador de pruebas?


Es posible que los certificados se firmen a sí mismos, como si fueran una entidad certificadora, estos se llaman certificados autofirmados.

Por otro lado es posible que firmemos un certificado a través de otro certificado, por ejemplo puedo firmar todos los certificados internos de una empresa, con un mismo certificado, y configurar en los ordenadores de la empresa, el certificado firmante como entidad firmante de confianza. A partir de este momento todos los certificados firmados con aquel, serán de confianza.

domingo, 20 de septiembre de 2015

Swift: Variables, Opcionales (?), Opcionales Implícitamente Desempaquetados (!) y conversiones entre ellas (as, as? y as!)


!?

Actualmente me encuentro aprendiendo Swift para programar dispositivos iOS,  es un lenguaje con características muy atractivas que me está agradando mucho.  Me gusta sobretodo la seguridad que ofrece al ser muy restricción en las opciones que ofrece para programar algunos aspectos. Cuanto mas restrictivo sea el lenguaje mas seguro será. Algunos programadores sienten que un lenguaje restrictivo cohíbe su libertad al momento de programar, yo creo que confunde el concepto de libertad, libertad es poder jugar con tu hijo por la tardes, en lugar de estar en la madrugada con una sobredosis de café (o de Red Bull), preguntándote porque está mal referenciado un puntero.

Pero antes de nada, ¿Cómo pruebo Swift?


- Es muy fácil, solo necesitas ejecutar XCode en tu Mac y …

- No tengo una Mac

Vale, entonces está más complicado,  se supone que la versión 2.0 de Swift, va a ser libre, lo cual podría implicar ver el lenguaje en otras plataformas como Windows o Linux, pero hasta entonces necesitaríamos una Mac. Existen algunas alternativas, como por ejemplo este compilador en línea para probar pequeños script de Swift e ir acostumbrándonos al lenguaje:


o este


¿Listo? Sigamos entonces…


Unas de las cosas que más me costado comprender son las variables opcionales, sobre todo por su aparente parecido con los tipos de datos Nulleables de C#, por que manejan conceptos parecidos al igual que su sintaxis. Hasta que no comprendí que son cosas completamente diferentes, no entendí el uso de los opcionales. (Así que aunque suene igual, ni los compares, no se parecen en nada).

Variables en Swift


Una característica de las variables en Swift, es que siempre deben tener valor, o más bien siempre deben estar instanciadas, no pueden tener un valor nulo, o nil, como se les llama en Swift.

Esto quiere decir de que cualquier variable que tengamos definida, sea cual sea, siempre tendremos acceso a sus métodos y propiedades, si necesidad de realizar una validación previa.

Por ejemplo si tuviéramos un String declarado, la cadena siempre debiera tener un valor y nunca podría valer nulo, si no inicializamos la cadena el programa simplemente no compilara. En el caso de definiciones de clases, la variables propiedades de esta deben ser obligatoriamente instanciadas en al momento de su declaración o en el constructor del objeto.

El siguiente código es válido, y el método endIndex, siempre estar disponible por que strValor siempre tendrá un “valor”.

var strValor = "Hola"
println(strValor.endIndex)

También el siguiente código es válido:

var strValor:String 
strValor = "Hola" 
println(strValor.endIndex)

El siguiente código directamente no compilara por querer usar la variable antes asignarla un valor (nótese que no dará un error en tiempo de ejecución, sino que simplemente no compilara).

var strValor:String 
println(strValor.endIndex)

El resultado de la compilación será:
 
error: variable 'strValor' used before being initialized

Tampoco es posible asignarle nil (nulo) a la variable, igualmente no compilara. El siguiente código no será valido:

var strValor:String 
strValor = nil 
println(strValor.endIndex)

Siendo el error el siguiente:

error: cannot assign a value of type 'nil' to a value of type 'String' strValor=nil

Variables Opcionales en Swift


Ahora bien y ¿si realmente necesitamos que algunas variables valgan nulo?, es posible que la ausencia de valor tenga un significativo para nosotros, o que directamente no podemos asignar un valor iniciar a nuestras variables. Para lo cual existen los opcionales.

Los opcionales son variables que pueden tener un valor de un determinado tipo o valer nulo. Para crear un opcional de un determinado tipo simplemente agregamos el símbolo ? al tipo, por ejemplo para tener un opcional de String, lo declaramos como String?:

var strValor1:String? 
strValor1="Hola" 
strValor2=nil

Las dos asignaciones anteriores son validas.

Podemos comprobar si el valor asignado es nulo, simplemente preguntándolo con un if, igual que lo haríamos en otros lenguajes:

if strValor1==nil 
    println ("Es NULO") 
}

Sin embargo si queremos usar el valor del opcional debemos realizar un proceso llamado desempaquetamiento, esto consiste en que obtengamos el tipo inherente al opcional, por ejemplo de un opcional de String, el tipo inherente seria el mismo String.

Para desempaquetar un opcional, podemos usar el operador ! o el operador ?, a la derecha de la variable. Cada operador tiene una funcionalidad diferente.

El operador ? indica al compilador que intente desempaquetar la variable y de no poder no continúe la operación con la variable opcional, asignando nil al resultado requerido (si se requiere).  Por ejemplo:

var strValor1:String?
strValor1 = nil
println (strValor1?.endIndex)

Por ejemplo se mostrara en la pantalla nulo (nil), como resultado, pero no fallara

Otra curiosidad del uso del operador ?, es que siempre devuelve un opcional, del tipo esperado, por ejemplo, el tipo esperado para el método endIndex, es un Integer así que devolvería un Integer?, esto es porque el compilador requiere saber siempre con el tipo que se está trabajando (Swift es de tipeado fuerte, con lo que la única manera de estar seguro del tipo al momento de trabajar es trabajar siempre con opcionales Cuando se usa el operador ? , por ejemplo la ejecución del siguiente código:

var strValor1:String?
strValor1 = "hola"
println ("la variable mide  \(strValor1?.endIndex)'")


Dara el siguiente resultado:

la variable mide 'Optional(4)'


El operador ! permite desempaquetar el valor de opcional,  el valor debe existe y en caso de no existir provocara un error, por lo tanto solo debemos ejecutarlo solo en el caso que estemos seguro que el opcional tenga un valor:

var strValor1:String?
strValor1=”Hola”
println(strValor1!.endIndex)

El siguiente código por ejemplo dará un error en tiempo de ejecución al no tener valor el opcional (es nulo puesto que nunca se inicializo)

var strValor1:String?
println(strValor1!.endIndex)

Esto nos supone un problema, puesto que al usar opcional, debemos comprobar siempre antes de usarlos que tengan valores y desempaquetar el valor en cada uso, por ejemplo en el caso del string debiera ser así:

var strValor1:String?
strValor1 = "Hola"
if (strValor1 != nil)
{
    println("Letras \(strValor1!.endIndex)")
    println("Primera letra \(Array(strValor1!)[0])")
    println("Mayusculas \(strValor1!.uppercaseString)")
    println("Minusculas posicion \(strValor1!.uppercaseString)")
}
else 
{
    //Lo que sea
}

El resultado es el siguiente:

Letras 4
Primera letra H
Mayusculas HOLA
Minusculas posicion HOLA

Como vemos cada vez que queremos usar la variable tenemos que desempaquetarla con el operador ! , Swift nos propone la estructura if let, para prevenir realizar este desempaquetado en cada ocasión y que nuestro código quede más comprensible:

var strValor1:String?
strValor1 = "Hola"

if let strValorDesenpacado=strValor1
{
    println("Letras \(strValorDesenpacado.endIndex)")
    println("Primera letra \(Array(strValorDesenpacado)[0])")
    println("Mayusculas \(strValorDesenpacado.uppercaseString)")
    println("Minusculas posicion \(strValorDesenpacado.uppercaseString)")
}else {

    //Lo que sea

}


Aunque pudiera parecer lo contrario la expresión if let, es una expresión completa y no dos por separado (no es un if mas un let). Al detectar el compilar la orden if let, lo que él entiende es “Desempaqueta la variable de la derecha, si puedes hacerlo (es diferente de nil), asígnaselo a la variable de la izquierda y ejecuta el código del if.”


Opcionales Implícitamente Desempaquetados


Los opcionales implícitamente desempaquetados (Implicitly Unwrapped Optionals, a partir de ahora por sencillez solo opcionales implícitos), son una vuelta de tuerca más al tema de los opcionales, son los más parecidos a los variables por referencia de otros lenguajes como .NET o Java, las variables pueden ser nulas o tener un valor, pero no necesitan ser desempaquetadas en ningún caso, se usan sin los operadores ¿ o ! ( de allí la parte implícita), pero si intentamos usar una variable con un valor nulo, esta generada un error:

var srtValor:String!
srtValor="Hola Mundo"
println(srtValor)

//Notese que no es necesario desempacar la varible
println (srtValor.endIndex)
srtValor=nil
//La siguiente instruccion fallara pero se compilara correctamente
println (srtValor.endIndex)

El uso de los Opcional Explícitos entre, otros motivos, es la interoperabilidad con ObjetiveC, donde es más natural trabajar con variables que se comportan de esta forma (pueden tener valor  o ser nulas). Cuando tengamos que interactuar con la API de ObjetiveC (lo cual pasara mucho), sobre todo para recibir valores de esta, casi siempre serán un opcional implícito.

Conversiones de tipo mediante as, as? y as!


El conjunto de operadores as, nos ayudan a convertir objetos de un tipo en objetos de otro, a través de mecamismo de empaquetado/desempaquetado o de hererencia. Para nuestros ejemplos, vamos a contar con tres clases ClaseA, ClaseB , siendo que ClaseB hereda de ClaseA:

class ClaseA
{
    let Mensaje="Hola Mundo"
}

class ClaseB : ClaseA
{

}

Operador as


Usaremos el operador as, cuando el compilador pueda garantizar que la conversión (o cast) es posible, en tiempo de compilación, y que esta siempre es posible, aunque agreguemos mas código en un futuro (no basta con que nosotros como codificaciones estemos seguros, el compilador debe estar seguro al 100% ). Por ejemplo,  es posible convertir una variable de tipo ClaseB en una de ClaseA o en opcional de ClaseA, mediante el operador as, por que el compilador sabe que dicha conversión es posible siempre:

var claValor: ClaseB = ClaseB()

//Conversiones
var clbValor1 =  claValor as ClaseA
println ("El tipo es '\(clbValor1.dynamicType)'")

//Conversiones
var clbValor2 =  claValor as ClaseA?
println ("El tipo es '\(clbValor2.dynamicType)'")

La salida sera:

El tipo es 'main.ClaseB'
El tipo es 'Swift.Optional'

Pero sin embargo no sera posible usar el operador as para convertir una variable de tipo ClaseA en una de tipo ClaseB, por que el compilador no puede garantizar que siempre sea posible, puesto que no todas los clases que hereden de ClaseA son forzosamente de tipo ClaseB, esto se aplica aunque en el código se vea claramente (por una persona)  que la variable si es convertible.

En el siguiente ejemplo fuerzo la conversion de una variable de tipo ClaseA en una de ClaseB (downcasting):

var claValor1: ClaseA = ClaseB()
//Conversiones
var clbValor1 =  claValor1 as! ClaseB
println ("El tipo es '\(clbValor1.dynamicType)'")

El los siguientes ejemplos, convierto la variable opcional de tipo ClaseA, en una de tipo ClaseB (no opcional) y una Opcional de ClaseB:

var claValor2: ClaseA? = ClaseB()
//Conversiones
var clbValor2 =  claValor2 as! ClaseB
println ("El tipo es '\(clbValor2.dynamicType)'")
var clbValor3 =  claValor2 as! ClaseB?
println ("El tipo es '\(clbValor3.dynamicType)'")

Ahora bien que pasaría en el ejemplo anterior, si la variable opcional del ClaseA valiera nulo y quisiera hacer el casting igualmente a una de ClaseB no opcional:

var claValor2: ClaseA? = nil
//Conversiones
var clbValor2 =  claValor2 as! ClaseB
println ("El tipo es '\(clbValor2.dynamicType)'")

var claValor: ClaseA = ClaseB()

//Conversiones
var clbValor =  claValor as ClaseB

El error marcado sera el siguiente:

error: 'ClaseA' is not convertible to 'ClaseB'; did you mean to use 'as!' to force downcast?

¿Por qué si visualmente se ve que se puede hacer un cast, el compilador no nos deja?, bueno, esto es porque en un futuro podríamos hacer asignar otro valor a la variable claValor, e impedir el cast, Swift nos protege de estos posible futuros errores, el siguiente código seria incorrecto y tampoco compilara (incluso visualmente):

var claValor: ClaseA = ClaseB()
claValor = ClaseA()

//Conversiones
var clbValor =  claValor as ClaseB

Operador as!


El operador as!, nos permite forzar el cast, cuando estemos seguros que el posible realizarlo (aunque el compilador no lo este), es una manera de decir al compilador, que nosotros asumimos la responsabilidad sobre posibles fallos del cast. Los siguientes cast son posibles:

var claValor2: ClaseA? = ClaseB()
//Conversiones
var clbValor2 =  claValor2 as! ClaseB
println ("El tipo es '\(clbValor2.dynamicType)'")
var clbValor3 =  claValor2 as! ClaseB?
println ("El tipo es '\(clbValor3.dynamicType)'")

Ahora bien si no es posible el cast, la conversión fallara y fallara en tiempo de ejecución (no en tiempo de compilación), por ejemplo en el siguiente código:

var claValor2: ClaseA = ClaseA()
//Conversiones
var clbValor2 =  claValor2 as! ClaseB

El operador as?


El operador as?, nos devuelve siempre un Opcional del tipo destino de la conversion, por ejemplo si el destino es un string, el resultado siempre sera un string?.

Se usa este operador para realizar cast de los cuales no estamos seguros que sean posible realizarlos, pero no queremos que falle en tiempo de ejecución. Si es posible realizar el cast se nos devolvera un opcional del tipo destino, si no es posible el resultado sera un nulo, por ejemplo:

//Conversiones
var clbValor2 =  claValor2 as? ClaseB
println ("El tipo es '\(clbValor2.dynamicType)'")

Devolvera un opcional de ClaseB (ClaseB?)

Debemos comprobar antes de usarlo si es valor devuelto es nulo, y si no es nulo desempacarlo para obtener, ahora si, un elemento de tipo ClaseB:

var claValor2: ClaseA = ClaseB()

//Conversiones
var clbValor2 =  claValor2 as? ClaseB

if clbValor2 != nil
{
    let cblValor3 = clbValor2!
    println ("El mensaje es '\(cblValor3.Mensaje)'")

}else {

    println ("El objeto no se puede convertir")

}

Es posible simplificar este conjunto de llamadas usando la instrucción if let revisada anteriormente:

var claValor2: ClaseA = ClaseB()

if let clbValor2 = claValor2 as? ClaseB
{
    println ("El mensaje es '\(cblValor3.Mensaje)'")

}else {

    println ("El objeto no se puede convertir")

}

La seccion del if solo se ejecuara si es posible la conversion, y se trabajara dentro del if con el objeto desempaquetado, sin necesidad de realizar ningún otro proceso adicional, la parte del else se lenzara cuando la conversión no haya sido posible.

Y esto es todo


¿Qué futuro tiene Swift?, es dificil saberlo y posiblemente vendra marcado con la salida de Swift 2.0 y si es capas de ofrecer una mayor integracion con XCode (en el cual hace cosas extrañas a veces), igualmente seria interesante ver Swift funcionando en otras plataformas no Mac. Quedamos en espera de observar que pasa en los siguientes meses.

domingo, 6 de septiembre de 2015

Un año después

¡Cumplimos un año en el blog!, el primer post fue el día lunes, 25 de agosto de 2014, así que unas semanas tarde del primer aniversario, decidí hacer un pequeño resumen de lo acontecido hasta ahora.



¿Cuántas publicaciones hemos hecho hasta ahora?, unas 21, una y media por mes aproximadamente, que no es un gran número, pero este es un proyecto individual y muy personal, en el cual cada publicación intenta reflejar un poco de mi vida laboral, mi experiencia, y acercar un poco a los posibles interesados al día a día de la ingeniería de software.

En general estoy contento con las publicaciones de este año y esperemos continuar con un ritmo parecido o superior (si es posible) el año que viene.

Podemos clasificar lo ocurrido en este año de la siguiente forma:

¡Tenemos redes sociales!


Estamos en Facebook y en Google+ en los siguientes enlaces:


Post relativos a reglas de software de la ingeniería de software


Es un conjunto de reglas o recomendaciones que nos ayudan a diseñar y construir software, con la intención de que aumentar nuestras posibilidades de éxito. Se han publicado las siguientes:


Post de diversos temas



Investigación en ingeniería de software


Los siguientes post están relacionados a prácticas y documentos realizados en el master que me encuentro actualmente estudiando en la UNED, “Investigación en Ingeniera de Software”, y el cual espero acabar en el algún momento de este siglo o el siguiente.


Y esto es todo en el primer año, espero que os haya gustado :-)

sábado, 8 de agosto de 2015

Regla N°9 de la Ingeniería de Software: Los warnings de hoy son los errores de mañana (programa sin warning)


Los warning (advertencias) son mensajes que los compiladores nos muestran al generar los ejecutables de un proyecto que indican que debemos poner atención en un detalle en particular de nuestro código.

Los warning son sentencias sintácticamente correctas para el compilador, pero que tiene un significado semántico dudoso y posiblemente incorrecto. Por ejemplo, la frase "Mi tarea se comió a mi perro", es sintácticamente correcta, pero carece de sentido.

Una versión más avanzada de warnings pueden incluso advertirnos que nos estamos saltando estándares o buenas prácticas de programación.

Cuando me enfrento al mantenimiento de código realizado por diversos equipos de trabajo (y he de reconocer que no con menos frecuencia al creado por mi), me encuentro con que al compilar, existe un excesivo número de advertencias (excesivo son más de 200 o incluso mas). Advertencias que se han ido creando a lo largo del tiempo y que nadie se ha molestado en revisar jamás, acumulándose más y más cuanto más codificadores mueven el sistema. Generalmente nadie toca dichos warning debido al temor que entraña "mover" algo cuyo sentido desconocemos (el hecho que lo desconozcamos ya debiera hacer saltar la alarma). Bueno, si existe el warning, seguramente no tenga ningún significado oculto y simplemente es una omisión no intencional que deba ser corregida.

Los warnings se acumulan a lo largo de los años y el número dificulta entender claramente lo que nos están indicando, cuanto más warnings haya, menos casos les haremos, hasta que uno de esos warnings realmente representen un potencial problema en producción que se nos pase completamente desapercibido, convirtiéndose en un dolor de cabeza (con suerte) o en algo más grave, porque "los warnings de ahora son los errores de mañana".

Algunos warnings comunes, en este caso de C#, son los siguientes:

  • Variables que no se usan: Generalmente es una variable privada que se definió en alguna parte del código, y después de ser definida, no es usada en ninguna otra parte. Si no es usada en ninguna parte, ¿Por qué se define?, y si es necesaria, ¿Por qué no se usa?, generalmente lo correcto aquí, es eliminar la variable sin más.

  • Variables que solo se inicializan: Es un caso parecido al anterior, una variable privada que se define y a la que se asigna un valor, pero jamás se usa. Si no se usa ¿Para qué se instancia?, y si debe instanciarse ¿Por qué no se usa? La solución es borrar la variable y la cláusula de creación.

  • Parámetros que no son usados: Una función define un parámetro en su firma que no se usa en ninguna parte de su cuerpo, aquí hay un doble problema porque estamos obligando a que todas las consumidores de dicha función consideren dicho parámetro (que no sirve para nada), y por otro lado nos encontramos en un caso semejante a los anteriores, una variable que no se usa. La solución puede ser compleja en base al uso que se le da a la función, si es posible eliminar el parámetro y corregir todas las llamadas a dicha función, seria nuestra primera opción, si no podemos (y aquí debemos estar completamente seguros de no poder), se puede sobrecargar la función con los parámetros correctos, y marcar la opción con el parámetro que no se usa, como obsoleta, de esa forma los sistemas consumidores notaran dicho cambio, y deberán modificar su código, en el momento adecuado.

  • Fragmentos de código que nos son usados: Un conjunto de varias líneas de código, que nunca será ejecutado, porque el flujo de ejecución se interrumpe antes, por ejemplo si pongo código debajo de una sentencia return, nunca se ejecutara, de forma semejante si lanzo una excepción con throw. En estos casos lo mejor es tener claro el significado del código y donde debiera ubicarse apropiadamente. Si realmente no se va a ejecutar nunca, simplemente se elimina (si es un código heredado de un sistema productivo, lo más seguro es que no sirva para nada dicho código y se pueda eliminar con tranquilidad).

  • Métodos públicos que no son comentados: Tenemos un método público, que no tiene comentarios (en la cabecera del método, con la cláusula summary). Cuando un método es público, es porque deben ser consumidos por entidades ajenas a nuestro modulo, clase o sistema, esto significa que alguien que no somos nosotros necesita comprenderlo, y para comprenderlo necesita la documentación. La solución es sencilla, simplemente hay que documentar la función.

  • Métodos de una clase heredada que se llaman igual a un método de una clase base pero sin embargo no la sustituyen: En este caso tenemos dos clases, una clase base y otra heredada de la anterior. En un esquema tradicional la clase heredada podría sobrescribir métodos virtuales de la clase base, simplemente llamándose igual e indicando que se desea sobrescribir con la palabra override. ¿Qué ocurre si no especificamos a clausula override?, que el compilador no sabe que estamos queriendo sobrescribir la función o si estamos definiendo una nueva. Esto ultimo tiene extraños resultados, por ejemplo si nos referimos al objeto como la clase base se ejecutar siempre el método de la clase base y si los referenciamos por la clase heredara ejecutar el método de la clase heredada, en cambio si indicamos que deseamos sobrescribir el método, con la palabra override, siempre se ejecutara el de la clase base. El sistema lanza un warning indicándonos que debemos adornar el método con el atributo new o con el atributo override, de forma que de forma que mostramos explicita que es lo que queremos hacer (porque explicito es mejor que implícito):

    internal class ClaseA
    {
     public void Metodo1()
     {
      Console.WriteLine("Soy el metodo 1 de la Clase A");
     }
     
     public virtual void Metodo2()
     {
      Console.WriteLine("Soy el metodo 2 de la Clase A");
     }
    }
     
    internal class ClaseB : ClaseA
    {
     public new void Metodo1()
     {
      Console.WriteLine("Soy el metodo 1 de la Clase B");
     }
     
     public override void Metodo2()
     {
      Console.WriteLine("Soy el metodo 2 de la Clase B");
     }
    }

  • Condiciones que siempre va a ser verdadero o falso: Esto ocurre cuando escribimos una condición que siempre va da el mismo resultado, por ejemplo si estamos comprobando si un entero es nulo, siempre será falso puesto que un entero no puede ser nunca nulo (si un entero “Nulleable”, pero no un entero “normal”). En este caso hay que revisar cual es nuestra intención puesto que la condición siempre se ejecutara, y si tuviera una contra condición (como un else) nunca será ejecutada, lo cual no tiene sentido (tenemos validaciones que no hacen realmente nada en nuestro código).

    int i = 0;
    if (i == null)
    {
     //Nunca se ejecuta este codigo puesto que un entero no puede ser nulo
     Console.WriteLine("i es mulo");
    }
    else
    {
     //Siempre se ejecutar este codigo
     Console.WriteLine("i no es mulo");
    }
     

  • Métodos obsoletos: Este warning indica que un método que consume nuestro sistema, fue marcado como obsoleto, es decir que no va a mantenerse más y existe un nuevo método que cumple mas apropiadamente la funcionalidad de este. Puede ser que el método obsoleto se mantenga en las versiones próximas del software o que se elimine, en cualquier caso dependemos de un software que nos coloca en una situación incierta para nosotros. Necesitamos actualizar lo antes posibles a las nuevas versiones de las funciones que estamos consumiendo.

    [Obsolete("Esta función esta obsoleta")]
    public void FuncionObsoleta()
    {
     
    }
     

Actualmente hemos implementado una política de “cero warning”, esto es, cualquier modulo al que se deba realizar un mantenimiento, debe entregarse con cero warnings independientemente si los warning son preexistente a nuestro manteniendo. Una vez que se han eliminado los warning se configura el compilador para tratar los warning como errores, de forma que nuestro sistema no compilara si tiene warning pendiente de revisar, esto es útil para que no se generen nuevos warning, incluso si el equipo que mantiene el código es otro en el futuro.

Ahora bien ¿Qué pasa si realmente el warning de nuestro código es correcto? Es decir nuestro código debe programarse tal y no puede evitarse que se genere el mensaje del warning. Lo primero que hay que preguntarse si la afirmación anterior es realmente correcta, porque en nueve de cada diez ocasiones no lo será. Una vez que estemos seguro podemos limitar el código dentro de bloques pragma, que indican que no nos notifique de dicho warning (es decir que lo ignore), de esta forma no se nos mezclaran los warning que si consideramos correctos (los cuales ignoraremos) de los que no. El siguiente es un ejemplo de la directiva pragma:

// Desativa la notificacion de warning de tipo 0168 (variable no usada)
#pragma warning disable 0168
 
//Esta variable debiera generar un Warning, pero no lo hace debido a la setencia pragma
int variableSinUsar;
 
Console.WriteLine("Hola mundo");
 
 
// Vuelve a activar la notificacion de warning de tipo 0168 (variable no usada)
 
#pragma warning restore 0168
 
 
Para finalizar incluyo un enlace con descripciones de diversas referencias y warnings para Visual Studio .NET:


domingo, 19 de julio de 2015

Regla N°8 de la Ingeniería de Software: El entusiasmo da el conocimiento, el conocimiento sin entusiasmo no sirve de nada.


"La excelencia es un arte que se conquista con la práctica y el hábito. No actuamos correctamente porque tengamos virtud o excelencia, sino más bien obtenemos éstas porque hemos actuado debidamente. Somos lo que repetidamente haceos, la excelencia, entonces, no es un acto sino un hábito". Aristóteles

Uno de mis roles es el de entrevistador de candidatos a codificadores, desde esa posición ves diversos perfiles, entre ellos, dos que destacan por encima de los demás, el entusiasta sin conocimientos y el que domina todo los requisitos, pero no tiene ningún tipo de motivación. A veces es increíble que abunden estos dos perfiles por separado, y escasee el perfil que mezcle entusiasmo y conocimientos.

Si nos vemos en la necesidad de elegir entusiasmo y conocimiento debemos elegir siempre entusiasmo.

El conocimiento sin entusiasmo es, en el mejor de los casos, fortuito, y casi nunca podrá convertirse en algo útil para el negocio, en sistemas y herramientas funcionalidades que creen una diferencia significativa. En la mayoría de los casos lo único que podrá realizarse sin entusiasmo es lo que yo llamo “tareas de escuela”, programas técnicamente correctos, hechos según un enunciado claro como una receta, pero que no sirve en la práctica de absolutamente nada, que son imposibles de encajar en un ambiente laboral real. En última instancia los conocimientos, y más en esta profesión, son caducos.

La caducidad de los conocimientos en una persona sin entusiasmo es quizás el temas más importante, una persona sin entusiasmo, buscara siempre hacerse imprescindible, se estancara en su conocimiento e impidiera que su entorno evolucione, cualquier forma nueva de realizar una tarea o cualquier mejora será una amenaza a su posición y podría hacer peligra su condición de “imprescindible”, por eso las personas que solo ofrecen conocimiento y no entusiasmo acaban convirtiéndose en pesadas anclas para los equipos de trabajo.

Sin embargo una persona sin conocimientos pero con entusiasmo, obtendrá lo que necesita para su trabajo de una forma rápida y efectiva. Entre otras características posera las siguientes:

  • La mencionada capacidad para obtener los conocimientos que necesita para resolver los problema a los que enfrenta. Aprenderá, y además aprenderá muy rápido.
  • Gusto por los desafíos y por los sistemas y desarrollo desconocidos.
  • Son personas ambiciosas, pero no egoístas, las personas ambiciosas buscan el beneficio personal y generalmente también el de su equipo, destacando a través de su trabajo, as personas egoístas sin embargo solo buscan el beneficio propio.
  • No tienen miedo a enfrentarse a sistema novedosos, pero tampoco a sistema con años de mantenimiento a sus espaldas.
  • y quizás la más importante, no se quedara detenido esperando instrucciones, tiene iniciativa y es proactivo.


Empezamos esta entrada con una cita de Aristóteles, sobre la excelencia, esta cita en particular me gusta mucho porque refleja que nadie nace con dones especiales, si no es a través de su perseverancia y voluntad que adquiere estos dones, incluyendo lo necesario para poder desarrollarse correctamente en el mundo de la ingeniería de software.

martes, 14 de julio de 2015

La evolución de los videojuegos hasta convertirse en servicios


La siguiente entrada es un extracto de un texto perteneciente a una actividad calificable del master “Investigación en Ingeniera del Software” que me encuentro actualmente cursando, exactamente para la asignatura “Arquitecturas Orientadas a Servicio”.

En este extracto hablo sobre como los evolucionaron los videojuegos desde un modelo basado en el producto físico a un modelo de distribución basado en servicios.


La industria de los videojuegos en los 80 y parte lo de 90, estuvo ligada a los soportes físicos, principalmente por cartuchos especiales para cada consola. Quien tuviera el cartucho era el dueño del juego, y tanto juego, como soporte físico eran inseparables. En los 90 se popularizo el uso de discos compactos (CD), formatos ópticos, sin componentes adicionales, que eran más fácilmente transportables y almacenables. Como efecto del cambio de formato, apareció la copia de juegos entre usuarios, con lo que el producto estaba cada vez más separado del soporte físico en sí. El tema de las copias de los juegos, que no reportaba ningún beneficio a las empresas de videojuegos, tuvo curiosamente un efecto inesperado, las consolas cuyo juegos se podían copiar más fácilmente, como la Sony PlayStation, se acabaron imponiendo sobre otras en los que eran más difíciles, como la consolas de Nintendo o las de Sega.

Imagen extraída en Wikipedia


Aunque el beneficio de la venta de consolas, por los motivos antes citados, no podía duran indefinidamente, puesto que en algún momento la creación de videojuegos debiera ser retribuible.

Paralelamente al desarrollo de videojuegos de consolas, en el mundo de las computadoras personales, se comenzó a aprovechar conectividad de estas a las redes locales, para dar una experiencia interactivas entre varios usuarios (usando por ejemplo el protocolo IPX), y posteriormente sobre internet (sobre el protocolo TCP/IP). Lo juegos comienzan a ofrecer interacción entre usuarios, y aunque el juego dista mucho de ser o ofrecer servicios, se marca de alguna forma el camino en que se posteriormente se liberan los juegos y su relación con Internet.

En el año 2003, comienza a originarse un nuevo formato de distribución de videojuegos. Valve, creadora de HalfLife (popular video juego de finales de los 90), decide cambiar su modelo de venta de software, prescidiendo de los empacadores y distribuidores de software (aquellos que ponen su software en discos y cajas y lo llevan hasta las tiendas físicas para su venta) y vender a través de internet, directamente al usuario, sin intermediarios. Para ellos crearon un programa llamado Steam, que a través de una cuenta de usuario, se pueden comprar videojuegos, e instalarse automáticamente desde internet. En el caso que perdiéramos (o borrásemos) la descarga del juego, al estar asociada a nuestra cuanta de usuario, podemos volver a descargárnoslo, con lo que el soporte físico queda obsoleto y se vuelve prescindible. Aun mas, el software se actualiza automáticamente y sin intervención del usuario, con lo que prácticamente tenemos un software donde podemos tener acceso a otros software (en este caso videojuegos), en los que no tenemos que preocuparnos por instalar o actualizar ningún componente (el sistema de encarga de ello) y al que podemos acceder instantáneamente. Se ven aquí los primeros indicios de software como servicio.

El modelo de Steam ha tenido un éxito creciente a lo largo de los años. Otros creadores de videojuegos se unieron a esta tienda para poder ofrecer sus productos de una forma rápida y sencilla al usuario, además de abaratar costos. Era una plataforma ideal tanto para nuevos lanzamiento, como para distribuir viejos videojuegos descatalogados y poder seguir obteniendo beneficios económicos de ellos.



Si bien ya tenemos un escenario donde es sencillo obtener software. Steam siguio creciendo para proporcionar servicios que permiten que interactúen los videojuegos de diversas formas con los usuarios, y también permite a los usuarios interactuar entre ellos.

Entre los servicios ofrecidos para los usuarios están los siguientes:

  • Voice Chat: Chat de voz durante y fuera de las partidas para los jugadores.
  • Acceso desde cualquier computadora: El usuario no está atado a un computadora, los videojuegos están atados a la cuenta de usuario, y este podrá ejecutar estos desde cualquier computadora donde use su cuenta.
  • Steam Cloud: Permite, a los juegos que sean compatibles, guardar datos en la nube, en lugar de en la maquina del usuario. Por ejemplo los juegos pueden guardar partidas en la nube y el usuario puede continuar dichas partidas en maquinas diferentes, esto quiere decir que el usuario ya no depende de una maquina fija y concreta para su datos. Aquí vemos como uno de los principales punto de los servicios, la movilidad, se cumple.
  • Gestión del perfil del usuario.
  • Gestión de Contenido descargable.

Los servicios dedicados a los desarrolladores de software son los siguientes:

  • Sistema antipiratería.
  • Sistema de actualizaciones automáticas para los productos.
  • Reportes de venta de los productos.
  • Control de ejecución por territorio.
  • Gestión de días gratuitos e invitaciones.

El concepto de tienda e interacción entre usuarios a través de servicios, continuo en las consolas domesticas, siendo estas cada vez más dependientes de internet para realizar sus operaciones

Xbox de Microsoft, creo el servicio Xbox Live, para permitir el uso de varios jugadores simultáneamente conectados a internet, Skype para servicios de videoconferencia, compra de videojuegos en línea, además de compra y gestión de contenido descargable y por ultimo gestión de perfiles de usuario en línea. De forma semejante, Sony creo PlayStation Network (PSN) y Nintendo su red Nintendo Network.






Si bien el consumo de los videojuegos a través de las consolas se ha popularizado en los últimos años debido a la creación de nuevo hardware cada vez más potente y de cierta manera más accesible. La verdad es que fue a través de otros formatos donde los videojuegos llegaron al gran espectro de los posibles usuarios. El uso general de los videojuegos se popularizó entre sectores que nunca habían jugado en un videojuego, a través de los tablets y teléfonos inteligentes.

Videojuegos sencillos (y muchas veces basado en temáticas de antiguos juegos), se hicieron muy populares en teléfonos inteligentes y en otros medios como la red social Facebook, entre los cuales están (por poner algunos ejemplos):

  • Candy Crush Saga (y derivados)
  • Plantas vs Zombies
  • Angry Bird (y derivados)

Estos videojuegos se pueden obtener de las distintas tiendas de Android y iOS (entre otros). Y cada uno tiene características orientas a servicios, y principalmente consumen a su vez servicios, para ofrecer su funcionalidad, estas características son:

  • Se pueden obtener desde internet, de forma sencilla, así como su actualizaciones (el software siempre esta actualizado sin intervención o con poca del usuario), algunos son gratuitos, o con micro pagos (pagar cierta cuotas para obtener mayores funcionalidades en el programa).
  • Algunos se asocia a una identidad que proporciona otro servicio, por ejemplo es posible asociar Plantas vs Zombies a un perfil de Google+, igualmente se puede asociar Candy Crush a un perfil de Facebook. Esto se hace por que ambos sistemas esta preparados para consumir un servicio de autentificación de las mencionadas redes social. Con lo que es están ligando dos servicios diferentes, por un lado los videojuegos, por el otro las diversas redes sociales.




Adicionalmente el servicio de Google Play proporciona un perfil común, para que puedan ser consumirlo como servicio por los jugos que así lo deseen.


Se puede jugar en múltiples dispositivos siempre y cuando el perfil sea el mismo, el usuario podría comenzar por ejemplo una partida de Candy Crush en Facebook, y posteriormente continuar su avance en su teléfono móvil. En este punto vemos otra característica de los servicios como la movilidad, es decir los juegos no están asociados un dispositivo físico en especial, sino que son trasportables.

Lo usuarios pueden interactuar entre sí a través del mismo juego o de entras plataformas, por ejemplo es normal ver notificaciones y interacciones de diversos juegos en Facebook, a la vez que dentro del los mismos juegos es normal ver el avance de nuestro amigos de Facebook.



Imagen de Candy Crush Soda, en Facebook y en Android

Es esta entrada hemos visto como los videojuegos se apoyan cada vez en servicios, para ofrecer una experiencia de interacción y colaboración entre distintos usuarios y en el mismo juego, a la vez en la que es cada vez más común ver cómo se va progresando entre un formato físico para distribución a uno completamente digital y a demanda del usuario.

jueves, 2 de julio de 2015

Google, casos de éxito y de fracaso de sus servicios y productos


La siguiente entrada es un extracto de un texto perteneciente a una actividad calificable del master “Investigación en Ingeniera del Software” que me encuentro actualmente cursando, exactamente para la asignatura “Arquitecturas Orientadas a Servicio”.

En este extracto hablo de la evolución de Google y el enfoque se sus productos hacia una arquitectura orientada a servicios.





Google comenzó su andanza en 1998, con una simple pantalla blanca, su logo, un cuadro de texto y un par de botones para buscar en internet. A pasar de lo sencillo de su apariencia y la competencia de buscadores emergentes (mucho más sobrecargados) que existían a final de los noventas, tuvo un gran éxito, el cual aumento en los años posteriores a su lanzamiento. El secreto de su éxito fue su misma sencillez, y un algoritmo realmente potente que sabia como organizar las paginas para entregar los resultados más relevantes para el usuario en los primeros lugares de la búsqueda.

Durante los años siguientes Google desarrollaría una seria de productos y compraría otros, creando un ecosistema de servicios que interactúan entre ellos y que son ofrecidos al usuario. En la mayoría de las veces de forma gratuita.

Al principio Google guardaba preferencias y comportamientos del usuarios a través de cookies que guardaba en el navegador de la maquina donde accedía el usuario. Esto permitía seguir la actividad del usuario y personalizarse a sus gustos, pero de forma temporal debido a la duración de la vida de la cookie, además que dichas personalizaciones solo podría accederse desde una maquina, y no llevarse a otras. Todavía distaba mucho de acercase a una arquitectura orientada a servicios.

Uno de los primeros servicios de Google fue iGoogle, un portal donde el usuario podría configurar la apariencia de la página de inicio de Google, para agregarle Gadgets, y a través de estos agregar funcionalidad al portal de diversas formas, como reporte del clima, juegos sencillos o noticias, Además permitía a terceros crear Gadgets, y modificar la funcionalidad de la pagina. De esta forma y mediante la composición de servicios, se creaban a su vez nuevos servicios y nueva funcionalidad. Si bien este servicio era interesante Google decidió cerrarlo, apuntando a que ya no resultaba útil frente a otros tipos de servicios. La verdad es que le daba una apariencia semejante a sus competidores, y hacia que Google perdiera parte de la identidad basada en la sencillez. El servicio se abrió en el año 2005 y se cerró en el 2012.







En el 2004, se dio el lanzamiento de Gmail, al cual solo podría accederse mediante invitación, y estuvo en fase de beta hasta el año 2009 (aunque desde algunos años antes ya no era necesaria la invitación). El correo tenía varias características sobresaliente con respecto a sus competidores, como por ejemplo un destacable espacio para guardar los email, y un poderoso filtro antispam. El correo fue ofrecido de manera gratuita para los usuarios normales, para las empresas se ofrece un servicio especial de correo, Google Apps for Work, que proporciona correos empresariales del estilo miempleado@micompañia.com, pero la gestión de esta es llevada por Google y no por la empresa en sí. Pudiendo acceder a nuestro correos desde cualquier lugar, además de poder acceder a cualquier servicio de Google desde esta cuenta.





Imagen extraída de Google Apps for Work

La cuenta de usuario de gmail, se convirtió desde entonces en la piedra angular que nos permitía acceder a sus herramientas. A partir de su estandarización, cada servicio o software, que crearon o comprado, le integraron una autentificación a través de la cuenta y clave de gmail, de esta forma con una sola cuenta, se podía acceder a todo lo que nos ofrece Google.





A continuación haremos una breve descripción de los servicios ofrecidos por Google, así como la relación que guardan entre ellos, y analizaremos el éxito o fracaso de cada uno de ellos

Google Maps


Es una herramienta de mapas, creada en el año 2005, ha pasado por varias revisiones, evolucionando cada vez más hasta el punto de llegar a superar en cuanto a precisión y funcionalidad a los creadores de mapas digitales tradicionales como por ejemplo TOM TOM, y otros.

A parte de las funciones típicas que se esperan de un servicio de mapas digital, como calculo de rutas, posiciones y navegación, además de una base de datos de localizaciones, Maps ofrece las siguientes funciones:

  • Servicios para crear aplicaciones basadas en la ubicación del usuario.
  • Uso del servicio de mapas en aplicaciones móviles de terceros.
  • Creación de mapas personalizados: Es posible establecer ciertas características personales a nuestro mapas, como rutas concretas, formas especiales de visualización (incluyendo las posibilidad de agregar datos propios de Street View, como interiores),
  • Decisiones e información basada en ubicaciones creadas por el usuario: Como por ejemplo la "casa" del usuario, su "trabajo", otras. Algunas aplicaciones como Google Now, nos muestra por ejemplo a través de Maps, el tiempo que falta para llegar de nuestra casa al trabajo, en base a otro servicio que informa de la cantidad de tráfico, por ejemplo.
  • Integración de los mapas en nuestras páginas web.

Google News


Es un servicio que recorre diversas páginas web de noticias de diversos medios, y las agrupa en formato consistente para el usuario, mostrando lo que más podría interesarle, teniendo en cuanta además su ubicación. El servicio puede consumirse desde su misma página web y de forma más cómoda desde un dispositivo móvil





El éxito o fracaso de este servicio, depende de un factor ajeno a él y a su como tecnología, y es la legislación de cada país con respecto al consumo de noticias por parte de Google. Algunos medios consideran que al mostrar (aunque sea un enlace, junto al resumen) información de sus páginas, es consumir su propiedad intelectual, y por lo tanto Google debiera hacer un pago por dicho uso, algunos medios cifran en grandes cantidades dichos pagos. En España por ejemplo se creó la "Tasa Google" que obliga a pagar a paginas por enlazar contenido en la red con propiedad intelectual. Esto implica que Google News deba pagar a las páginas de las cuales muestra noticia, sin embargo la misma popularidad de Google, hacia popular al resto de las paginas que enlazaban, y aumentaba el número de visitantes que veían sus noticias, sin los enlaces de Google, las visitas a dichas paginas disminuirían, y por lo tanto sus ingresos derivados de dichos conceptos. Los periódicos y proveedores de noticias, que impulsaron este ley demostraron un poco conocimiento sobre cómo funciona internet y como obtener beneficios de esta, ciñéndose a un modelo de recolecta de dinero, obsoleto pero más tradicional, que a la larga les va a reportar perdidas.

Google decidió cerrar el servicio en España y algunos países de la unión Europea (para evitar tener que pagar la tasa), con lo que dichas noticias y periódicos son inaccesibles desde Google News, suponiendo una perdida para los usuarios de estos servicios y para los mismos periódicos.

La continuidad (y éxito) de este servicio depende de si se aplican esas nuevas leyes y tasas en nuevos países, y la forma en la cual se apliquen.

Google Reader






El producto Google Reader que estuvo vigente desde el 2001 al 2013, era un lector de fuentes RSS (Really Simple Syndication, un formato XML para compartir contenido, que nos avisa sobre actualizaciones sobre páginas web) , durante ese tiempo paso por varias revisiones mayores cambiando parte de sus funciones y interfaz grafica. Existía como servicio accesible desde una página web y como aplicación para teléfonos móviles.

Pese a que fue una aplicación y servicio excelente, además de tener cierta popularidad, el servicio fue discontinuado. Existe varias teorías sobre porque Google decidió prescindir de este servicio, una de ellas, es que al tener tantos servicios Google, algunos realizan funciones parecidas, en este caso Google podría hacer preferido que se compartieran contenidos a través de Google+ y no a través de Google Reader, con lo que quito los servicios que le podrían restar popularidad.

YouTube






YouTube fue un servicio creado en 2005, que permitía visualizar y compartir videos, a finales del 2006, fue comprada por Google, después de que esta liberara de forma poco exitosa su propio servicio de videos llamado Google Video.

A pesar de su popularidad, no obtuvo beneficios, hasta que Google supo como rentabilidad el sistema, a través de publicidad, convirtiéndolo un negocio de gran éxito.

El servicio permite compartir videos a través de redes sociales, visualizarla en páginas web de terceros, y agregar comentarios a los videos.

Pese a ser una servicio que enlaza contenido protegido con derechos de autor, y haber tenido en su historia varias demandas con las distribuidoras de estos contenido, ha sabido lidiar con ellas, y con esta situación, convirtiéndose en una referencia para la compartición de videos, tanto para particulares, como para empresas privadas.

Google Plus






Google Plus es una red social creada por Google en el año 2011. A través de esta red social Google da acceso a algunos servicios, para compartir contenido entre sus usuarios. Los usuarios pueden:

  • Compartir comentarios, videos y fotografías entre ellos de forma privada o pública.
  • Tener acceso a conversaciones de video, audio o texto entre ellos, por Handouts.
  • Acceder a fotografías del usuario: Estas fotos pueden ser cargadas como un backup de un dispositivo Android, o fotografías de Blogger.
  • +1: Es parecido a "me gusta" de Facebook, permite indicar desde una página web de terceros que es de preferencia del usuario, y que nuestros círculos vean dicha preferencia.
  • Servicio de autentificación: Permite usar la autentificación de Google+ para que a su vez sean autentificaciones para otros sistemas, dichos sistemas se integrarían en Google+, para usar otros servicios a su vez.





El servicio es altamente promocionado por Google (aun así no ha alcanzado la popularidad de otras redes sociales como Facebook, o Twitter) motivo por el cual parece garantizado su éxito, hasta que deje de ser interesante por Google, o lo sustituya por otro servicio, con intención de aumentar su éxito.

Google Talk y Google Handouts


Google Talk fue lanzado en el año 2005, como un servicio de mensajes y VoIP entre usuarios, fue sustituido en el año 2013 por Google Handouts, con las mismas funciones, más otras nuevas (como recepción de SMS en los dispositivos Android). El servicio es accesible desde Chrome, desde Google+ y desde los Android.

Pese a ser un software bastante completo de gran funcionalidad y haber remodelado su apariencia varias veces, no ha conseguido alcanzar la popularidad de WhatsApp, aunque este fuera un software más limitado en sus funciones y en su apariencia.

Blogger






Blogger es un servicio veterano creado en al año 1998, por Pyra Labs, la cual fue adquiera por Google en el año 2003. Blogger permite que sus usuarios compartan artículos por internet de usa forma sencilla, y rápida. El sistema se contacta a varios servicios de Google entre los cuales:

  • Google+: para la autentificación y para compartir contenido como imágenes.
  • Google AdSense: Sirve para que el propietario del blog gane dinero a través de publicidad incrustada en su página.
  • Google Analytics: Para estudiar las estadísticas del uso del blog por sus propietarios.
Al margen de eso y como muestra del uso de servicios Blogger se puede conectar a otros servicios para mostrarlos como parte de nuestro blog, esto componemos nuestro blog con servicios o "trozos" de otros proveedores de contenidos.

El servicio es bastante popular y es casi segura su continuidad, a pesar que el número de blogs activos, se ha visto reducido debido a los usuarios ahora pueden compartir contenido de forma más rápida a través de las diversas redes sociales.

Google Docs


Google Docs es una suite ofimática en la nube, que ofrece acceso a un procesador de texto, una hoja de cálculo, y creador de presentaciones.

El usuario puede acceder desde cualquier computador a través de un navegador web, e inmediatamente comenzar a trabajar.

Permite realizar un trabajo individual o un trabajo colaborativo entre varios usuarios. El documento se puede compartir, por gmail a los usuarios designados por el autor, y dichos usuarios pueden editar el documento, en distintos lugares, a través de internet. Además los cambios hechos son visualizados en tiempo real por el resto de los usuarios.

Adicionalmente el sistema se conecta con Google Drive para almacenar en la los documentos creados.

La suite es ideal para trabajar en tablet, donde puede que no tengamos un suite ofimática (como MS Office o LibreOffice) instalada localmente o simplemente tengamos una estación de trabajo fijo y queremos la movilidad de la tablet para trabajar fuera de esta.





Google Chrome





El lanzamiento de Google Chrome, fue un tanto curioso, en el año 2008, se filtro que Google estaba creando un navegador, lo que abrió muchos rumores y expectativas, finalmente Google libero una versión beta de su navegador, que a finales de año se acabo convirtiendo en una versión estable.

Google estaba acumulando una seria de servicios y aplicaciones WEB, pero dependía de otros para poder ejecutar dichos servicios, ya fuera de Internet Explorer o de Firefox. Google creó un navegador que pudiera ser el marco de ejecución de todos sus servicios, sin depender de terceros.

El navegador es actualmente uno de los más populares en cuanto al número de usuarios, gracias su rapidez, y su alta compatibilidad con los estándares HTML.

Permite además acceder a una serie de servicios mezcla de servicios web y programas ejecutados localmente, como el servicio Google Now, notificaciones de correo Gmail, y otros

Chromebook


El Chromebook, son portátiles, con un sistema operativo de nombre ChromeOS, que llegan a un paso más la idea mencionada sobre un sistema dedicado a ejecutar servicios. Si antes exponíamos a Chrome como un entorno para ejecutar servicios de Google, este es un hardware y un sistema operativos, pensados para que el portátil sea exclusivamente un consumidor de servicios en la nube.

La idea es tener un dispositivo hardware, cuyo software sean servicios en la nube, y que todo lo necesario para hacerlo funciona esta en internet, lo cual la hace muy dependiente de esta, pero por otro lado muy sencillo de manejar, al no tener el usuario de preocuparse de actualizaciones del software, ni de donde almacenar sus datos, además de ser más baratos, puesto que no requieren toda la potencia necesaria para ejecutar el software localmente.

Aunque la idea es interesante, no ha tenido gran éxito, quizás porque la gente está acostumbrada a trabajar de otras formas con sus equipos portátiles. Por el costo más barato es una buena opción para países emergentes, salvo por el hecho que en dichos países emergentes la conexión requerida para que funcionen correctamente no siempre esta disponibles. Habrá que esperar todavía un par de años para ver si esta idea tiene éxito, o queda en el olvido, ante el uso de teléfonos móviles o tablets.