martes, 13 de julio de 2010

iPhone, MonoTouch y la insoportable levedad del ser: El servidor

Primero fue iPhone, MonoTouch y la insoportable levedad del ser: El Comienzo. Luego vino iPhone, MonoTouch y la insoportable levedad del ser: El Cliente (la prueba). Ahora, en otra espeluznante vuelta de tuerca, le toca el turno al servidor.

Pero antes, abro un pequeño inciso para comentar que ha salido un libro sobre MonoTouch. Mientras escribía el primero de los artículos de esta serie leí (qué grande es el RSS, sí señor) que habían publicado el primer libro -en realidad el segundo- sobre programación con MonoTouch: 'Professional iPhone Programming with MonoTouch and .NET/C#', de la editorial Wrox [@ Amazon]. A día de hoy, lo único que sigo descargando de Internet son libros técnicos. Toda la música y las películas las compro (ya hablaré sobre eso). Pero los libros técnicos los sigo descargando, pues no suelo ni leerlos completos ni mantenerlos mucho tiempo una vez leo lo que me interesa. El resto de libros sí que los compro, so pena de que mi mujer acabe echándome de casa por la cantidad de papel que voy acumulando. Motivo éste, también, para recurrir a lo que la ministra de cultura, en una voltereta mortal al concepto en sí, denomina «piratería», para conseguir los libros técnicos. Del libro en cuestión ya tengo mi copia legal (aunque no muy lícita) en mi disco duro. Sin embargo no he tardado un suspiro en solicitar mi copia impresa (que tardará casi un mes en llegar) por menos de 30 €. Estoy muy entusiasmado con esta tecnología, lo confieso. Lo que me lleva a hacer este tipo de tonterías. Pero mientras llega, seguiré leyendo mi copia legal. Espero que la guardia civil no aporre mi puerta mañana.

