Jorge Serrano - MVP Visual Developer - Visual Basic

Introducción

En las entradas anteriores, vimos como desarrollar una aplicación a partir de un problema teóricamente trivial.

Los requisitos cambian y las necesidades empresariales nos llevan a ser ágiles y adoptar cambios de manera rápida y flexible, facilitar las pruebas unitarias y en definitiva, codificar código lo más limpio posible y con posibilidades de reutilizarlo.

Hemos llegado a un punto bastante aceptable pero no es suficiente. Al menos no para unos programadores exigentes como nosotros.

Y de esta manera, hemos llegado a mencionar un conjunto de principios básicos de programación orientada a objetos… bueno, en realidad cinco principios, que reciben el nombre de SOLID.

Así que en este punto, lo mejor es hacer una pequeña pausa y hablar de esos cinco principios que deberíamos tratar de cumplir siempre que sea posible con el fin de no perdernos más adelante.

¿Es obligatorio cumplirlos?. No, pero sí es recomendable cumplirlos todos. Sino podemos cumplir todos, cuantos más cumplamos, mejor.

Empecemos entonces…

SOLID

SOLID es un acrónimo de 5 principios básicos de programación orientada a objetos que surgieron alrededor del año 2000.

También lo escucharás citar como los principios SOLID.

Cada letra de la palabra SOLID corresponde a un principio:

  • SRP o Single Responsability Principle.
  • OCP u Open/Close Principle.
  • LSP o Liskov Substitution Principle.
  • ISP o Interface Segregation Principle.
  • DIP o Dependency Inversion Principle.

Lo mejor para entender cada uno de estos principios, es verlos de forma breve y concisa.

SRP o Single Responsability Principle

Es quizás el más fácil de entender.

El concepto detrás de este principio es el de tener en mente que cada clase tenga una única responsabilidad.

Esa responsabilidad debería estar contenida dentro de la clase.

Si tenemos la necesidad de encapsular una responsabilidad en varias clases, quizás nuestra clase estuviera haciendo más cosas de las que debiera y por lo tanto, deberíamos pensar en refactorizar nuestro código para mejorarlo y llegar a cumplir este principio.

Para este principio, sólo se exige atención a los requisitos, refinamiento si procede y sentido común a la hora de hacer las cosas.

Un ejemplo sencillo podría ser el siguiente:

Partimos de una clase Coche con diferentes comandos y funcionalidades. Básicamente y para no complicarlo, tenemos la posibilidad de arrancar el motor y apagarlo, y de acelerar y frenar.

Dos variables nos indican si el coche está arrancado así como su velocidad.

Desde el punto de responsabilidad única y a simple vista, la clase Coche hace bastantes cosas.

Podríamos mejorar por lo tanto todo esto para lograr algo parecido a (en aproximación):

No pongo el código porque creo que se entiende bien, y lo principal realmente aquí es el concepto de este principio.

Como se puede apreciar, además de separar responsabilidades, podemos hacer pruebas unitarias de cada una de estas partes por separado y de todas ellas conjuntamente.

No es quizás el mejor ejemplo, pero si sirve para aclarar el concepto, con eso me conformo.

OCP u Open/Close Principle

El concepto detrás de este principio dice que deberíamos codificar nuestras clases, funciones, métodos, etc., de forma abierta a su extensión y cerrada en su modificación.

Dicho así puede que suene etéreo, así que digámoslo de otra manera.

Nuestras clases, funciones, métodos, etc., deberían permitir que su comportamiento variara o cambiara sin que tengamos que modificar nuestro código fuente.

Un ejemplo sencillo podría ser el siguiente:

El código de este ejemplo demostrativo sería similar al siguiente:

   1:      using System;
   2:   
   3:   
   4:      public class Rectangulo
   5:      {
   6:          public double Alto { get; set; }
   7:          public double Ancho { get; set; }
   8:      } // Rectangulo
   9:   
  10:      public class Circulo
  11:      {
  12:          public double Radio { get; set; }
  13:      } // Circulo
  14:   
  15:      public class CalculoArea
  16:      {
  17:          
  18:          public double GetArea(Circulo circulo)
  19:          {
  20:              return Math.PI * Math.Pow(circulo.Radio, 2);
  21:          } // GetArea
  22:          
  23:          public double GetArea(Rectangulo rectangulo)
  24:          {
  25:              return rectangulo.Alto * rectangulo.Ancho;
  26:          } // GetArea
  27:   
  28:      } // CalculoArea

Y si queremos consumir estas clases en nuestra aplicación, emplearíamos un código similar al siguiente:

   1:  CalculoArea calculoArea = new CalculoArea();
   2:  Circulo circulo = new Circulo();
   3:  circulo.Radio = 13;
   4:  Rectangulo rectangulo = new Rectangulo();
   5:  rectangulo.Alto = 3;
   6:  rectangulo.Ancho = 7;
   7:  MessageBox.Show(calculoArea.GetArea(circulo).ToString());
   8:  MessageBox.Show(calculoArea.GetArea(rectangulo).ToString());

Como podemos apreciar aquí, el ejemplo que hemos desarrollado parece estar bien. De hecho, funciona y hace lo que esperamos que haga. Así que desde el punto de vista de requisitos lo podríamos dar por bueno.

Sin embargo, si prestamos atención a lo que hemos hecho, veremos que hay algo que nos chirría… o debería chirriarnos… ¿os acordáis del primer principio SOLID?. ¿Ese que trata sobre la responsabilidad simple?. Cuando un principio no se cumple, decimos que violamos ese principio, algo que estamos haciendo aquí.

Tenemos un objeto de cálculo del área que calcula todas las áreas habidas Y POR HABER, es decir, si decidimos agregar una nueva figura geométrica para calcular su área, nos veremos obligado a modificar la clase CalculoArea.

El caso es que podríamos mejorar lo presente (quizás) dando una vuelta de tuerca.

Imaginemos entonces el siguiente diagrama de objetos refactorizando lo anterior:

Aunque a priori hemos mejorado el mantenimiento de nuestra aplicación, sabemos ya a estas alturas que no estamos delante de un marco ideal de cómo hacer las cosas. Así que si incrementamos las figuras geométricas, estaremos nuevamente delante de la necesidad de agregar otra variable dentro de la clase CalculoArea para la nueva figura geométrica además de tener que agregar en la función GetArea su correspondiente cálculo.

En resumidas cuentas, que estaremos más o menos igual que antes.

Parece evidente analizando nuestro código, que todas las figuras geométricas tienen en común algo. La necesidad o el requisito de calcular su área, nada mejor como su propia figura geométrica para saber y conocer perfectamente cuál es el cálculo de su área.

Pero aún mucho mejor si abstraemos esa funcionalidad de manera tal que si agregamos una nueva figura, cumpla con ese requisito.

El siguiente diagrama recoge esta filosofía:

Y el código de esta implementación quedaría de la siguiente manera:

   1:      using System;
   2:   
   3:   
   4:      public interface IFiguraGeometrica
   5:      {
   6:          double GetArea();
   7:      } // IFiguraGeometrica
   8:   
   9:   
  10:      public class Cuadrado : IFiguraGeometrica
  11:      {
  12:   
  13:          public Cuadrado(double lado)
  14:          {
  15:              this.Lado = lado;
  16:          } // Circulo Constructor
  17:   
  18:          private double Lado { get; set; }
  19:   
  20:          public double GetArea()
  21:          {
  22:              return Math.Pow(this.Lado, 2);
  23:          } // GetArea
  24:   
  25:      } // Cuadrado
  26:   
  27:      public class Circulo : IFiguraGeometrica
  28:      {
  29:   
  30:          public Circulo(double radio)
  31:          {
  32:              this.Radio = radio;
  33:          } // Circulo Constructor
  34:   
  35:          private double Radio { get; set; }
  36:   
  37:          public double GetArea()
  38:          {
  39:              return Math.PI * Math.Pow(this.Radio, 2);
  40:          } // GetArea
  41:   
  42:      } // Circulo
  43:   
  44:      public class Rectangulo : IFiguraGeometrica
  45:      {
  46:   
  47:          public Rectangulo(double ancho, double alto)
  48:          {
  49:              this.Ancho = ancho;
  50:              this.Alto = alto;
  51:          } // Rectangulo Constructor
  52:   
  53:          private double Ancho { get; set; }
  54:          private double Alto { get; set; }
  55:   
  56:          public double GetArea()
  57:          {
  58:              return this.Alto * this.Ancho;
  59:          } // GetArea
  60:   
  61:      } // Rectangulo

Y una aproximación de utilizar esto quedaría de la siguiente manera aproximada:

   1:  IFiguraGeometrica figuraGeometrica = new Circulo(13);
   2:  MessageBox.Show(figuraGeometrica.GetArea().ToString());
   3:  figuraGeometrica = new Rectangulo(7, 3);
   4:  MessageBox.Show(figuraGeometrica.GetArea().ToString());

Evidentemente, todo esto como podemos ver resulta mucho más simple.

Si modificamos una implementación de Cuadrado, Circulo o Rectangulo, no estaremos “rompiendo” nada de lo que ya existe.

Mejoraremos el mantenimiento, e incorporaremos pautas para reutilizar el código.

LSP o Liskov Substitution Principle

Este principio viene a decir que los objetos de una aplicación deberían ser reemplazables con instancias de sus subtipos sin que por ello tengamos que alterar el funcionamiento y la lógica de la aplicación.

Dicho de otro modo, que las funciones que utilizan referencias o punteros a clases base, deberían ser capaces de utilizar los objetos de las clases derivadas sin conocerlas.

Veámoslo con un ejemplo de aproximación partiendo del siguiente diagrama:

Y el código fuente de lo que estamos viendo quedaría de la siguiente manera:

   1:  public class Cuadrado : Rectangulo
   2:      {
   3:   
   4:          public override double Ancho
   5:          {
   6:              get
   7:              {
   8:                  return base.Ancho;
   9:              }
  10:              set
  11:              {
  12:                  base.Ancho = value;
  13:                  base.Alto = value;
  14:              }
  15:          } // Ancho
  16:   
  17:          public override double Alto
  18:          {
  19:              get
  20:              {
  21:                  return base.Alto;
  22:              }
  23:              set
  24:              {
  25:                  base.Ancho = value;
  26:                  base.Alto = value;
  27:              }
  28:          } // Alto
  29:   
  30:      } // Cuadrado
  31:   
  32:      public class Rectangulo
  33:      {
  34:          public virtual double Ancho { get; set; }
  35:          public virtual double Alto { get; set; }
  36:   
  37:          public double GetArea()
  38:          {
  39:              return this.Ancho * this.Alto;
  40:          } // GetArea
  41:   
  42:      } // Rectangulo

El consumo de este ejemplo quedaría de la siguiente forma:

   1:  Rectangulo rectangulo = new Cuadrado();
   2:  rectangulo.Alto = 3;
   3:  rectangulo.Ancho = 7;
   4:  MessageBox.Show(rectangulo.GetArea().ToString());

El resultado esperado de este cálculo sería 21, sin embargo, obtendremos 49 que sería el producto de 7 x 7, algo que en el caso del cálculo del rectángulo no es lo que esperábamos.

¿Cómo resolver el problema?.

Una posibilidad sería la siguiente:

En código, este planteamiento quedaría de la siguiente forma:

   1:      public class Dimensiones
   2:      {
   3:          
   4:          public virtual double Ancho { get; set; }
   5:          public virtual double Alto { get; set; }
   6:   
   7:          public double GetArea()
   8:          {
   9:              return this.Ancho * this.Alto;
  10:          } // GetArea
  11:   
  12:      } // Dimensiones
  13:   
  14:      public class Cuadrado : Dimensiones
  15:      {
  16:   
  17:          public override double Ancho
  18:          {
  19:              get
  20:              {
  21:                  
  22:                  return base.Ancho;
  23:              }
  24:              set
  25:              {
  26:                  base.Alto = value;
  27:                  base.Ancho = value;
  28:              }
  29:          } // Ancho
  30:   
  31:          public override double Alto
  32:          {
  33:              get
  34:              {
  35:                  return base.Alto;
  36:              }
  37:              set
  38:              {
  39:                  base.Alto = value;
  40:                  base.Ancho = value;
  41:              }
  42:          } // Alto
  43:   
  44:      } // Cuadrado
  45:   
  46:      public class Rectangulo : Dimensiones
  47:      {
  48:      } // Rectangulo

Consumir nuestras clases ahora quedaría de la siguiente manera:

   1:  Dimensiones figura = new Rectangulo();
   2:  figura.Alto = 3;
   3:  figura.Ancho = 7;
   4:  MessageBox.Show(figura.GetArea().ToString());

De esta manera y con este ejemplo, aproximamos una solución a los problemas planteados.

ISP o Interface Segregation Principle

Este principio nos indica que los clientes no deberían ser forzados a implementar interfaces que no van a utilizar.

Deberíamos tener en cuenta que si tenemos una interfaz bastante grande, deberíamos pensar en segregarla en varias más pequeñas y específicas.

Un ejemplo práctico de esto que estamos comentando en la siguiente interfaz:

Esta interfaz tiene tres métodos muy sencillos a modo de ejemplo:

   1:      public interface IDesplazarse
   2:      {
   3:          void Conducir();
   4:          void Correr();
   5:          void Pasar();
   6:      } // IDesplazarse

Sin embargo, aquí nos encontramos con una característica a tener en cuenta.

Un ser humano que va a desplazarse no tiene porqué saber conducir, o incluso a lo mejor, no tiene edad suficiente para conducir.

Imaginemos un niño de 15 años. Podrá pasear y podrá correr, pero no podrá conducir.

Así que nuestra interfaz es correcta para otro grupo de personas que cumplan todos los requisitos de la interfaz o sobre las que queramos ejecutar el método de Conducir, pero si tuviéramos una clase Persona que implementara IDesplazarse y que no pudiera conducir, se produciría una excepción ya que no hemos implementado dicha funcionalidad.

Es decir, deberíamos segregar la interfaz en más de una interfaz de acuerdo a nuestras necesidades. Y en este caso, nuestra solución quedaría de la siguiente manera:

Y el código de esta nueva implementación quedaría de la siguiente manera:

   1:      public interface IDesplazarse
   2:      {
   3:          void Correr();
   4:          void Pasar();
   5:      } // IDesplazarse
   6:   
   7:      public interface IDesplazarseConCarnetConducir : IDesplazarse
   8:      {
   9:          void Conducir();
  10:      } // IDesplazarseConCarnetConducir

Como podemos apreciar, tendremos personas que utilicen la interfaz IDesplazarse y otras que además de desplazarse conduzcan, por lo que implementarán la interfaz IDesplazarseConCarnetConducir que implementará a su vez IDesplazarse.

DIP o Dependency Inversion Principle

En este principio se enuncia que deberíamos depender de las abstracciones y no de las implementaciones. Las abstracciones no deberían depender de los detalles.

Por otro lado, Dependency Injection o Inyección de Dependencias es un método que nos permite cumplir con este principio.

Pero ciñéndonos a los ejemplos, vamos a aproximar una comprensión sobre DIP.

El diagrama que recogería esta filosofía sería el siguiente:

El código del diagrama anterior es el que se indica a continuación:

   1:      public interface IValidator
   2:      {
   3:          bool Validate();
   4:      } // IValidator
   5:   
   6:      public class ValidationManager
   7:      {
   8:          private IValidator validator;
   9:   
  10:          public ValidationManager(IValidator validator)
  11:          {
  12:              this.validator = validator;
  13:          } // ValidationManager
  14:   
  15:          public void Execute()
  16:          {
  17:              if (!this.validator.Validate())
  18:              {
  19:                  // Do Something
  20:              }
  21:          } // Execute
  22:   
  23:      } // ValidationManager

Como podemos ver aquí, dependemos de las abstracciones en lugar de las implementaciones, y todas las referencias están basadas en interfaces.

Independientemente del ejemplo anterior, también podríamos utilizar el patrón factoría (Factory Pattern) con el fin de resolver a través de ese patrón, todas las dependencias.

Introducción

Seguimos avanzando en nuestro desarrollo mejorándolo poco a poco.

Esto me recuerda a aquellos maravillosos años de la normalización de nuestras bases de datos para llegar a tercera forma normal (3NF) o llegar al éxtasis con Boyce-Codd.

Implementación de la solución

En este caso, la implementación de nuestra solución partiendo del código anterior nos sugiere partir el código en módulos o de una forma tal que nos permita depurar y mantener mejor nuestra aplicación, al mismo tiempo que podemos abordar la posibilidad de reutilizar el código.

Para llevar a cabo nuestro propósito, hemos creado un proyecto en Visual Studio que será una biblioteca de clases a la que he llamado Foo.Framework.

Dentro de este proyecto, vamos a crear nuestra lista enumerada que ya vimos en la entrada anterior, y un objeto que se encargará de llevar a cabo el proceso de lectura y escritura de ficheros de texto y documentos Excel.

Dicho de otro modo, vamos a separar algunas responsabilidades iniciales de modo que aporte diferentes beneficios.

La lista enumerada se llamará ConnectorType y tendrá este aspecto:

El código de esta lista enumerada corresponderá con lo que se indica a continuación:

   1:  namespace Foo.Framework
   2:  {
   3:   
   4:      public enum ConnectorType
   5:      {
   6:          Excel,
   7:          Text
   8:      } // ConnectorType
   9:   
  10:  } // Foo.Framework

El código dentro del cuál vamos a trabajar con ficheros de texto y documentos Excel estará alojado en una clase de nombre ConnectorProcess:

El código de esta clase es el que se indica a continuación:

   1:  namespace Foo.Framework
   2:  {
   3:   
   4:      using System;
   5:   
   6:   
   7:      public sealed class ConnectorProcess
   8:      {
   9:   
  10:          public ConnectorProcess(ConnectorType connectorType)
  11:          {
  12:              this.Connector = connectorType;
  13:          } // ConnectorProcess Constructor
  14:   
  15:          private ConnectorType Connector { get; set; }
  16:   
  17:          public string Read()
  18:          {
  19:              switch (this.Connector)
  20:              {
  21:                  case ConnectorType.Excel:
  22:                      // Excel
  23:                      return "Excel leída";
  24:                      // Hacemos algo con la información leída.
  25:                      // ...
  26:                      break;
  27:                  default:
  28:                      // Texto
  29:                      return "Texto leído";
  30:                      // Hacemos algo con el texto leído.
  31:                      // ...
  32:                      break;
  33:              }
  34:              return String.Empty;
  35:          } // Read
  36:   
  37:          public void Write()
  38:          {
  39:              switch (this.Connector)
  40:              {
  41:                  case ConnectorType.Excel:
  42:                      // Excel
  43:                      // Escribimos Excel.
  44:                      break;
  45:                  default:
  46:                      // Texto
  47:                      // Escribimos Texto.
  48:                      break;
  49:              }
  50:          } // Write
  51:   
  52:      } // ConnectorProcess
  53:   
  54:  } // Foo.Framework

Y finalmente, nuestra interfaz de usuario.

No queda otra de momento, que crear una vinculación fuerte entre nuestra interfaz de usuario y Foo.Framework, ya que vamos a utilizar las clases que tenemos dentro de ese ensamblado.

Habiendo incluido una referencia a Foo.Framework, lo que tenemos que hacer es escribir el código de nuestra aplicación y que tendrá el siguiente aspecto:

   1:  namespace UI_Sample
   2:  {
   3:   
   4:      using System;
   5:      using System.Collections.Generic;
   6:      using System.ComponentModel;
   7:      using System.Drawing;
   8:      using System.Windows.Forms;
   9:   
  10:      using Foo.Framework;
  11:   
  12:   
  13:      public partial class MainForm : Form
  14:      {
  15:   
  16:          public MainForm()
  17:          {
  18:              InitializeComponent();
  19:              // Por defecto es un fichero de texto.
  20:              this.Connector = ConnectorType.Excel;
  21:          } // MainForm Constructor
  22:   
  23:          public ConnectorType Connector { get; set; }
  24:   
  25:          private void btnSampleTest_Click(object sender, EventArgs e)
  26:          {
  27:              ConnectorProcess connectorProcess = new ConnectorProcess(this.Connector);
  28:              // Leemos la información.
  29:              string data = connectorProcess.Read();
  30:              // Escribimos el resultado del supuesto proceso anterior.
  31:              connectorProcess.Write();
  32:              // Mostramos un mensaje en pantalla tipo fake.
  33:              MessageBox.Show(
  34:                              data +
  35:                              Environment.NewLine +
  36:                              "Lectura y escritura realizada.");
  37:          } // btnSampleTest_Click
  38:          
  39:      } // MainForm
  40:   
  41:  } // UI_Sample

Como podemos apreciar, el código de nuestra interfaz de usuario se ha reducido bastante y está ahora quizás, mucho más claro que antes.

Posibles problemas

Hemos mejorado mucho algunos de los problemas detectados en las fases de desarrollo iniciales, y no decimos nada con respecto a como empezamos el proyecto y como está ahora. Sin embargo, seguimos teniendo problemas y se nos siguen ocurriendo mejoras.

El problema más molesto es quizás que nuestra interfaz de usuario tiene una relación fuerte con nuestro ensamblado Foo.Framework.

Por otro lado algo resuena en nuestras cabezas… algo denominado como principios básicos de programación orientada a objetos… en una sola palabra: Los principios SOLID.

Retomando la idea que indiqué al principio sobre 3NF y Boyce-Codd con respecto al modelado de una base de datos, SOLID es para mí su espejo con respecto a la programación orientada a objetos.

Cierto es que si queremos, podemos preparar una base de datos sin normalizar y que podemos trabajar con ella sin necesidad de llegar a 3FN o Boyce-Codd, pero que duda cabe que evitaremos problemas a largo plazo si la tenemos normalizada correctamente desde un principio.

También y por similitud, podemos desarrollar una aplicación Software sin tener en cuenta ningún principio SOLID, pero que duda cabe, que tenerlos presentes todos y cumplirlos, nos aportará beneficios notables de mantenimiento y reutilización.

La idea principal es la de adaptar nuestra aplicación a los cambios, ser ágiles ante esos cambios, y tratar de evitar que dichos cambios afecten a otras partes de la aplicación.

Pero quizás antes de seguir mejorando nuestro ejemplo, debamos hacer una pequeña pausa en el camino…

Introducción

Nos encontramos en una encrucijada.

Nuestra aplicación parecía sencilla y empezó siéndolo, pero los requisitos inicialmente marcados han variado y nos está empezando a dar algún que otro dolor de cabeza.

No obstante, hemos sabido adaptarnos a esos requisitos y hemos modificado nuestra aplicación para cubrirlos.

Implementación de la solución

La idea inicial es la de partir del código de la entrada anterior, refactorizar o acondicionar de forma general el código para que cumpla los requisitos de forma aceptable y posibilite un mejor mantenimiento del código.

Basándonos aún en una aplicación Windows, nuestro código quedará de la siguiente forma.

En primer lugar, la lista enumerada:

   1:  namespace UI_Sample
   2:  {
   3:   
   4:      public enum ConnectorType
   5:      {
   6:          Excel,
   7:          Text
   8:      } // ConnectorType
   9:   
  10:  } // UI_Sample

Como podemos ver en el código anterior, nuestra clase enumerada tiene dos valores, uno para definir los ficheros de tipo Excel y otro para los de tipo Text o texto.

De esta manera, podremos indicar el origen y destino de forma más flexible.

El código de nuestra aplicación Windows quedará ahora de la siguiente forma:

   1:  namespace UI_Sample
   2:  {
   3:   
   4:      using System;
   5:      using System.Collections.Generic;
   6:      using System.ComponentModel;
   7:      using System.Drawing;
   8:      using System.Windows.Forms;
   9:   
  10:      public partial class MainForm : Form
  11:      {
  12:   
  13:          public MainForm()
  14:          {
  15:              InitializeComponent();
  16:              // Por defecto es un fichero de texto.
  17:              this.Connector = ConnectorType.Text;
  18:          } // MainForm Constructor
  19:   
  20:          public ConnectorType Connector { get; set; }
  21:   
  22:          private void btnSampleTest_Click(object sender, EventArgs e)
  23:          {
  24:              string data = String.Empty;
  25:              // Leemos la información.
  26:              data = Read();
  27:              // Escribimos el resultado del supuesto proceso anterior.
  28:              Write();
  29:              // Mostramos un mensaje en pantalla tipo fake.
  30:              MessageBox.Show(
  31:                              data +
  32:                              Environment.NewLine +
  33:                              "Lectura y escritura realizada.");
  34:          } // btnSampleTest_Click
  35:   
  36:          private string Read()
  37:          {
  38:              switch (this.Connector)
  39:              {
  40:                  case ConnectorType.Excel:
  41:                      // Excel
  42:                      return "Excel leída";
  43:                      // Hacemos algo con la información leída.
  44:                      // ...
  45:                      break;
  46:                  default:
  47:                      // Texto
  48:                      return "Texto leído";
  49:                      // Hacemos algo con el texto leído.
  50:                      // ...
  51:                      break;
  52:              }
  53:              return String.Empty;
  54:          } // Read
  55:   
  56:          private void Write()
  57:          {
  58:              switch (this.Connector)
  59:              {
  60:                  case ConnectorType.Excel:
  61:                      // Excel
  62:                      // Escribimos Excel.
  63:                      break;
  64:                  default:
  65:                      // Texto
  66:                      // Escribimos Texto.
  67:                      break;
  68:              }
  69:          } // Write
  70:          
  71:      } // MainForm
  72:   
  73:  } // UI_Sample

Hemos preparado una propiedad para indicar el tipo de conector a utilizar.

Y posteriormente hemos llamado a una función Read y a un método Write para llevar a cabo nuestras acciones.

Indudablemente el código tiene un carácter meramente descriptivo porque faltarían más cosas como implementar la lógica de lectura y otras partes importantes de nuestra solución, pero lo importante aquí es quedarnos con la idea.

Posibles problemas

Empezamos con una aplicación para procesar archivos de texto.

Más tarde, los requisitos cambiaron y nos pedían procesar archivos de texto y Excel. Hicimos los cambios, pero nos dimos cuenta que de cara al mantenimiento, podríamos tener algún que otro quebradero de cabeza, así que hemos pensado en refactorizar un poco el código y mejorar algunas cosas.

Así surge esta tercera revisión que mejora aspectos relacionados con el mantenimiento. Además, si alguien nos pide ahora agregar otro conector como por ejemplo uno para leer y escribir en base de datos, bastará con agregar un nuevo elemento a nuestra lista enumerada y modificar Read y Write para que procesen también entradas y salidas con bases de datos.

Parece que todo está más o menos acorde con lo que buscamos, pero tenemos delante de nosotros varios problemas bastante más graves que a simple vista muchas veces no vemos.

Por un lado la separación de responsabilidades. Aquí el lema es divide y vencerás. Si queremos hacer algo que nos va a llevar mucho tiempo o proceso, lo mejor es separar en unidades pequeñas cada una de esas actividades. Pensemos por poner un ejemplo, en una línea de montaje.

Por otro lado, y en el caso de que hiciéramos pruebas unitarias, la posibilidad de probar las porciones de código por separado y centrando los esfuerzos y dedicación únicamente en aquellas unidades de Software que realmente cambian sin que estas afecten a un todo. Pensemos en que alguna parte de nuestro Software se modifica, como por ejemplo que aparece una nueva versión de Excel que afecta como es lógico al proceso de documentos Excel. Si el resto de código de nuestra aplicación funciona perfectamente, la forma en la que hemos codificado nuestra aplicación nos obliga lo queramos o no, a tocar una parte de código que entremezcla cosas que funcionan y otras que no. Además de que puede haber diferentes personas tocando el mismo código y que existen herramientas que lo permiten, es cierto que es un foco de problemas, y además, es posible que toquemos accidentalmente código que funcionaba, por lo que podemos crear nuevos problemas.

Otro aspecto a destacar y no menos importante, tiene que ver con la dependencia. Y es que nuestra aplicación depende fuertemente de unas piezas de Software que entremezclan UI con lógica de negocio y no sólo ensucian nuestro desarrollo, sino que enmaraña el mantenimiento de la misma y dificulta su depuración.

Y todo esto sin poner encima de la mesa otro de los problemas más habituales y que siempre pensamos en ellos al final, la reutilización del código realizado. En este caso, al estar todo integrado dentro de una misma aplicación como es la interfaz de usuario, su reutilización se nos antoja al menos, compleja.

¿Qué hacer entonces?. ¿Cómo resolver estos problemas?.

En la próxima entrada veremos como resolver alguno de estos problemas.

Introducción

Como vimos en el artículo inicial, nos encontramos con un problema sencillo de resolver pero que poco a poco se iba retorciendo o complicando.

Inicialmente teníamos en mente la lectura de un fichero de texto y la escritura de una información determinada después de procesarla en un fichero de texto.

Sin embargo, los requisitos cambian y ahora se nos pide que además de leer y escribir un fichero de texto, hagamos lo mismo pero con un fichero de Excel.

En realidad sería hacer algo similar a lo siguiente:

Implementación de la solución

Suponiendo que tengamos toda la lógica en nuestro formulario de prueba (igualmente ocurriría si tuviéramos toda la lógica implementada en una biblioteca de clases aunque los problemas estarían más acusados en el caso de tener todo implementado la interfaz de usuario), el código quedaría en este caso de la siguiente manera:

   1:  namespace UI_Sample
   2:  {
   3:   
   4:      using System;
   5:      using System.Collections.Generic;
   6:      using System.ComponentModel;
   7:      using System.Drawing;
   8:      using System.Windows.Forms;
   9:   
  10:      public partial class MainForm : Form
  11:      {
  12:   
  13:          public MainForm()
  14:          {
  15:              InitializeComponent();
  16:              // Por defecto es un fichero de texto.
  17:              this.EsTexto = true;
  18:          } // MainForm Constructor
  19:   
  20:          public bool EsTexto { get; set; }
  21:   
  22:          private void btnSampleTest_Click(object sender, EventArgs e)
  23:          {
  24:              string data = String.Empty;
  25:              if (this.EsTexto)
  26:              {
  27:                  // Texto
  28:                  data = ReadText();
  29:                  // Hacemos algo con el texto leído.
  30:                  // ...
  31:                  // Escribimos el resultado del supuesto proceso anterior.
  32:                  WriteText();
  33:              }
  34:              else
  35:              {
  36:                  // Excel
  37:                  data = ReadExcel();
  38:                  // Hacemos algo con la información leída.
  39:                  // ...
  40:                  // Escribimos el resultado del supuesto proceso anterior.
  41:                  WriteExcel();
  42:              }
  43:              // Mostramos un mensaje en pantalla tipo fake.
  44:              MessageBox.Show(
  45:                              data +
  46:                              Environment.NewLine +
  47:                              "Lectura y escritura realizada.");
  48:          } // btnSampleTest_Click
  49:   
  50:          private string ReadText()
  51:          {
  52:              // Abrimos el fichero y leemos su contenido.
  53:              return "Texto leido";
  54:          } // ReadText
  55:   
  56:          private void WriteText()
  57:          {
  58:              // Escribimos el fichero en su lugar destino.
  59:          } // WriteText
  60:   
  61:          private string ReadExcel()
  62:          {
  63:              // Abrimos Excel y leemos su contenido.
  64:              return "Excel leída";
  65:          } // ReadExcel
  66:   
  67:          private void WriteExcel()
  68:          {
  69:              // Escribimos el Excel en su lugar destino.
  70:          } // WriteExcel
  71:   
  72:      } // MainForm
  73:   
  74:  } // UI_Sample

Posibles problemas

Aunque lo esté exagerando un poco, la idea es la de presentar delante nuestra diferentes problemas cotidianos con los que podemos encontrarnos a la hora de desarrollar una solución a un problema planteado.

En este caso, vemos que el código se está empezando a volver insoportable de mantener.

En este punto, tenemos una variable booleana que nos va a permitir discriminar entre un fichero de texto y un documento Excel.

No siendo la mejor de las soluciones, es hasta cierto punto aceptable.

Sin embargo, ¿qué ocurre si además de Excel y texto necesitamos acceder a la información de una tabla por ejemplo para leer determinada información, procesarla y volver a almacenarla en otra tabla?.

Bien, nuestra propiedad bool la podemos hacer nullable y así tendremos tres valores, true, false y null.

Posible chapuza a la vista aunque bien, es una posible solución.

Otra posible solución es crear una lista enumerada y a partir de ella determinar el tipo de origen, destino que queremos utilizar.

Es quizás una solución más elegante.

Otra es crear una llamada por cada tipo y que se cree el objeto de cada tipo para el objetivo de nuestra aplicación, y bien… quizás así podamos llevar a cabo una solución más o menos gloriosa.

De hecho, en la próxima entrega voy a ajustar todo esto que estoy comentando para sacar adelante algo que resulte un poco más claro a la hora de leer el código… a ver si lo logro y seguimos avanzando viendo problemas y posibles soluciones.

Hasta la próxima entrega… :)

Introducción

No me voy a andar con grandes tecnicismos, más bien todo lo contrario.

Voy a ir directo al asunto y de forma concisa, planteando los problemas habituales con los que podemos encontrarnos los desarrolladores y cómo hacerlos frente.

Como avanzar y mejorar nuestro código basándonos en un proyecto teórico inicial y como ir salvando los diferentes obstáculos con los que podemos encontrarnos.

¿Seremos capaces?… ¡veámoslo!.

Punto de partida

Partiremos de un ejemplo muy sencillo de entender.

Empieza el proyecto de desarrollo y nos dicen que preparemos una aplicación que lea como entrada el contenido de un fichero de texto, y como salida, que escriba también en un fichero de texto.

Vamos a obviar de momento el proceso intermedio.

Sería algo similar a lo que se indica en la siguiente imagen:

Como podemos apreciar… algo muy sencillito de realizar.

Implementación de partida

Ante esto, la idea parece muy clara y evidente.

Vamos a crear un proyecto de aplicación Windows y sobre él vamos a llevar a cabo nuestro desarrollo.

Dentro del formulario Windows hemos insertado un control Button.

Todo muy sencillo.

El código quedaría de la siguiente manera:

   1:  namespace UI_Sample
   2:  {
   3:   
   4:      using System;
   5:      using System.Collections.Generic;
   6:      using System.ComponentModel;
   7:      using System.Drawing;
   8:      using System.Windows.Forms;
   9:   
  10:      public partial class MainForm : Form
  11:      {
  12:   
  13:          public MainForm()
  14:          {
  15:              InitializeComponent();
  16:          } // MainForm Constructor
  17:   
  18:          private void btnSampleTest_Click(object sender, EventArgs e)
  19:          {
  20:              string data = Read();
  21:              // Hacemos algo con el texto leído.
  22:              // ...
  23:              // Escribimos el resultado del supuesto proceso anterior.
  24:              Write();
  25:              // Mostramos un mensaje en pantalla tipo fake.
  26:              MessageBox.Show(
  27:                  data +
  28:                  Environment.NewLine +
  29:                  "Lectura y escritura realizada.");
  30:          } // btnSampleTest_Click
  31:   
  32:          private string Read()
  33:          {
  34:              // Abrimos el fichero y leemos su contenido.
  35:              return "Texto leido";
  36:          } // Read
  37:   
  38:          private void Write()
  39:          {
  40:              // Escribimos el fichero en su lugar destino.
  41:          } // Write
  42:   
  43:      } // MainForm
  44:   
  45:  } // UI_Sample

Posibles problemas

La solución anterior no está mal, sin embargo, puede presentarnos a futuro una serie de problemas que dependiendo de la complejidad del proyecto y otras circunstancias como por ejemplo si el código de nuestra aplicación cambia frecuentemente, etc., puede acarrearnos serios contratiempos.

Por otro lado, el principal problema que aporta el ejemplo anterior, sería el mantenimiento de la solución propuesta.

Mezclar lógica e interfaz de usuario debería ponernos los pelos como escarpias de antemano.

En otro orden de cosas, separar la lógica en una biblioteca de clases para apartarla de la interfaz de usuario, podría resolver parte de este problema, pero se nos presentación otro adicional.

¿Qué ocurriría si en lugar de querer leer desde un fichero de texto y escribir en un fichero de texto queremos cambiar ese fichero de texto por una hoja Excel?.

Esto es lo que resolveremos en la siguiente parte del artículo siguiendo con la inercia de desarrollo marcada aquí.

Introducción

El título es un poco largo, sí, ya lo sé, pero viene al caso de una serie de problemas que me han ocurrido y que he resuelto uno detrás de otro.

Comento la situación.

En mi mano he tenido tres terminales móviles con Windows Phone 7 (un LG E900 Windows 7 y dos Nokia Lumia 800).
Ambos han funcionado perfectamente, pero les he hecho alguna que otra perrería como es lógico.
Entre esas perrerías, reiniciarlos, resetearlos, actualizar firmwares, etc.

Todos los he registrado y desbloqueado para depurar aplicaciones Windows Phone desde mi Visual Studio, pero durante todo ese proceso, he cometido algún error que otro que he descubierto ahora y del que aquí expongo la solución.


Desbloqueo de un Windows Phone

Sólo a modo informativo y para aquel que no lo sepa, para desbloquear un Windows Phone y poder depurar aplicaciones Windows Phone en Visual Studio, deberemos desbloquearlo.

Para desbloquearlo, Microsoft proporciona una aplicación denominada Windows Phone Developer Registration, que puede ser encontrada en el SDK de Windows Phone 7 ó Windows Phone 8.

Esta herramienta detectará si tenemos conectado un Windows Phone 7 ó un Windows Phone 8.

Al hacer clic sobre registrar nuestro dispositivo, el proceso de desbloqueo se iniciará.

Si todo va bien, veremos que aparecerá un mensaje indicándonos que nuestro dispositivo ha sido registrado correctamente, sin embargo y en mi caso, me indica que ya tengo un dispositivo desbloqueado con el mismo nombre.


Mi primer error

Mi primer error ha sido llamar al terminal Nokia Lumia 800 igual que mi antecesor LG E900 Windows 7.
El LG está de backup ahora mismo, pero fue mi primer Windows Phone y con él he estado trasteando con Visual Studio y demás.

El hecho es que a la hora de registrar mi dispositivo, la herramienta de desbloqueo detecta, como decía anteriormente, que ya tengo registrado un dispositivo con el mismo nombre.

¿Cómo resolver este problema?.

La solución más sencilla no es la más óptima, y consistiría en reiniciar el terminal a fábrica y una vez así, cambiar el nombre del dispositivo. Otra posible solución sería sincronizar con Zune por primera vez el terminal y cambiar el nombre del terminal ahí, pero hay una solución más elegante que veremos a continuación.

El caso es que si acudimos a la web de Microsoft de Windows Phone (https://www.windowsphone.com) y accedemos con nuestra cuenta Passport, observaremos que en la sección Account settings de nuestra cuenta, encontraremos todos los dispositivos registrados para esa cuenta.

Lo sorprendente en mi caso, es que tengo dos dispositivos móviles con el mismo nombre.

Y claro, no tengo ninguna gana de reiniciar mi terminal a su estado inicial de fábrica.

Si accedo al terminal, tampoco encuentro dentro ninguna posibilidad para cambiar el nombre de ningún terminal, y en esta web tampoco encuentro nada.

Bien... pues como decía antes, hay una forma cómoda y elegante para resolver este problema.


Solución al primer problema

La solución consiste en acudir a Zune y dentro de Zune y con el dispositivo conectado (obviamente), ir a Setting del dispositivo.

Dentro de la configuración del dispositivo, acudiremos a la opción NAME YOUR PHONE, y allí, podremos ver el nombre actual de nuestro dispositivo y cambiar su nombre.

Ala,... ya estamos listos para desbloquear nuestro dispositivo móvil, así que volvemos a ejecutar el proceso de la herramienta Windows Phone Developer Registration.


Mi segundo error

Antes comenté que había estado trasteando con diferentes dispositivos móviles y con Visual Studio, así que eso significa que he desbloqueado una gran cantidad de dispositivos móviles con mi cuenta Passport.

Algo en lo que no he reparado...

El caso es que después de volver a ejecutar la herramienta de desbloqueo del terminal, me encuentro con otro mensaje nuevo.

En este caso, el problema es que tenemos desbloqueados más terminales de los que podemos.

Así que acudo a la Web anterior y trato de eliminar aquellos terminales que ya no uso dentro de la sección Account settings, y vuelvo a intentarlo, pero nada... sigo en las mismas.

Sin embargo, y una vez más... hay solución y no es esta última, sino otra nueva y diferente. ;)


Solución al segundo problema

La solución a este segundo problema no reside en ir a la Web que indicaba anteriormente, sino en ir a otra Web diferente que desde mediados del año 2012, sustituye al App Hub de Microsoft.

Esta Web es la web de desarrollo de Windows Phone (https://dev.windowsphone.com).

En esta web podemos subir nuestras aplicaciones Windows Phone, descargar el SDK para desarrollar aplicaciones Windows Phone, y acceder a los detalles de nuestra cuenta.

Allí debemos registrar a nuestra cuenta y a la subsección Phones.

Si nos fijamos bien en esa web pone: "Maximum number of phones you can register: 3".

En caso es que yo tenía 3 terminales ya registrados y 2 de ellos anticuados, así que he eliminado dos de ellos y he vuelto a intentar ejecutar la herramienta de desbloqueo Windows Phone Developer Registration.

Ahora sí, el terminal se ha desbloqueado perfectamente.

Y si nos fijamos en la sección anterior, veremos que nuestro terminal se ha registrado correctamente.

De hecho, podemos fijarnos en otra columna de datos de esa sección que indica si ha expirado la fecha de desbloqueo o no, para reiniciar el proceso de desbloqueo en ese terminal (en mi caso tengo ya un terminal con fecha expirada tal y como se puede observar).


Espero que todo esto le ayude a alguien que se encuentre con estos problemas o problemas parecidos.

Publicado por Jorge Serrano | con no comments

Introducción

A los que nos gusta los juegos de coches y la Xbox, casi se nos hace indispensable disponer de un mando que nos haga vivir con mayor realismo todo lo que acontece en esos juegos.

Una buena forma de lograr ese realismo sin llegar a unas cotas excesivamente frikis, es adquiriendo un volante.

La entrada de hoy es un poco friky, y trata sobre una experiencia personal y como lo he solucionado por si a alguien más le pasa y no sabe o no se atreve a hacer lo que yo he hecho.

 

Tipos de volantes

Dentro del amplio abanico de volantes que hay en el mercado para las consolas Xbox, hay algunos modelos que poseen force feedback y otros no. Mi consejo es que para tener una sensación más realista en la conducción, vayas a por un volante con force feedback. Notarás la diferencia.

Y dentro del mercado de volantes (los que tienen force feedback y los que no), los hay desde aproximadamente unos 60 € hasta los nada menos que 600 € dependiendo del acabado y calidad, y todo esto, sin contar con los asientos, soportes y pantallas donde nos tendríamos que rascar del bolsillo desde 1200 € sólo en asiento y soportes, hasta arriba sumando a esa cantidad las televisiones o monitores aparte.

Pero si tienes dinero pero no sabes por donde empezar, no te preocupes,… lo tienes fácil con este configurador que te facilitará la tarea de elegir todo lo que quieras.

Pero para los que no estamos sobrados de dinero y soñamos con una lotería para lograr ese sueño, debemos ser más modestos, como el ya desaparecido HRT F1 Team y buscar piezas de segunda mano y dejarlas lo más vistosas posibles para que hagan su función de entretenimiento.

Así que puesto que la primera premisa no la cumplo (el dinero), tendré que buscar algo más adecuado a mi economía.

 

El volante que he decidido comprar

Para ello, hay en el mercado un tipo de volante muy perseguido por su calidad/precio. Hablo del volante oficial de Microsoft (el que indico en la portada de esta entrada y que se llama Microsoft Xbox 360 Wireless Racing Wheel),… sin embargo, ese volante fue descatalogado por Microsoft y su fabricación es inexistente (tanta imitación de tableta y similar y ¿porqué los chinos no se han puesto con esto?).

He buscado y buscado, y está o agotado en todos los sitios y sin espera de stock por parte del fabricante, o a unos precios tan prohibitivos que casi me sale mejor pedir un crédito al banco (si me lo diera) y optar por la solución cara que exponía anteriormente.

Desconozco porqué Microsoft decidió no seguir con la fabricación de ese volante. Quizás quisiera publicitar únicamente la Xbox entre los amantes de los juegos de conducción y el volante no saliera rentable, pero son/somos muchos los que lo hubiéramos comprado nuevo hoy.

Como ese no es el caso y es imposible comprarlo nuevo, siempre hay un sitio en el que buscar… y no, no es ningún estercolero o basurero, sino el mercado de segunda mano donde los precios rondan entre los 75 € y los 120 € en España, hasta por 400 € fuera de España (en eBay por ejemplo).

Personalmente considero un precio de 100 € caro, así que ya no digo nada con respecto a los 120 €, mientras que el precio entre 75 € y 90 € lo considero un precio justo, aceptable y acorde al mercado con respecto a un producto obsoleto ya.

Sé que este volante llegó a costar algo más de 200 € en su tiempo, pero han pasado 4 años y ya no vale eso, y menos con el uso que algunas personas les da a los volantes.

 

Mi volante

En mi caso, me han ofrecido el volante por 120 € (no me ha interesado a ese precio), y más barato que esa cantidad. Al final he obtenido uno que me ha parecido tener un precio razonable dentro del baremo normal.

Sin embargo, este tipo de hardware tiene un problema. Su uso. O mejor dicho, el uso que le haya dado el dueño.

El que he comprado tiene el volante en bastante buenas condiciones.

El soporte que acopla el volante a la mesa también estaba en buenas condiciones.

Pero la pedalera… bueno, en realidad el plástico que recubre alrededor a los pedales, estaba arañado e incluso manchado de rotulador rojo y negro.

Entiendo como normal que la gente que acostumbra a vender las cosas de segunda mano, le da un lavado global o superficial al producto para que la entrega esté vistosa, pero en mi caso, me llegó que daba pena verlo. Quizás sea muy exigente, pero realmente no era lo que me esperaba porque denota poca seriedad por parte del vendedor.

Estuve a punto de devolverlo pero decidí quedármelo.

Sin embargo, ni el volante ni el soporte ni los pedales, tenían el aspecto estético que me gustaría que tuviera, así que me puse a limpiarlo de pegotes de pintura, polvo y suciedad típica de haberlo tenido en un trastero, descuidado o haber soportado las inclemencias de una obra.

Lamentablemente no hice fotos del estado inicial, pero tengo testigos que pueden corroborar lo que comento.

 

Limpieza

Lo primero que hice fue limpiar el volante, los cables, el soporte que une el volante a la mesa y los pedales.

Para ello, hice una visita al chino del barrio y por 6,5 € adquirí todo esto:

El contenido es muy simple:

  • Un bote de alcohol.
  • Algodones.
  • Toallitas de bebé.
  • Protectores adhesivos para la base de los pedales a la hora de ponerlo al suelo (faltaban dos de los cinco que tiene de fábrica).
  • Pintura blanca para plásticos.

Para esta primera fase, utilicé todo menos los protectores adhesivos y la pintura.

Lo que hice fue limpiar todas el hardware de modo que quedara lo más limpio posible, quitando restos de pintura, rotulador y algún que otro resto de suciedad.

Una vez finalizado todo el proceso, todo el hardware quedó bastante limpio y saneado.

La primera fase la repetí unas cuantas veces.

 

Fase de pintado

En la fase de pintado me he decantado por la utilización de un spray de color blanco mate, en esmalte sintético y con código de color 9010.

Mi bote de pintura lo podéis encontrar en esta web.

Y más concretamente aquí.

El objetivo, pintar el borde blanco que recubre a los pedales que es la parte que estaba arañada del uso.

Para llevar acabo esta tarea, he puesto cinta adhesiva en la zona gris de los pedales y he cubierto los pedales para que a la hora de pintar con el spray no se pinten de blanco claro está.

Después de una primera mano de pintura, el aspecto de esta parte era este:

Sin embargo, le he dado hasta 4 manos de pintura con el spray con el fin de que la pintura refuerce más su acoplamiento a la base de plástico.

 

Fase de fijación

Sin embargo, el proceso no finaliza con la fase de pintado, así que se requiere dar el punto definitivo de fijación, algo que he dado con un spray de barniz acrílico satinado que me ha costado 2,5 € más.

En concreto, el que he usado es este:

Se trata de un barniz satinado con código S199 que sino estoy equivocado, es el que equivale a este en la web del fabricante.

Después de repetir la operación de barnizado sobre la superficie de dos a tres veces, el resultado es este:

Realmente se aprecia poco en la imagen y aprecia mucho mejor en la realidad.

 

El resultado final

De hecho, uno de los errores que se tienen a la hora de comprar este tipo de volantes (lo aviso para que a otros no les pase), es que las fotos que te envían los vendedores respecto a este producto engañan con respecto a la realidad, y una cosa es la imagen que te envían y otra la de verdad, la que ves tú con tus propios ojos que es cuando ves lo detalles.

El vendedor no me envió ninguna foto trucada, pero lógicamente no se apreciaban bien los detalles del poco cuidado que se tuvo y el flashazo no ayuda a detectar esos detalles (fallo mío).

Tanto es así, que la imagen que me envió el vendedor de los pedales era esta:

Y ahí no se muestran ni las manchas ni churretes que tenía, ni los pintarrajos rojos y negros, ni los arañazos. A simple vista parece que estaba todo ok, pero no era así (volvedme a llamar meticuloso).

Pero nada que dos o tres pasadas de algodón con alcohol y toallitas de bebé no quiten, pero claro… siempre te llevas un poco de decepción por no haber recibido toda la información sobre el estado del producto.

El caso es que ese es el antes, y aquí va el después de todo el proceso de limpiado y fijación:

Como se puede apreciar, el aspecto es mucho más vistoso.

Un detalle principal del logo de Xbox 360 para que se vea algo de detalle del proceso finalizado:

 

Mejoras

Sin embargo, creo que el proceso puede mejorarse.

En mi caso no soy ningún experto en todo esto, y alguna motita de polvo se ha alojado a la pintura.

La idea es hacer esto en un lugar seco y cerrado, pero yo lo he hecho en un lugar abierto y con viento, así que reconozco que no lo he hecho en las mejores condiciones. Aún y así, no lo quiero para ninguna exposición, y seguramente ensucie el soporte una vez apoye sobre él mis pezuñas.

El resultado no obstante ha sido más que satisfactorio, sin embargo, la base de barniz que le he aplicado no me termina de convencer, y si dejo el dedo apretado unos segundos se marca un poco la huella dactilar con el efecto de la presión y el calor del dedo. Como estoy escribiendo esta entrada a las pocas horas de haber finalizado el proceso, es posible que le falte reposo o bien que necesite un tipo de barniz diferente.

No obstante, la huella dactilar la he quitado fácilmente con un algodón humedecido muy muy poco en alcohol, pero sigo pensando en que el proceso necesita una mejora o simplemente tiempo. Eso lo veré en los próximos días.

Espero que le sirva a alguien mi experiencia.

Publicado por Jorge Serrano | 2 comment(s)
Archivado en:

Introducción

A la hora de diseñar nuestras aplicaciones en Windows 8, es posible que nos encontremos con la necesidad de preparar una maqueta de estilos y formas respecto a nuestra aplicación. Lo que vulgarmente se denomina prototipo (en su fase inicial).

Como todos sabemos, lo ideal es hacer un fake, pero muchas veces y para ganar tiempo, es preciso hacer o preparar unos wireframes o prototipos que compartiremos con nuestro equipo de trabajo (desarrollo + UX).

Sin embargo, en muchas ocasiones se nos pide incluso más flexibilidad y menos tiempo para hacer o preparar grandes florituras, es decir,… hacernos una idea rápida de como va a ser nuestra aplicación.

¿Cómo salir adelante cuando los plazos aprietan, y se pide flexibilidad y rapidez en la toma de decisiones?.

 

Wireframe templates para PowerPoint

Sí, no me he vuelto loco.

Si se nos pide flexibilidad y rapidez a la hora de discutir con el cliente o con el equipo como podría ser nuestra aplicación Windows 8, no lo dudemos… hacerlo con el Notepad quedará más cool, pero nos llevará mucho más trabajo, y hacerlo con Visio y PowerPoint nos quedará muy vistoso, no será tan friky pero nos llevará mucho menos tiempo.

En este caso, vamos a utilizar PowerPoint, y para ello, unas plantillas gratuitas que generosamente nos ofrece Andreas Wulf y Austin Andrews.

Estas plantillas las podrás encontrar en este enlace.

 

Espero que sean de utilidad.

Publicado por Jorge Serrano | con no comments
Archivado en:

Introducción

Cuando deseamos migrar una base de datos de SQL Server a SQL Azure, experimentaremos diferentes fases de sentimientos encontrados, y es que pasar estructuras de tablas, relaciones, datos maestros y otras partes, desde una base de datos SQL Server a SQL Azure no es tarea fácil.

Sin embargo, tenemos una herramienta que nos va a facilitar enormemente las cosas para que esa transición y esa carga sea lo menos pesada posible y sí lo más liviana y ligera posible.

Esta herramienta es SQL Database MW o SQL Database Migration Wizard si se desea emplear el nombre largo de la misma.

 

¿Qué es SQL Database MW?

Esta herramienta gratuita nos facilitará la tarea de migrar bases de datos en SQL Server 2005, 2008 y 2012 a SQL Azure.

Existen dos versiones:

SQL Database Migration Wizard v3.x.x que requiere SQL Server 2008 R2 SP1.

SQL Database Migration Wizard v4.x.x que requiere SQL Server 2012.

 

¿Dónde localizar SQL Database MW?

Esta herramienta la podemos localizar en codeplex.

 

Ejecutando la herramienta

Lo primero que tenemos que hacer, es descargar los binarios de la herramienta y descomprimir los archivos de la misma en una carpeta.

Una vez hecho esto, ejecutaremos la aplicación (en mi caso, la versión 3.9.9.1 y el fichero SQLAzureMW.exe).

La aplicación se mostrará en una ventana similar a la siguiente:

En nuestro caso, voy a migrar una tabla con datos de SQL Server a SQL Azure para lo cual, seleccionaré la opción de Analyze/Migrate y en concreto, la primera opción Database.

A continuación, pulsaremos el botón Next.

Una vez hecho esto, aparecerá una ventana para establecer la conexión con la fuente origen de datos.

Seleccionaremos el servidor y las características de conexión correspondientes.

Como se puede apreciar, adicionalmente he decidido indicarle a la herramienta, que me muestre todas las bases de datos de dicha conexión para indicarle la que quiero migrar.

Otra opción es seleccionar la opción Specify Database para indicarle el nombre concreto de la base de datos, pero la opción Master DB es la opción más cómoda.

Estableceremos la conexión pulsando el botón Connect y aparecerá una nueva ventana con el listado de todas las bases de datos.

Seleccionaremos la que queremos migrar.

Pulsaremos el botón Next para continuar.

Aparecerá una nueva ventana que nos permitirá seleccionar las partes de objetos de SQL Server que queremos migrar.

En principio y para mi prueba, he decidido seleccionar todos los objetos.

Una vez resuelto este punto, volveremos a pulsar el botón Next.

Aparecerá entonces, una nueva ventana con un resumen de los objetos seleccionados anteriormente.

Una vez más, pulsaremos el botón Next.

Aparecerá una ventana de diálogo que nos preguntará si deseamos crear el script o no.

Pulsamos afirmativamente y la herramienta empezará a preparar el script por nosotros.

Una vez finalice el proceso, podremos revisar el informe de generación del script y el script en sí.

Si queremos, podemos guardar esta información o pasar de ella como voy a hacer yo en esta demostración.

Como todo el rato hasta ahora, volveremos a pulsar el botón Next.

En este momento, seleccionaremos la conexión destino con nuestra base de datos SQL Azure y estableceremos la conexión correspondiente al igual que hicimos para el origen de datos en SQL Server.

Una vez que hemos indicado los datos de conexión con SQL Azure correspondientes, haremos clic en el botón Connect.

Si todo ha ido tal y como se espera, la aplicación nos mostrará un listado de las bases de datos de SQL Azure.

La base de datos ya la tengo creada y lo que voy a hacer es pasar las tablas de SQL Server a SQL Azure, así como sus datos, etc.

Por lo tanto, una vez seleccionada la base de datos del listado anterior, haremos clic en el botón Next.

Aparecerá una ventana de notificación preguntándonos si queremos ejecutar el script contra el servidor de SQL destino (nuestro SQL Azure), a lo que responderemos afirmativamente.

El proceso de migración dará comienzo y se empezarán a pasar datos.

Si todo va bien, el proceso finalizará sin ningún error después de unos minutos.

Ya solamente tenemos que hacer clic en el botón Exit para cerrar la aplicación.

Como vemos, se trata de una herramienta muy sencilla de utilizar y que nos ahorra mucho tiempo y muchos pasos, asegurándonos un proceso rápido, seguro y limpio.

Si ahora abrimos SQL Server Management Studio por ejemplo e indicamos los parámetros de conexión (servidor, usuario y contraseña), podremos probar que los datos han sido migrados correctamente y todo está según lo esperado.

Publicado por Jorge Serrano | con no comments
Archivado en:

Introducción

El hecho de que me haya animado a escribir esta entrada, es debido fundamentalmente a que en dos días prácticamente seguidos, he tenido la oportunidad de charlar con dos compañeros distintos de trabajo sobre un tema concurrente en el tiempo:

La fidelidad de los clientes en las compañías en las que consumen bienes y servicios y lo que estas aportan a los clientes fieles.


Poniéndonos en situación

Creo que de todos es sabido (y sino ya lo sabes a partir de ahora), que una de las primeras premisas que te explican en marketing es que hacer un cliente cuesta mucho esfuerzo y dinero, y perderlo muy muy poco.
Sin embargo, cuando pierdes un cliente por insatisfacción, engaño o molestia, en un porcentaje que se acerca al 100%, ese cliente lo habrás perdido para siempre salvo contadas, raras y excepcionales ocasiones en las que regresa a ti nuevamente.
Una de esas situaciones extraordinarias en las que un cliente insatisfecho regresa es que la competencia a la que se haya ido sea la única existente en el mercado, e incluso peor que la empresa de la que se fue, algo que por desgracia ocurre en no pocas ocasiones.

Un baremo que se estudia mucho en marketing para tomar el pulso de los clientes son los resultados del llamado análisis de satisfacción del cliente.
Se trata de un baremo bastante útil, sí, pero muchas empresas lo miran por encima o no lo analizan con mayor profundidad y no entienden que dentro de la satisfacción del cliente existen varios niveles diferentes, siendo el más alto el de la satisfacción completa del cliente, un valor muy difícil de alcanzar realmente, ya que estamos hablando de la excelencia, algo a lo que se debería tender como meta única.
Es precisamente en esa amplia horquilla en la que se mueve la satisfacción del cliente a la que no se le presta siempre la misma atención y sobre la que muchos clientes deciden cambiar de empresa o compañía.

Pero esto no es extrapolable solamente al consumo, también ocurre algo parecido con los propios empleados de una empresa y por eso muchos de ellos terminan cambiando de empleo.


Objetivos de una empresa

Regresando al tema principal que nos ocupa, una empresa no es una ONG y se nutre de balances económicos, beneficios, pérdidas, inversiones, etc, por lo que cada vez que hablamos de satisfacción del cliente, debemos tener en cuenta dos vías fundamentales para aportar esos valores positivos a la compañía.

Una primera vía estaría formada por la consecución de nuevos clientes. Esto se consigue de muy diferentes maneras.
Como dije antes, conseguir un nuevo cliente suele costar tiempo y dinero, pero algo que se obvia y que es fundamental igualmente es el boca a boca. Pero para todo ello, la imagen actual de marca y empresa es vital.
La imagen de marca y la percepción de los potenciales consumidores se puede lograr a base de esfuerzos como por ejemplo el establecimiento de canales de comunicación adecuados y más efectivos, la mejora de la red de ventas, el posicionamiento de la marca, etc.

Una segunda vía estaría formada por los clientes y consumidores actuales de la marca.
Es indudable que un cliente actual es el que está consumiendo nuestros productos, por lo que esa incógnita la podemos despejar centrándonos únicamente en la incógnita de lograr vender a ese cliente más productos.
Sin embargo, si un cliente actual no está completamente satisfecho y tratamos de venderle un producto, se puede producir un efecto contrario de rechazo decidiendo en ese mismo momento, cancelar nuestra relación.

En todo caso, una empresa debe tener siempre presente que haga lo que haga va a perder clientes, porque nunca puedes satisfacer todas las demandas.
El éxito para una empresa es tener un ratio menor del 2% de pérdida de clientes. De esta manera, un 5% por ejemplo es normalmente una cantidad bastante grande de pérdidas y denotan un problema a medio plazo.


Objetivos de un cliente

Un cliente por su parte puede ser de diferentes tipos.

Existen los clientes que consumen un producto y no vuelven a tener contacto con la marca más veces..., o si la vuelven a tener es después de muchísimo tiempo para repetir la operación. Son los clientes Guadiana.

También tenemos a los clientes que después de consumir un producto y quedar satisfechos, vuelven a repetir la operación, o que incluso estando satisfechos y sin ánimo de consumir al menos de momento más que lo que ha consumido o tiene contratado, son tentados por la competencia y no tienen ninguna intención de cambiar porque están vinculados sentimental o de alguna otra manera con la compañía, marca, etc.

En tercer lugar tenemos a los clientes insatisfechos que continúan consumiendo servicios o productos, más por inercia que por otra causa especial. Son clientes denominados residuales.

Finalmente, tenemos también a los clientes que en un estado insatisfecho han decidido cambiar de empresa.


Y aquí estamos...

Y después de todo lo comentado anteriormente (y me he ahorrado muchos detalles para no parecer esto una clase de marketing), viene la realidad. Al menos en España.

Pregunta directa.
¿Porqué las empresas consideran o priorizan la contratación de nuevos clientes en lugar de potenciar la satisfacción del actual cliente?.

Y es que también es sabido que cuando un cliente consume un producto, se da por hecho que salvo que la caguemos, raramente va a cambiar y se va a ir con la competencia (¡error!).
También es frecuente el hecho de que muchas empresas se centren en hacer cartera de clientes y meterlos en su CRM para enseñarles a los inversores cuantos clientes se han hecho, eso sí... a costa de gastar mucho dinero... perdón... a costa de tirar el dinero quería decir (¡error!).
También es un mito pensar que el cliente lo será para toda la vida... (¡error y de los gordos!).

Vivimos en un mundo globalizado, y por lo tanto, cada vez el consumidor posee mayores oportunidades. Un ejemplo de esto son las ventas por Internet. Hay productos como la luz, el agua o el teléfono que hoy día no se pueden consumir por Internet, pero existen otros productos que sí.

Pero pongamos ejemplos reales a todo esto.

El ejemplo más típico de todo lo comentado anteriormente lo tenemos con las empresas de telecomunicaciones en España.
Desde la liberalización de las telecomunicaciones en el año 1998, el marco comercial apenas ha cambiado.
Este año 2013 se prevé la liberalización de la energía principalmente y veremos que ocurre, pero mucho me temo que copiarán el mismo marco o modelo comercial de agresividad en el que se ha movido el de las telecomunicaciones y en el que lo más importante es hacer clientes, y cuantos más mejor, sin importar cuantos clientes actuales se pierden, así que los clientes estarán saltando de una compañía a otra como si estuviéramos salteando guisantes en una sartén.

En telecomunicaciones hoy día, un cliente de toda la vida de una operadora recibe menos beneficios que un cliente que decide hacer la portabilidad. Incluso ha habido personas que han estado pegando saltos de portabilidad en portabilidad en busca no de la mejor oferta, sino de sacar terminales de última generación al mejor precio (aka gratis).
Las empresas de telecomunicaciones que estaban ávidas por hacer clientes, entraban en esa dinámica porque comercial o estratégicamente las interesaba, y así hemos estado en estos últimos casi 15 años.

Como ejemplo me citaré a mí mismo que estando en Telefónica (Movistar) desde hace creo recordar algo más de 15 años ya (que tiempos aquellos del Moviline), no he recibido NUNCA ninguna oferta o regalo de un terminal de última generación.
Sin embargo, si siendo cliente Movistar me voy a otra operadora y elijo la portabilidad, esa operadora sí me regala ese terminal que añoro tener si le prometo fidelidad durante 12, 18 ó 24 meses.
Es decir, me presta mayor atención y mimos una nueva compañía con la que nunca he hecho tratos que mi compañía de toda la vida. ¿Curioso?.

Y es que muchas compañías se olvidan de una cosa.
La primera y más importante es que un cliente es MÁS IMPORTANTE que un futuro cliente, y que un cliente contento y satisfecho es un potencial escaparate para animar a otros amigos o conocidos a entrar a formar parte del grupo de consumidores de una empresa.
¿Qué creen que comentaré en una reunión informal cuando uno de mis amigos enseñe todo ilusionado y contento el nuevo terminal que ha obtenido gracias a la portabilidad que ha realizado desde el operador A al operador B?.
Pues simple y llano... "En Movistar son unos ratas".
A lo que otro amigo me dirá... "En Vodafone estamos igual".
Y otro dirá... "En Amena no somos distintos".
Y finalmente otro más dirá... "¡Anda!, ¿y qué os creéis que pasa en Yoigo?".
Vamos... que sólo te queda una alternativa... hacer como tu amigo y portar tu número a otra compañía y dejar la compañía telefónica de toda la vida.

Otro ejemplo.
Una empresa que tiene seguros médicos y que siendo cliente de ellos desde hace años, te invitan a salirte de la compañía y cancelar el seguro para volver a contratarlo y poder así aprovechar una de las ofertas de promoción que tienen para... ¡¡¡NUEVOS CLIENTES!!!.
Vamos... que le importa un rábano que seas cliente actual de la compañía, porque lo que quieren comercialmente es tener un contador que sume un +1 a "nuevos clientes", aunque sea a costa de poner un -1 a clientes actuales, porque el inversor de turno no va a ver, prestar atención o contabilizar esos datos.

Estos ejemplos los quiero compartir porque además de ser reales, dejan a las claras una triste afirmación.

Un cliente nuevo es mejor valorado que un cliente antiguo y fiel a la marca, cuando en realidad debería ser al contrario.

Ahora voy a poner un ejemplo teórico de actuación por parte de una empresa de telecomunicaciones que quiere romper el mercado preparando un modelo comercial moderno y diferente.

Si por ejemplo, un cliente fiel recibe una prebenda cada... ¿4 años por ejemplo?, ¿creéis que ese cliente va a cambiarse de compañía?.
Pongo un ejemplo más descriptivo aún.
Si hoy sale Windows Phone 8 y soy un fanático de dichos terminales y el operador de telecomunicaciones decide ofrecerme gratis un Nokia 820 con una permanencia de 24 meses y un Nokia 920 con una permanencia de 36 meses con consumo fijo, etc... ¿creéis realmente que aceptaré o rechazaré la oferta?.
Imaginad lo mismo para otros terminales tipo iPhone, Android, BlackBerry, etc...

Ahora pensad que llego a esos 24 meses de permanencia por ejemplo y mi Nokia 820 se me queda obsoleto o simplemente me he cansado de él... ¿que haría el consumidor?.
Seguramente cambiar, pero a lo mejor puede acogerse a un servicio como los actuales puntos que tienen las operadoras para obtener una rebaja.
Pero imaginemos nuevamente que el cliente está contento con el terminal y decide continuar usándolo otros 24 meses más (4 años ya), y el operador me llama sin yo decirle nada para decirme que han detectado que llevo 4 años usando el mismo terminal que me ofrecieron y que ahora me ofrece otro terminal nuevo modelo gratis si le ofrezco fidelidad nuevamente... ¿que creéis que pasaría?.

¿Y qué creéis que pasaría cuando me juntara con los otros colegas de profesión, amigos y familia como hice antes para hablar estas cosas?.
Indudablemente les diría que utilizaran los servicios de mi operador de telecomunicaciones porque las ventajas son enormes, me cuidan, etc.
¿Y qué creéis que la portabilidad les sale gratis a las compañías de telecomunicaciones?. Pues no, da mucho dinero... de ahí que estén jugando con este modelo de negocio sin pensar que es el chocolate del loro y que otros modelos les aporta mayores beneficios.

¿Y que hay aquí en esta forma de actuar diferente realmente?. Pues varias cosas.

Por un lado, se crea una dependencia y una estrecha relación casi personalizada entre empresa y cliente, y entre cliente y empresa.
La fidelidad va en doble dirección y no sólo como hasta ahora ocurre casi siempre, en la que es el cliente el que le puede ser fiel o no a la empresa.
La satisfacción del cliente aumenta.
La empresa además recoge como canal indirecto una entrada de clientes debido a las recomendaciones y satisfacciones de los actuales clientes.
El cliente se encuentra mimado y valorado.
El cliente no se planteará ningún cambio si su grado de satisfacción y servicio son óptimos.
La empresa recogerá unos ingresos fijos de acuerdo al contrato de fidelidad establecido, por lo que podrá incluso hacer estudios de inversión y contabilidad más precisos.

Me gustaría poner dos ejemplos o anécdotas más que han salido a colación de comentar todo esto con algunos de mis compañeros de trabajo.

Mi primera impresora fue una HP Deskjet 510 en blanco y negro.
Me acuerdo perfectamente.
Yo era un ignorante de todo el mundillo informático y alguien me dijo que era muy bueno registrar los productos por el soporte de las empresas.
Como era eso, un ignorante... se me ocurrió registrar en HP mi impresora enviando el formulario de registro a una dirección de USA.
Lo hice y me olvidé de aquello... total... ¿para qué servirá?.
De hecho, algunos conocidos me dijeron cuando lo comenté que había perdido el dinero de los sellos y que no serviría para nada...
Comencé mis estudios de informática y de repente viene un paquete a casa desde USA.
Cuando lo abrí me encontré un aparato metálico y pesado y una carta.
La carta pedía disculpas por un fallo en la impresora e indicaba que como usuario y consumidor de dicha impresora, me enviaban dicho aparato para resolver los problemas detectados.
El problema era muy simple. Cuando la bandeja de papel llegaba a tener como tres o cuatro hojas, la impresora no las enganchaba.
El aparatoso soporte que me enviaban levantaba un poco las hojas para que los rodillos las pillara. Así de simple.
Lo cierto es que sí había notado el fallo, pero lo solventaba añadiendo más papel.
La verdad es que aquello hizo que recomendara la marca a todos mis conocidos.

Años después, adquirí un Citröen C5.
Era un anti-citröen, no lo niego, pero ya sabéis... calidad/precio... achuchado económicamente,... etc.
Lo adquirí y al poco tiempo de usarlo detecté un fallo de fábrica que remití a Francia.
Al cabo de los meses recibí una carta que me indicaba que me acercara por un taller Citröen para resolver gratuitamente algunos problemas técnicos detectados en el modelo.
Cuando fui al taller y pregunté, me dijeron que las reparaciones eran de unos 1000 € por coche y que estaban llamados a hacerlas todos los modelos desde una fecha determinada.
Que no eran fallos graves y que quien no quisiera realizar las reparaciones podía circular sin problemas, pero que lógicamente me recomendaban hacerlas, a lo que accedí como es lógico.
Después de utilizar el vehículo durante algo más de 8 años y de aquella anécdota... os lo podéis imaginar... me compré otro Citröen C5.

Todo esto lo comento porque me duele enormemente ver como las empresas invierten (o tiran) una gran cantidad de dinero en hacer nuevos clientes ignorando a los que ya tiene, invitándoles prácticamente a ser clientes residuales o incluso a cambiar de marca, compañía, empresa, etc.

Y es que creo que es más importante mantener a tus actuales clientes y potenciar esa relación empresa-cliente, cliente-empresa, que pensar únicamente en crear nuevos clientes.
Nuestras ansias de crecer a veces, nos hace perder el foco de lo que importa,... y cuidado, que hay quienes se mueren de éxito.

¿Tienes alguna fórmula para defender el marco normal de actuación de las empresas para olvidar a los clientes actuales y fieles y atender mejor a los potenciales nuevos clientes?. ¿Qué opinas?.

Publicado por Jorge Serrano | 5 comment(s)
Archivado en:

Introducción

La semana pasada, mi compañero de trabajo y sufrimientos, Luis Ruiz Pavón, escribió una interesantísima entrada sobre cómo utilizar LINQPad 4 y NHibernate para probar consultas LINQ y resolver posibles problemas de rendimiento, cuellos de botella, etc., sin tener que hacer grandes alardes de programación… es decir, sin utilizar Visual Studio.

En mi caso, voy a preparar una entrada variante y complementaria de la de Luis pero enfocándome en lo que sería un pequeño ejemplo paso a paso de cómo llevar a cabo esta tarea utilizando levemente Visual Studio para aquellos que se encuentren un poco perdidos en la utilización de LINQPad 4 y NHibernate Profiler tal y como apuntaba Luis.

 

Preparando el modelo

Lo primero de todo, vamos a crear un proyecto de tipo Class Library en C# por ejemplo, al que le he puesto el nombre de NHibernateTest y en el que agregaremos una clase de nombre Exployee y con los siguientes campos:

   1:  namespace NHibernateTest
   2:  {
   3:   
   4:      using System;
   5:   
   6:      
   7:      public class Employee
   8:      {
   9:   
  10:          public virtual Guid Id { get; set; }
  11:          public virtual string Name { get; set; }
  12:          public virtual string Surname { get; set; }
  13:          public virtual string Address { get; set; }
  14:          public virtual string City { get; set; }
  15:          public virtual string Country { get; set; }
  16:   
  17:      } // Employee
  18:   
  19:  } // NHibernateTest

A continuación, compilaremos nuestro proyecto para ver que todo está bien.

Una vez hecho esto, nos olvidaremos ya de Visual Studio.

Pensemos por lo tanto, en que hemos preparado un proyecto con los objetos de dominio o similar.

Sin embargo, nos gustaría poder “jugar” con ellos introduciendo datos o haciendo algunas operaciones básicas o genéricas con NHibernate.

Crear un proyecto de consola o similar es una alternativa, pero nos obligaría a abrir Visual Studio y trastear, cuando en realidad, lo que queremos, es hacer algo más ágil, rápido y sencillo.

 

Preparando LINQPad 4

Vamos a ejecutar por lo tanto LINQPad 4.

Lo primero que haremos será modificar la propiedad Language a C# Statements.

Una vez hecho esto, si queremos, podemos establecer una conexión con nuestra base de datos.

En concreto, tengo una base de datos en SQL SERVER a la que le he puesto el nombre de TESTS, y que tiene una tabla de nombre Employees con los campos indicados en la clase de C# que vimos anteriormente:

Sólo de modo opcional y si quisiéramos establecer una conexión en LINQPad 4 con nuestra fuente de datos, haríamos clic en la opción Add connection de la aplicación:

Probaríamos la conexión y veremos que todo es correcto. Pero en este caso, este último paso lo vamos a obviar.

 

Fichero de configuración de NHibernate en lugar de utilizar la conexión con LINQPad 4

En mi caso sin embargo, voy a tirar de ficheros de configuración.

Así que para establecer la conexión con nuestra fuente de datos, voy a crear un archivo de configuración llamado sqlserver.hibernate.cfg.xml dentro del cual he agregado la siguiente configuración:

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <configuration>
   3:    <configSections>
   4:      <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
   5:    </configSections>
   6:    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
   7:      <session-factory>
   8:        <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
   9:        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
  10:        <property name="connection.connection_string">Data Source=P-JOSE8\MSSQLSERVER2012;
  11:        Initial Catalog=TESTS;Integrated Security=True</property>
  12:      </session-factory>
  13:    </hibernate-configuration>
  14:  </configuration>

Recapitulando, hemos dejado preparado LINQPad 4 y hemos creado una biblioteca de clases en Visual Studio donde hemos creado nuestra clase Employee con sus campos.

Tenemos una base de datos de prueba con una tabla Employees con los campos correspondientes, y por último, hemos creado un archivo de configuración de NHibernate para establecer la conexión con nuestra fuente de datos.

 

Creando el archivo de mapeo con la entidad Employee

El siguiente paso será el de preparar el archivo de mapeo de nuestra entidad Employee para que NHibernate interprete correctamente sus campos y pueda trabajar con ella sin problemas.

Existen otras formas de llevar a cabo esto, pero aquí y para probar todo, vamos a hacerlo así.

El archivo de mapeo se llamará Employee.hbm.xml, y su contenido queda de la siguiente manera:

 

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
   3:  assembly="NHibernateTest"
   4:  namespace="NHibernateTest">
   5:    <class name="Employee" table="Employees">
   6:      <id name="Id">
   7:        <generator class="guid.comb" />
   8:      </id>
   9:      <property name="Name" not-null="true" />
  10:      <property name="Surname" />
  11:      <property name="Address" />
  12:      <property name="City" />
  13:      <property name="Country" />
  14:    </class>
  15:  </hibernate-mapping>

Vuelta a LINQPad 4, agregando ensamblados y namespaces

Para completar todo el proceso, vamos a agregar algunos ensamblados y namespaces a LINQPad 4 para que cuando agreguemos el código de ejecución, pueda localizar e interpretar las instrucciones de código que vamos a ejecutar de forma correcta.

Lo primero que debemos tener en la herramienta NHibernate Profiler que nos va a permitir analizar las instrucciones que lanzamos contra NHibernate.

Por otro lado, en LINQPad 4 vamos a pulsar la tecla F4 que nos permite abrir la ventana para agregar referencias, ensamblados y namespaces.

Nos situaremos en la solapa Additional References.

Los ensamblados a agregar son estos cuatro:

  • HibernatingRhinos.Profiler.Appender.dll
  • Iesi.Collections.dll
  • NHibernate.dll
  • NHibernateTest.dll

Dentro de la carpeta en la que tenemos nuestra herramienta de profiling encontraremos un ensamblado de nombre HibernatingRhinos.Profiler.Appender.dll que deberemos agregar en las referencias adicionales de LINQPad 4.

También deberemos agregar las librerías Iesi.Collections.dll y NHibernate.dll que encontraremos en la carpeta de ensamblados de NHibernate.

Y finalmente agregaremos el ensamblado que creamos con Visual Studio al principio del todo.

Para concluir, iremos a la solapa Additional Namespace Imports y agregaremos tres namespaces:

  • NHibernate
  • NHibernate.Cfg
  • NHibernateTest

Bastará con poner cada uno de los nombres de los namespaces ahí uno debajo del anterior.

LINQPad 4 ya se encargará de hacer el correspondiente using por nosotros.

 

Escribiendo el código a ejecutar en LINQPad 4

Ya estamos prácticamente concluyendo.

El último paso es escribir nuestro código y ejecutarlo.

Para ello, vamos a escribir el siguiente código:

   1:  HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
   2:   
   3:  ISessionFactory sessionFactory = new Configuration().
   4:  Configure(@"C:\Temp\sqlserver.hibernate.cfg.xml").
   5:  AddFile(@"C:\Temp\Employee.hbm.xml").BuildSessionFactory();
   6:      using (ISession session = sessionFactory.OpenSession())
   7:      {
   8:          using (ITransaction transaction = session.BeginTransaction())
   9:          {
  10:              Employee employee = new Employee();
  11:              employee.Name = "Pedrito";
  12:              employee.Surname = "Gómez Sánchez";
  13:              employee.Address = "Calle Mayor, 1";
  14:              employee.City = "Burgos";
  15:              employee.Country = "Spain";
  16:              session.Save(employee);
  17:              transaction.Commit();
  18:              session.Close();
  19:          }
  20:      }

Este ejemplo, cargará el archivo de configuración de NHibernate para establecer la conexión con NHibernate y el archivo de mapeo de la entidad Employee.

Finalmente agregaré un nuevo empleado a la base de datos con los datos que hemos agregado aquí.

Podríamos haber hecho un bucle para agregar un conjunto de empleados a modo de ejemplo o cualquier otra cosa, pero sirva este ejemplo para mostrar cómo escribir datos en una tabla utilizando NHibernate y sin apenas utilizar Visual Studio.

El caso es que para ejecutar nuestro código, bastará con pulsar el botón de ejecución o pulsar la tecla F5.

Si la ejecución es correcta, veremos un mensaje en la parte inferior de la aplicación LINQPad 4 que indica algo así como Query successful.

 

Analizando NHibernate Profiler

Adicionalmente y con ayuda del profiler, podemos obtener información valiosa a la hora de ejecutar nuestras instrucciones.

Si comprobamos los datos en SQL Server, veremos que estos están correctamente persistidos.

(Nota: también podemos ver los datos persistidos desde LINQPad 4 si hemos establecido previamente una conexión con el modelo de datos como se apuntaba al principio, lo cuál nos evitará incluso la tarea de irnos a SQL Server Management Studio).

Tal y como decía Luis en su entrada, estas prácticas nos pueden ahorrar mucho tiempo y quebraderos de cabeza.

Podemos crear y ejecutar instrucciones LINQ o podemos incluso probar determinados comportamientos y ejecuciones en nuestro código sin tener la necesidad de abrir Visual Studio para ello.

Espero que le resulte de utilidad a más gente.

Introducción

Microsoft ha publicado una actualización de WCF Data Services v5.0, con el que podemos crear y consumir servicios de datos para la Web a través del protocolo OData (Open Data Protocol) versión 3.

La idea es que entre otras cosas, podamos utilizar fácilmente los verbos HTTP para poder acceder y cambiar datos.

Los requisitos de esta versión son Microsoft .NET Framework 4.0 Visual Studio 2010.

Este paquete resuelve diferentes bugs al mismo tiempo que añade mejoras.

Adicionalmente, Microsoft ha publicado igualmente una nueva versión de WCF Data Services, la versión 5.2 que añade mejoras y resuelve bugs y problemas. Esta nueva versión puede ser instalada en equipos con Microsoft .NET Framework 4.0 y Microsoft .NET Framework 4.5, así como en Visual Studio 2010 y Visual Studio 2012.

Recomendación

Microsoft recomienda encarecidamente la instalación de la actualización en el caso de que ya utilices WCF Data Services en la middle-tier, especialmente para los usuarios de LightSwitch en Visual Studio 2012.

Respecto a este último punto, recomiendo acceder a la información que sobre ello ha publicado Beth Massi.

Descarga

Podrás acceder a la descarga de la actualización de WCF Data Services v5.0 for OData V3 en este enlace (5.3 Mb).

También puedes acceder a WCF Data Services v5.2 RTM Tools Installer, que utilizaremos para actualizar los paquetes NuGet referenciados por la plantilla de WCF Data Services a la versión v5.2.0, resolviendo además, algunos bugs detectados que tiraban abajo a Visual Studio en la generación de referencias a servicios contra modelos grandes. Se puede acceder a este otro paquete en este enlace (10.4 Mb). Los requisitos mínimos de esta herramienta son Microsoft .NET Framework 4.0 ó Microsoft .NET Framework 4.5, y Visual Studio 2010 ó Visual Studio 2012.

Finalmente, agrego igualmente el enlace de NuGet de esta nueva versión 5.2 y el enlace del sitio oficial de Microsoft con la información de esta nueva versión 5.2.

Aprendizaje

Si lo que quieres es saber un poco más sobre WCF Data Services, entonces te recomiendo el siguiente tutorial.

Publicado por Jorge Serrano | con no comments
Archivado en:

Introducción

Microsoft ha liberado recientemente su aplicación SkyDrive para Xbox 360.

Con esta aplicación gratuita, podremos disfrutar, ver y compartir nuestras imágenes y videos de SkyDrive en nuestra consola.

Para ello, basta con acudir al apartado de aplicaciones y la sección social, localizar SkyDrive e instalarla.

La instalación se realiza en un par de minutos y estaremos preparados para poder utilizarla.

Error 0x80048821

Sin embargo, nada más arrancar nuestra aplicación podemos tener dos escenarios.

El primero y esperado es que todo funcione perfectamente.

El segundo y no esperado, es que de un error… concretamente el error 0x80048821.

He esperado un tiempo prudencial por si el error se debía a un problema de conexión pero nada de eso, así que me he puesto a buscar si a alguien más le había pasado y efectivamente, no soy el único.

Por suerte, existe solución, o al menos, a algunos les ha funcionado.

La solución puede ser encontrada en este enlace.

Básicamente, la explicación de la misma es la siguiente (transcribo en inglés que es como está redactada dicha solución):

If you have changed the password on your Microsoft account since first signing in to your Xbox, you may get a sign in error code of 0x80048821. If so, you need to provide the new password. You can do this by pressing the Xbox Guide button on your controller, then select Chat & IM. Scroll to the right and select Sign In. Enter your Microsoft account password on the next screen. Once you are signed in, restart the app.

If this doesn’t work, or if you renamed your account with the release of Outlook.com, you may need to update your account information. To do this, go to Settings and select the “Profile” tile. Then select “Account Security,” then “Security Proofs” and enter your information. You will need to then restart the app. If this does not resolve sign in for you, please reply below.

Espero que a alguien más le ayude en caso de encontrarse con este problema.

Publicado por Jorge Serrano | 1 comment(s)
Archivado en:

Introducción

Me encuentro delante de mi Microsoft Visio 2013 recién instalado en mi Windows 8, e intentando hacer como otras muchas veces en versiones anteriores de Visio, un nuevo diagrama.

Para ello, me nutriré como he hecho siempre, de un conjunto de plantillas de iconos o stencils tal y como he hecho siempre cientos de veces antes.

Sin embargo, cuando me pongo en disposición de agregar la plantilla de iconos, me encuentro con la siguiente ventana de error:

Como podemos apreciar, las plantillas de iconos han sido bloqueadas por seguridad por Visio 2013.

Indudablemente, lo primero que hacemos es ir a la información de Microsoft y a buscar por Internet alguna posible solución,… e incluso llegamos a pensar que igual deberíamos manipular en el registro de Windows algo, pero nada de nada.

La solución no obstante es mucho más sencilla, y casi casi es lo que nos apunta en esta página.

La solución

Si acudimos a donde la ventana de mensaje anterior de Visio nos indica, observaremos una ventana como la que se indica a continuación:

Lo llamativo del asunto no es solamente que podamos seleccionar o quitar la selección de los elementos indicados, sino que por un lado y siguiendo lo que la primera ventana nos indicaba, lo que aquí está seleccionado debería ser suficiente, pero ya hemos visto que no.

Sin embargo, podemos prestar atención a la parte inferior de la ventana:

En este punto, nos damos cuenta de que seleccionemos lo que seleccionemos arriba,… abajo nos deja seleccionar claramente una única opción “Do not open selected file types”… ¡toma ya!.

Es decir, que da igual lo que hagas, estás jodido… ¿o no?.

Pues no… no estás jodido, hay una combinación de opciones que lo resuelve.

Basta con quitar la selección de todos los elementos y una vez hecho esto, podremos agregar nuestras plantillas de iconos o stencils a Visio 2013 y utilizarlos sin problemas.

Espero que este pequeño truco ayude a más de uno.

Publicado por Jorge Serrano | con no comments
Archivado en:

Microsoft ha publicado el pasado mes de Noviembre a través de Codeplex una actualización de su herramienta StyleCop.

En concreto, se trata de la versión 4.7.42.0.

Podrás acceder a la descarga de esta nueva versión en este enlace (4.3 Mb).

Para acceder a la información general sobre StyleCop v4.7, deberás hacer clic en este otro enlace.

Recordad finalmente, para los que tengáis y utilicéis Twitter, que el equipo de trabajo de StyleCop, posee una cuenta en twitter en @stylecopdev.

Microsoft ha publicado un fichero en formato pdf, que representa un póster con características, servicios y usos comunes.

El documento, proporciona una descripción de los servicios, separados por categoría.

Así, se agrupan los detalles y características en servicios de aplicación, servicios de datos, sistema, red y almacenamiento.

El póster puede ser impreso en un póster de 66 centímetros x 1 metro.

El documento pdf puede ser descargado desde este enlace (1.1 Mb).

Publicado por Jorge Serrano | con no comments
Archivado en:

Microsoft ha publicado un documento en formato pdf con las guías de diseño para aplicaciones Windows 8.

La bondad de este documento es que contiene las guías de estilo y diseño que podemos consultar en la Web, con la facilidad de que podemos leerlo offline con una tableta o incluso imprimirlo.

Estas guías deben cumplirse para poder diseñar aplicaciones Windows 8 y poder publicarlas en la Windows Store de Microsoft. Así que si estás pensando en desarrollar tus aplicaciones para Windows 8, deberías empezar a conocer este documento y lo que en él se explica.

El documento tiene un tamaño de unos 3.5 Mb y puede ser descargado desde este enlace.

Si queremos consultar estas guías en línea a través de la página Web, podemos hacerlo a través de este otro enlace.

Publicado por Jorge Serrano | con no comments
Archivado en:

Introducción

Desde hace poco tiempo, tengo entre mis manos un dispositivo de Microsoft especialmente diseñado para Xbox 360, y el cual me permite conectarlo a mi consola y poder chatear entre otras cosas.

Lo más interesante de este dispositivo, es que tiene un modo de selección dual: Xbox 360 y Bluetooth.

Según rezan los datos de Microsoft, el modo de selección Bluetooth, nos permite conectarlo con dispositivos móviles y PCs, así que me he puesto a trastear con él y efectivamente, es o puede llegar a ser un buen aliado.

Características

Entre sus características y pruebas que he hecho, destaco las siguientes:

Conexión dual: Xbox 360 y conexión Bluetooth.

Conectividad: Xbox 360, PCs, otros dispositivos.

Soportes Bluetooth: HSP, HFP y A2DP.

Carga a través de microUSB-USB, conectándolo al PC, Xbox 360 u otra fuente de alimentación.

Más datos.

Pruebas

Pero para ver su funcionamiento, que mejor que probarlo digo yo…

Así que me he puesto manos a la obra y he probado el Xbox 360 Wireless Headset en varios dispositivos.

Xbox 360: Obviamente, no tengo apenas nada que decir. Que funciona tal y como se espera.

Windows Phone: He usado este terminal telefónico porque es el que tengo ahora mismo. Seguramente funcione con todos,… al menos, todos los que soporten los protocolos de comunicación Bluetooth HSP, HFP o A2DP. En mi caso he usado un modelo Nokia Lumia 800, y la conexión entre ambos dispositivos ha sido satisfactorio. He podido escuchar música sin problemas, aunque también funciona para recibir llamadas o mantener conversaciones con Skype por ejemplo.

iPad: También me he puesto a juguetear con mi iPad 3, y al igual que con mi Windows Phone, el funcionamiento ha sido el esperado, pudiendo escuchar a través del Xbox 360 Wireless Headset lo que proyectaba en mi iPad.

PC: De igual forma, este dispositivo se ha conectado satisfactoriamente a mi ordenador.

Precio

El precio oscila según donde lo compremos, pero éste puede variar entre los 23€ y los 50€.

Mi consejo a día de hoy, cuando estoy publicando esta entrada, es adquirirlo en Amazon por 23€.

Conclusiones

Lo considero un dispositivo muy útil y a bajo precio (pensando como bajo precio el mínimo posible), capaz de conectarse a diferentes dispositivos, permitiéndonos escuchar música, mantener conversaciones de chat o de Internet como por ejemplo Skype o Lync, y pudiendo sacarle provecho de diferentes formas.

Es uno de esos dispositivos que sin ser imprescindible, lo considero muy útil y recomendado.

Actualización

He continuado probando este dispositivo y en concreto, con una PSP Go. Puedo decir con seguridad, que el dispositivo se enlaza con la consola portátil de Sony, y que permite escuchar el sonido de los juegos por este dispositivo... así que ya tiene otro uso más. :)

Publicado por Jorge Serrano | con no comments
Archivado en:

Foto: Jim Norton

Introducción

Estaba revisando mis Twitts en Twitter cuando me encuentro con un mensaje que me lleva a un artículo en la página web consultoras.org y de título "Mejor el Open Source conocido, que un cloud inmaduro" y que en realidad, nos lleva a la fuente original del artículo en siliconnews.com y a su autora, Nerea Bilbao.

Centrándome en el artículo original, éste trata acerca de un estudio mandado hacer por Amadeus a un prestigioso académico IT en el que en rasgos generales concluye, que el cloud está inmaduro y se debería mirar más hacia soluciones Open Source.

Te invito a leer previamente este artículo y posteriormente si quieres, leer mis comentarios al respecto, ya que me gustaría puntualizar algunas cosas.


Algunos detalles del artículo

Antes de hacer mis apreciaciones sobre el estudio, desgranaré algunas partes principales del mismo.

En dicho estudio, el "prestigioso" académico IT (Jim Norton) asevera y urge a los CIOs de las empresas de IT, que deberían considerar seriamente las soluciones y productos de código abierto (open source) sobre el Software propietario o los servicios públicos de tipo cloud.

Para ser justos con las aseveraciones de dicho estudio, en él, se indica que lo primero es el open source, no el cloud.

Y concluye con que la nube pública (public cloud) es un negocio inmaduro.

Y aquí viene quizás lo mejor, cuando Norton afirma que espera que hagamos un mayor ahorro de costes mediante el uso de open source sin la necesidad de utilizar una solución basada en la nube.

No pongo en duda la rigurosidad del estudio, pero permitidme que haga una pequeña salvedad que sembrará la duda y que me ha hecho meditar el no escribir este post de entrada, y es el hecho de que Amadeus esté detrás del estudio, ya que Amadeus se caracteriza por apoyar el Open Source, así que dudo mucho que haga un estudio que les diga que lo interesante es el Software propietario y el cloud, pero vamos... eso no quita para que haga algunas matizaciones al respecto de dicho estudio.

Pero pongamos los puntos sobre las íes y obviemos quién ha hecho el estudio, sino, analicemos las conclusiones... que para mi parecer son alarmantes, ya que si algún CIO lee esto y se lo traga a pies juntillas, quizás se encuentre en poco tiempo con problemas por haber adoptado o una mala solución a sus problemas, o una dirección errónea para su empresa.

Pero vayamos por partes y poco a poco.


Algunas puntualizaciones al respecto

No voy a empezar ahora a contar si el open source es bueno o es malo. Más que nada, porque yo también he hecho open source y yo también he consumido open source, pero hablemos de algo más concreto. Los problemas y las soluciones.

Ni todos los problemas se resuelven con open source, ni la solución a todos los problemas es el open source.

Según este estudio, el open source resuelve los problemas de los costes, y pone en el disparadero una palabra... el miedo.

Para ello, se nutre de una afirmación que es una falacia, por muy prestigioso que sea el señor Norton, y es el hecho de afirmar que la nube es inmadura.

Hagamos un pequeño flashback y viajemos a principios del siglo XXI, 2002, 2003 aproximadamente... ¡FlAsH!.

...

Ya estamos en el años 2002, 2003 y os voy a hablar de ASP, pero como el término ASP en informática puede dar a confusión, seré más concreto y hablaré de Application Service Provider.

El CLOUD o el embrión del mismo no es nuevo señores. Yo precisamente estuve a punto de entrar en una compañía en el año 2003 que se iba a dedicar a algo parecido a lo que hoy se conoce como cloud,... bueno, era en realidad algo casi igual, pero por aquel entonces, sí estaba inmaduro (doy fe).

El problema es que en esos años, el Software que se podía ejecutar en la nube era prácticamente nulo, es decir... no había apenas Software que funcionara como Servicio (SaaS).

Sin embargo hoy, todo eso ha cambiado porque la tecnología se ha ido adaptando y mejorando, y el desarrollo del Software también.

 

¿Está maduro el Cloud?

Aquí me gustaría preguntarle al señor Norton que entiende él por madurez, ya que afirmar que "algo" está maduro o no es muy complicado, y si hablamos de tecnologías más aún, sobre todo porque las tecnologías no son estáticas, evolucionan, cambian, mutan, etc. Y él mejor que nadie, debería saber que lo mismo le ocurre al open source,... ¿alguien recuerda la palabra mantenimiento y sabe lo que realmente significa?, ¿alguien recuerda la palabra o frase de flexibilidad y rapidez al cambio?.

Pero ojo... las afirmaciones del señor Norton en dicho estudio son aún más dolorosas, ya que no habla de inmadurez como tal, sino de "negocio inmaduro".

Y yo me pregunto en ese caso... ¿qué hay que hacer?, ¿esperar a que salga una solución open source de tipo cloud?.

El problema es que no sé si realmente el señor Norton conoce lo que es el cloud, y me explico.


El cloud de Microsoft

Pongo y hablo del cloud de Microsoft porque es el que más conozco, así que permitidme que hable de él para exponer porqué el señor Norton se está columpiando como un colegial (cosa que me sorprende debido a su prestigio que asocio a su experiencia).

El cloud de Microsoft por ejemplo, permite instalar tanto Software propietario como open source.

Sin embargo, hay algo que permite el cloud y que no permite el Software de tipo open source (NI EL PROPIETARIO) y es la redimensión de los sistemas en base al consumo, al crecimiento, etc., así como otras características ASOCIADAS al HARDWARE. Eso sin contar con el ahorro de costes por el mantenimiento de los sistemas o por la actualización de las aplicaciones base ejecutándose en ellos.

Y es que una parte de dicho estudio que ha sido obviada interesadamente creo yo, es el hecho de separar el SOFTWARE del HARDWARE.

Pero dudo enormemente que el señor Norton lo haya obviado desinteresadamente, y que haya ignorado el hecho de que el Cloud, no sólo es SOFTWARE, también es HARDWARE, pero queda muy bien desviar la atención, hacer un estudio tendencioso y decir las verdades a medias, para posteriormente, que el incauto empresario se lo trague y contrate a Amadeus o al señor Norton para que les cobre nosecuantos dólares en consultoría antes de que el maligno Software propietario o el cloud lo haga antes que ellos.

Pero pensemos las cosas con mayor profundidad...

Si una empresa adquiere Software open source, ¿dónde lo va a ejecutar?. En un Hardware por el que habrá pagado unos cuantos cientos de dólares supongo.

Si una empresa adquiere Software propietario, ¿dónde lo va a ejecutar?. En un Hardware por el que habrá pagado unos cuantos cientos de dólares supongo.

Es decir, ambos van a tener que pagar unos cientos de dólares por el Hardware, con la salvedad del Software que en el caso del open source es gratis "por defecto" y de pago en el propietario.

Sin embargo, para el open source, muchos tendrán que adquirir los correspondientes contratos de soporte pagando al final unos cuantos dólares también.

¿Acaso el open source al que todos asocian erróneamente con gratis sale más barato que el propietario?. Pues depende de cada problemática a resolver, pero recordad una cosa que a mí siempre me decían de pequeñito y que me aprendí a fuego… “nadie da duros a pesetas”.

Sea como sea, en ambos casos también (open source o propietario), necesitarán un departamento de sistemas (externalizado o interno) que se encargue de mantener dicho Software y dicho Hardware. Un grupo de personas que se encargue de dar soporte, que aporte valor y que asegure el buen funcionamiento del sistema y que los usuarios no tengan problemas de acceso, seguridad, etc. Y que ante la posibilidad de que se den fallos en el sistema los resuelva fácil y rápidamente, y que incluso si la demanda de usuarios crece o decrece, sea fácil y rápidamente escalable en las dos direcciones (hacia adelante o hacia atrás si la demanda baja por ejemplo), y todo sin incidir directamente en los costes.

No es de recibo por ejemplo, que adquiramos dos máquinas nuevas para soportar un crecimiento de usuarios y que pasado un año, la empresa se dé de baja del servicio por ejemplo, y nos comamos con patatas las dos máquinas o las revendamos como podamos para no tirar el dinero invertido por el retrete… ¿a alguien le suena¿. Si algún CIO lo lee, seguro que sí, yo al menos sin serlo hoy, recuerdo algún que otro caso parecido.


¿Y qué aporta el Software open source?

Seamos serios y rigurosos en las cosas en las que tenemos que serlas.

A mí, lo que me parece realmente sangrande de este estudio, es mezclar intencionadamente churras con merinas y hacer creer a los CIOs que el open source es la solución a todos sus problemas, que el Software propietario es el origen de sus problemas, y que el cloud es "algo" que está ahí pero que no no va a resolver sus problemas de IT debido a que es inmaduro.

Personalmente creo, que esas aseveraciones tienen un único fundamento... "amigo CIO, sigue gastándote la pasta en el open source y pasa del Software propietario". El tema es que el cloud no es un problema de Software open source vs propietario, va más allá, pero es mejor enredar el asunto y hacer creer que digo blanco cuando en realidad quería decir negro. Como dije en Twitter al respecto, es mejor mezclar churras con merinas y aseverar inconscientemente que ha salido una cabra, para afirmar a continuación que todas las ovejas son cabras. Si alguien se lo quiere tragar, adelante.

Si eres CIO y has leído esto, sólo te deseo una buena elección en la solución de la problemática y no dejarte llevar por estudios tendenciosos, pero para concluir, pondré ejemplos reales de muchas empresas (ni una ni dos) que trabajando hoy con el sistema inmaduro de la nube o cloud, se han evitado mil y un problemas, han ahorrado mucho dinero, han escalado sus sistemas de forma eficiente y rápida, han podido hacer frente a retos de forma mucho más rápida a como lo hacían en el pasado (imaginemos lo que ha pasado con la transmisión REAL de los Juegos Olímpicos de Londres en la nube), y han podido hacer un seguimiento de costes mucho más preciso.

Para ser la nube o cloud inmaduro no está nada mal ¿verdad?.

Este tipo de estudios, lejos de empequeñecer al cloud, le hace aún si cabe más grande.

¿Para cuando el próximo estudio señor Norton?.

Publicado por Jorge Serrano | 2 comment(s)
Archivado en:

No suelo poner este tipo de noticias en mi blog de forma pública (más bien, creo que es la primera vez que lo hago en Internet), pero en este caso voy a hacer una excepción porque creo que la ocasión lo merece.

He decidido cambiar de aires y cambiar de empresa.

He decidido dejar mi actual empresa, Sogeti (grupo Cap Gemini y partner de Microsoft), y apostar por una empresa en auge (Partner de Microsoft también), con gente implicada y fantástica profesional y personalmente, y envuelta en proyectos y retos nacionales e internacionales interesantísimos, y un excepcional futuro por delante.

Durante este último año y medio he estado inmerso en un interesantísimo proyecto en un cliente sensacional. De la nada y de forma colaborativa hemos empezado a dar forma a un producto enorme introduciendo en el mismo multitud de tecnologías nuevas para el cliente, y cubriendo las necesidades iniciales que debían ser abordadas para conseguir que el proyecto resultara un éxito. Al ser un proyecto empresarial bastante grande y complejo, aún le falta recorrido, pero la parte fundamental sobre la que se ha estado trabajando en todo este tiempo ha sido llevada a cabo con éxito.

Entre otros cambios, se ha impulsado el paso de PowerBuilder, Source Safe, VB6, C++, Oracle y Java a nuevas tecnologías como TFS, metodologías Scrum, UML, C#, Oracle y SQL Server (entre otras cosas), todo ello bañado de OOP puro, patrones, buenas prácticas, guías de arquitectura y desarrollo.

Y para colmo, todo ello adornado de un buen compañerismo y buena gente.

En resumen,... no tengo nada más que buenas palabras y agradecimientos para mi anterior empresa y los compañeros que he tenido tanto en Sogeti como en el cliente en el que he estado trabajando durante todo este tiempo.

Sin embargo, cuando uno menos se lo espera, aparecen oportunidades profesionales que a uno le tientan y le hacen dudar de si debe cambiar su camino profesional o no. Eso es lo que me ha pasado en esta ocasión, y de verdad que me siento muy afortunado por ello y tremendamente agradecido a mi nueva empresa el hecho de que hayan pensado en mí.

Lamentablemente, he cambiado demasiadas veces de empresa en los últimos años, algo que desde luego no me agrada reconocerlo pero que tampoco nadie tiene porqué pensar mal de ello ni tampoco tengo porqué ocultarlo porque no ha sido por nada extraño. A veces, los cambios han sido motivados por temas personales/profesionales, y en otras ocasiones (las menos por suerte) porque el mercado tan voraz e inesperado en el que estamos todos inmersos, me ha “invitado” a llevar a cabo en alguna ocasión un cambio de aires (lo que algunos llaman “ajustes”).

El caso, y lo que más me importa ahora mismo, es que no todos los días te presentan delante de tus ojos un caramelo… una oportunidad fantástica de formar parte de un proyecto de largo recorrido, de grandes expectativas y de un futuro que a simple vista parece no tener límites. En esos casos, de los que la experiencia me ha hecho saber que no ocurren todos los días, es muy difícil negarse a dar el paso definitivo.

Si además de todo eso, vas a tener compañeros de trabajo fantásticos y como la copa de un pino (que diría un famoso periodista deportivo), las decisiones son si cabe aún más fáciles de tomar.

Cierto es que la situación económica y social actual le manda a uno ser quizás más conservador, pero no es menos cierto que las barreras están para romperlas y los retos para vencerlos, así que me he decidido a dar ese paso hacia adelante y agarrar con las dos manos la oportunidad que se me ha presentado.

Espero estar a la altura de las circunstancias.

Así que a partir de ahora, formo parte de la familia Spenta dentro de la cuál, hay personas que algunos ya conocéis en los blogs de Geeks como David Martos o Luis Ruiz Pavón, y otras que sin tener un blog tan seguido o conocido, son extraordinarios profesionales y seguro que más de uno se hará notar dentro de poco.

Spenta, There we go!

Publicado por Jorge Serrano | 6 comment(s)
Archivado en:
Más artículos < Página anterior - Página siguiente >