Sería bueno que Apple rectificara ya su sección 3.3.1 [Apple podría cambiar la sección 3.3.1 para evitar una investigación antimonopolio @ Appleismo]. No solo porque se evitarían la investigación antimonopolio que también se está planteando en Europa [Apple podría enfrentarse a una investigación antimonopolio en Europa @ Faq-Mac]. Un cambio en la sección 3.3.1 permitiría «estandarizar» .NET como plataforma de desarrollo para iPhone. ¿Y por qué sería bueno? O, mejor preguntado, ¿por qué podría llegar a suceder eso? Pues porque los chicos de Mono están trabajando duramente en una versión para Android: MonoDroid, de la que ya está abierto el programa de trabajo beta [MonoDroid - Mono for Android Beta Program @ Miguel Icaza's Blog]. ¿Alguien me presta un teléfono con Android para probar? Prometo cuidarlo bien, aunque no creo que llegue a devolverlo. Pero no veo la aparición de MonoDroid como una especie de «trabaja una vez y usa en muchas plataformas»; algo que, de todos modos, sería fantástico. Pero más allá de que no se podrá aprovechar el código escrito para el SDK específico de iPhone o de Android, los cuales difieren, sí implica que se podría emplear un mismo lenguaje de programación y, por consiguiente, patrones —e idioms— del lenguaje. O existir bibliotecas de clases para funciones diferentes a las de interfaz de usuario que permitiesen reutilizar código. Se abre un universo de posibilidades.

También estos días he leído un rumor sobre que Apple podría estar preparando un nuevo lenguaje de programación para sustituir Objective-C [Apple podría estar preparando un nuevo lenguaje de programación para reemplazar a Objective-C @ Applesfera] que como todos los rumores se debería coger con pinzas. En cualquier caso yo diría que ese «nuevo lenguaje» ya existe y, perfectamente, podría ser .NET. Sea o no a través de MonoTouch.

En cualquier caso parece que la aparición de este libro permite hacer creer que habrá un sector creciente de gente que tenga ganas de programar para iPhone aprovechando su conocimiento de .NET. Ya veremos. Pero yo me estoy replanteando seriamente adquirir la licencia de desarrollo.

De todas formas, para el puntilloso, comentar que ya existe la posibilidad de desarrollar soluciones multiplataforma: PhoneGap [Homepage]. Sería usando JavaScript y espero tener la oportunidad de probarlo con un poco más de calma y, aún mejor, tener tiempo para escribir sobre ello. Sin embargo, por gustos, yo me decanto más por C# y la cantidad de cosas que ofrece su sintaxis y que, hasta la fecha, no he podido ver en JavaScript (¿dije «tipado fuerte»?).

Fin del inciso. Aunque se podría decir que esto, más que un inciso, es una anotación dentro de una anotación. Qué plasta que soy.

Como decía al principio, hoy le toca la vez a la parte de servidor. En realidad, para ser estricto, la aplicación en sí no necesita la existencia de tal parte. Para las chorradas que podría decir el «adivino», Numerón, se puede perfectamente embeber en la propia aplicación. Pero a efectos del experimento lo consideraba vital. Así que, aunque el servicio en sí sea algo ridículo, vamos a intentar conectar la aplicación cliente con un servicio web hecho a medida.

Tal como hice con la parte cliente, no es mi intención escribir otro tutorial sobre el asunto. Aunque al final acabe adquiriendo cierto tufillo a tutorial. En Internet hay unos cuantos a un click de Google. Por ejemplo, tienes el vídeo Create a web service on Monodevelop C# Linux en YouTube y una serie de documentos PDF en español [Entendiendo Web Services con MonoDevelop]. Entre cientos, si no miles, de documentos y vídeos por el estilo.

En mi caso he creado una Aplicación Web ASP.NET y, luego, he añadido un nuevo archivo de tipo Servicio Web con code behind.



A efectos de la prueba, basta con escribir un código similar al siguiente.

public class NumeronDice : System.Web.Services.WebService
{
  
   public NumeronDice () {}
  
   [WebMethod]
   public RespuestaNumeron Numero ( DatosPersonales datos ) 
   {
   return new RespuestaNumeron ( 42, 
                   string.Format ( "¿Pero de verdad crees en la adivinacion, {0}?", datos.Nombre ) );
   }
  
}

¿Qué ves de «extraño» en el código? Además de usar un tipo de datos, DatosPersonales, como parámetro de entrada y otro, RespuestaNumeron, como resultado. Es uno de esos malos hábitos que he adquirido con los años al «diseñar» servicios web. No, eso no es. Parece una falta de ortografía, pero «adivinacion» sin tilde no es porque yo haya querido dejarlo así. Aún no he conseguido que MonoDevelop me permita escribir tildes. He consultado en el IRC, he leído en el foro y todo apunta a una limitación a la hora de procesar las combinaciones de teclas del port para MacOS de GTK+. O una limitación mía para entender las discusiones en lenguas bárbaras como el inglés. Este ha sido el único contratiempo que le he encontrado al MonoDevelop hasta el momento. Bueno, lo de las tildes y que de vez en cuando le da por colgarse. Generalmente cuando intento escribir la descripción de una región y, por costumbre, o por la letra aprehendida con sangre, intento poner tilde sobre alguna vocal. En esas raras ocasiones se produce un salida imprevista del entorno y toca rezar para que el autoguardado me reponga del susto.

Lo de usar estructuras de datos (clases) como parámetro de entrada y salida es, también, porque deseaba comprobar hasta qué punto funciona la integración de servicios Web SOAP en el código de MonoTouch. A efectos de este pequeño breviario, baste decir que son clases bastante «tontas» sin ninguna funcionalidad más allá de definir propiedades (getters y setters) para que se pueda serializar y deserializar automáticamente a la hora de usarlos en el servicio web.

Si ahora lanzamos la ejecución de la aplicación, podremos acceder a la descripción del servicio en sí (que se asoció al método público con el identificador «Numero»).



Hecho el servicio Web, quedaría incluirlo en el cliente. Aquí me he encontrado con una limitación de MonoDevelop. En realidad es que no he sabido cómo hacerlo, así que busqué una alternativa para salir del paso. Ya seguiré indagando a ver si consigo lanzar dos proyectos a la vez: la aplicación web y el cliente iPhone cuando ambos están bajo la misma solución. Y, hasta donde yo sé, no puedo abrir dos soluciones al mismo tiempo con MonoDevelop. En fin, que para no andar perdiendo mucho tiempo en estas complejidades menores, comentar que existe una forma de salir del paso, como decía. Ya buscaré un mecanismo más elegante de hacer esto mismo. El mecanismo paliativo pasa por lanzar el entorno desde línea de comando. Dos veces. Hala, ¿a que es sencillo? Eso sí, asume que la salida de la aplicación será luego algo abrupta. Tendrás que forzar el cierre del terminal. No siempre, aunque muchas veces el Cmd+Q típico suele dejar colgada la sesión de terminal.



Pudiendo arrancar el servidor —de hecho hay que hacerlo— en una instancia de MonoDevelop y el cliente en otra, podemos crear la referencia al servicio web y depurar cada elemento por separado. Sin embargo, no nos vamos a meter a depurar. Baste ahora con la posibilidad de crear la referencia al servicio web desde el proyecto cliente. Para ello, con la parte servidor en funcionamiento, seguiremos la secuencia de pulsar botón derecho sobre el nombre del proyecto en la vista de solución, «Añadir;» y «Agregar referencia web». En el diálogo rellenar la URL del servicio, el nombre con el se quiere crear y, esto sí es importante de momento, indicar que se trata de un servicio web .NET 2.0 en lugar de uno de la más moderna arquitectura WCF [@ Wikipedia | @ MSDN Microsoft] que, sin embargo, es el que ofrece por defecto. Hay un How-To que enseña los pasos a dar para hacer uso de la variante WCF [Using WCF @ MonoTouch Wiki].



La invocación del método desde el código cliente, una vez se ha creado la referencia al servicio web, podría tener la siguiente forma:

private SWNumeronDice.RespuestaNumeron CalcularNumero ()
{
   SWNumeronDice.DatosPersonales datos = new SWNumeronDice.DatosPersonales ();
   datos.Nombre = this.nombreTextEdit.Text.Trim ();
   datos.Apellidos = this.apellidosTextEdit.Text.Trim ();
   datos.FechaNacimiento = _diaNacimiento.Value;
   datos.FechaPrediccion = _diaFuturo.Value;
   datos.Sexo = (this.sexoSegmentedControl.SelectedSegment == 0) ? SWNumeronDice.DatosPersonalesSexo.Hombre 
         : SWNumeronDice.DatosPersonalesSexo.Mujer;
    
   return new SWNumeronDice.NumeronDice ().Numero ( datos );
}

La inclusión de un servicio web dentro del cliente para iPhone usando MonoTouch mantiene el mismo esquema que teníamos para los clientes de escritorio, donde se crean versiones con tipado de las estructuras que se pasan como parámetros y/o se obtienen como respuestas. Esto permite tener el código funcionando en cuestión de minutos mientras nos aseguramos que en tiempo de compilación se detectarán problemas de tipo de datos.

Con la respuesta, se podría hacer algo como:

public override void ViewDidLoad ()
{
   Title = "Numeron dice...";
   numeroLabel.Text = this.respuesta.Numero.ToString ();
   cuentoLabel.Text = this.respuesta.Cuento;
   
   base.ViewDidLoad ();
}

El resultado de la ejecución sería algo como:



Con esta última ejecución del cliente, ya podríamos dar por cerrado el experimento. A partir de este punto quedaría enriquecer tanto la parte cliente como la parte servidora con todo aquello que se considere oportuno incorporar. Por mi parte dejaré para dentro de unos días unos pequeños comentarios sobre la experiencia en sí. Intentaré que sea más estructurada y funcional. Y breve. Sin embargo, concluyo la entrada de hoy con la esperanza de que esta pequeña prueba haya servido para demostrar cuán fácil es hacer un proyecto con un lenguaje moderno como .NET y que, con ello, sirva para atraer nuevos adeptos a la causa de MonoTouch y por la abolición de la sección 3.3.1 de la licencia de desarrollador de Apple para iPhone.

No hay comentarios: