Este artículo proviene de un motor de traducción automática.

Aplicaciones de Windows Phone 7

Cree aplicaciones controladas por datos con Windows Azure y Windows Phone 7

Danilo Ceballos

En los últimos 30 años, hemos visto una explosión en el sector de hardware del equipo. Desde grandes sistemas a los equipos de escritorio a dispositivos de mano, el hardware realiza obteniendo más eficaces incluso a medida se reduce. Los desarrolladores tienen, hasta cierto punto, se convierten en algo dañados por este aumento constante de la capacidad informática y ahora que los recursos del equipo sin límite en todos los dispositivos para el que se escriben las aplicaciones. Muchos programadores más recientes que no hay memoria de una hora cuando el tamaño y la eficacia de su código fueron factores importantes.

La tendencia más reciente en el desarrollo es en adoptando el aumento de la popularidad de los teléfonos inteligentes. Cuando se codifica para dispositivos smartphone, muchos desarrolladores se tengan que ajustar el hecho de que, aunque los teléfonos de hoy son muy eficaces en comparación con los dispositivos de tan sólo unos años, que se enfrentan las limitaciones. Estas limitaciones están relacionadas con el tamaño, la potencia de procesador, memoria y conectividad. Es necesario comprender cómo evitar estas limitaciones al crear aplicaciones móviles para garantizar un buen rendimiento y la mejor experiencia de usuario.

Algunos de los motivos de rendimiento sea óptimo de aplicación se pueden atribuir directamente a las decisiones de diseño deficiente por el programador. Sin embargo, en otros casos, algunos de estos factores no son directamente en el control del desarrollador. Una aplicación mal rendimiento podría ser un síntoma de lenta o sin conexión de otros proveedores servicio, las conexiones de banda ancha móviles perdidas o el tipo de datos que está trabajando (por ejemplo, para grandes conjuntos de datos o de los archivos multimedia de transmisión por secuencias).

Todo lo que podría ser la causa, el rendimiento que percibe el usuario final de la aplicación debe ser una de las principales preocupaciones de cualquier desarrollador de software. En este artículo, trataremos algunas consideraciones de alto nivel para el diseño de aplicaciones, eficaces controladas por datos 7 de teléfono de Windows de forma que pueden proporcionar una experiencia de usuario excelente y escalar de forma correcta.

En primer lugar Let’s unos instantes y configurar un escenario en el que podemos analizar algunas opciones de codificación y diseño. Por ejemplo, vamos a trabajar con una aplicación de información del viaje ficticio que proporciona información sobre los vuelos de billetes de avión seleccionado por el usuario. Como se muestra en de figura 1, la pantalla principal de la aplicación muestra un número de elementos de datos, incluidos el tiempo actual y el estado de vuelo. Puede ver que, como las aplicaciones se vuelven más expresivo y centralización de datos, desarrollo de éstos es un poco más complicada. Existen simplemente más áreas a las que el código puede pronosticadas.

image: The Flight Information Sample App

Figura 1 de la aplicación de ejemplo de información de Flight

Bloqueo del subproceso de interfaz de usuario

Iniciar Let’s mirando en la interfaz de usuario. Es fácil confundir el modelo incorrecto al diseñar la aplicación como si se va a realizar la codificación para el escritorio, por lo tanto, let’s tomar un vistazo a algunos problemas de la interfaz de usuario de teléfono específico.

Cuando una aplicación no responde correctamente a comandos de usuario, el efecto de la experiencia de usuario global puede ser considerable. Respuesta lenta a swipe, puntee o presione puede ser perjudicial para el recurso global de la aplicación. Sin embargo, son problemas muy sencillos prever y resolver, como se verá.

Considere la posibilidad de un control ListBox. Cuando un objeto ItemTemplate contiene las imágenes o carga desde una fuente de datos, hay muy buenas posibilidades de que se bloqueará el subproceso de interfaz de usuario y la interfaz de usuario se detendrá hasta que las solicitudes o realizar cálculos. Por lo tanto, durante el desarrollo de la interfaz de usuario, es un método realizar cálculos largos, incluidos WebRequests: fuera de los subprocesos de interfaz de usuario. De hecho, es un buen método para cualquier aplicación, móvil o no.

Otro problema que puede crear problemas de rendimiento es cuando se está enlazando grandes cantidades de artículos del ItemSource sin limitación de inserción en el control ListBox. Un mejor enfoque sería enlazar un ObservableCollection y rellenar unos pocos artículos cada ms 20-30 de la colección. Esto desbloquea el subproceso de interfaz de usuario para responder al usuario.

En el caso de nuestra aplicación de ejemplo, que también estamos haciendo un uso intensivo de las imágenes en la pantalla. El control ListBox debe realmente descargar la imagen para mostrar dichos datos. Aunque esto parece Aceptar, hacer este trabajo en el subproceso de interfaz de usuario se bloqueará al usuario especificar un gesto. Cargar imágenes en un subproceso en segundo plano resuelve varios problemas tanto en lo que respecta a los requisitos de memoria y libera el subproceso de interfaz de usuario, al mismo tiempo que hace la aplicación con mayor rapidez.

Se deben procesar todos los elementos que se muestran al usuario. Procesamiento requiere el diseño, alineación y el cálculo que se muestre correctamente. Cuando se agregan más capas a la interfaz de usuario, el cálculo y el procesamiento general los costos de aumento. Aunque Silverlight ya virtualiza el interfaz de usuario, no virtualizar los datos que se va a enlazar. Esto significa que si tuviéramos que enlazar los elementos de 10.000 para nuestro control ListBox, Silverlight debe repetir todas 10.000 ListItems antes de que se representen.

Tenga en cuenta lo que se encuentra el enlace de datos y mantener el conjunto dependiente tan pequeño como sea posible. Si necesita controlar grandes conjuntos de elementos de enlace de datos, considere la posibilidad de controlar de forma dinámica el procesamiento en segundo plano. Es el caso de aplicaciones de escritorio, por supuesto, el impacto de estas opciones sólo se amplificados en un teléfono.

ValueConverters puede tener un efecto drástico sobre el rendimiento de procesamiento debido a que se definen usando código personalizado y la representación no puede ser predeterminada y en la caché antes de la representación de elemento real y el diseño.

Trabajar con datos

A continuación, debemos hablar sobre el almacenamiento de datos en el teléfono de Windows 7. Let’s obtener directamente a la del punto: No hay ningún motor de base de datos relacional disponibles para los desarrolladores. SQL Server Compact (SQL CE) se instala con el sistema operativo de Windows teléfono 7, pero actualmente no hay ninguna API disponibles para los desarrolladores. Por lo tanto, crear una base de datos para almacenar datos de la aplicación, en nuestro ejemplo, información de viaje, no se va a trabajar.

No obstante, hay una amplia gama de opciones de obtención de datos de nuestra aplicación. Un enfoque común es utilizar un servicio de la nube, como Windows Azure para la persistencia de datos. Hay numerosas tecnologías disponibles para la creación de la capa de servicio de la aplicación, REST y SOAP que se va a las más populares. SOAP es la primera opción para muchos desarrolladores, pero pensamos que REST proporciona un método más eficaz y más fácil de implementar que las solicitudes de datos.

Empleamos una serie de métodos que proporcionan datos a la aplicación y que se puede tener acceso mediante el uso de expresiones de REST como los siguientes:

/Trip/Create/PHL-BOS-SEA/xxxx/2010-04-10
/Flight/CheckStatus/US743

REST nos ofrece la posibilidad de utilizar XML o JSON para un formato de mensaje.

Desde la perspectiva de aplicaciones para usuario de Web, se ha optado por el marco de trabajo de ASP.NET MVC (asp. NET/mvc) debido a nos permite procesar la solicitud y devolver cualquier tipo de marcado con una vista personalizada.

Nuestra aplicación de ejemplo que se necesita para controlar la información de viaje y el vuelo, por lo que creamos un FlightController y un TripController que interceptar las solicitudes de esta información:

// GET: /Flight/CheckStatus/US743
public ActionResult CheckStatusByFlight(
  string flightNumber) {
  return CheckStatus(flightNumber, DateTime.Now);
}

// GET: /Flight/RegisterInterest/US743/2010-04-12
public ActionResult CheckStatus(
  string flightNumber, DateTime date) {
  Flight f = new Flight(flightNumber, date);
  GetFlightStatus(f);
  return new XmlResultView<Flight>(f);
}

Para proporcionar métodos de acceso simplificado y guardar algunos bytes de ancho de banda, si la fecha de hoy en día es que puede diseñar un método abreviado para obtener estos datos sin que implícitamente se especifica en la actualidad es la fecha.

Datos almacenados en caché y persistentes

El servicio de estado de vuelo es un elemento de la aplicación que no está en nuestro control y, por tanto, va a formar parte del rompecabezas de rendimiento. Ya que el éxito de la aplicación puede recibir un gran número de solicitudes, es importante pensar acerca de una estrategia de almacenamiento en caché.

Por lo general, cuanto más se aproxime el vuelo a partida, puede esperarse que cuanto mayor sea el número de solicitudes de su información. Los números más altos de las solicitudes de casi simultánea pueden afectar al no sólo el rendimiento de la aplicación, sino también los costos asociados a almacenar y manipular los datos. Como norma general, las aplicaciones de Windows Azure acumulan los cargos de ancho de banda tanto en la solicitud y devolución y servicios de información del vuelo también podrían incurrir en gastos de acceso. La cantidad de datos devueltos debe ser no más de lo que se necesita la aplicación.

La plataforma Windows Azure proporciona una amplia gama de opciones para el almacenamiento de datos, de tablas, blobs y pone en cola a la base de datos relacional, como el almacenamiento de información a través de SQL Azure. Hemos decidido utilizar Azure SQL porque utiliza técnicas de programación familiares de SQL Server y permite almacenar y tener acceso a datos almacenados en caché de vuelo y de información del viaje persistente fácilmente.

La figura 2 muestra la capa de almacenamiento de información simple que diseñamos mediante Entity Framework.

image: Flight Data Storage Schema

La figura 2 del esquema de almacenamiento de datos de Flight

Devolución de datos

Se devuelven datos al cliente a través de la vista personalizada. Puesto que estamos utilizando ASP.NET MVC, cada vista debe derivar de ActionResult y implementar ExecuteResult.

Como se mencionó anteriormente, podemos ofrecer representaciones de XML o JSON de la información del vuelo a través de nuestro servicio REST. Let’s realizar primero un vistazo a la opción de XML. El serializador para generar XML requiere un tipo, por lo que se crea una clase de tipo genérico, como se muestra en de figura 3.

La figura 3 de serialización XML

public class XmlResultView<T> : ActionResult {
  object _model = null;
  public XmlResultView(object model) {
    this._model = model;
  }

  public override void ExecuteResult(ControllerContext context) {
    // Create where to write 
    MemoryStream mem = new MemoryStream();

    // Pack characters as compact as possible, 
    // remove the decl, do not indent.
XmlWriterSettings settings = new XmlWriterSettings() { 
      Encoding = System.Text.Encoding.UTF8, 
      Indent = false, OmitXmlDeclaration = true };
    XmlWriter writer = XmlTextWriter.Create(mem, settings);
    
    // Create a type serializer
    XmlSerializer ser = new XmlSerializer(typeof(T));

    // Write the model to the stream
    ser.Serialize(writer, _model);

    context.HttpContext.Response.OutputStream.Write(
      mem.ToArray(), 0, (int)mem.Length);
  }
}

Igualmente se puede trabajar con JSON para nuestros datos. El único elemento de nuestra solución que cambiaría sería el contenido del método ExecuteResult. Utilizar JsonResult, podemos crear la devolución JSON de nuestro servicio en sólo unas pocas líneas de código:

// Create the serializer
var result = new JsonResult();
// Enable the requests that originate from an HTTP GET
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
// Set data to return
result.Data = _model;
// Write the data to the stream
result.ExecuteResult(context);

¿Guardar los datos al propio dispositivo? Para hacer que la aplicación para extraer datos desde el servicio cada vez que el usuario tiene acceso a la información de viaje no tendría sentido. Aunque no hay ningún almacén de datos relacionales en el teléfono de Windows 7, los desarrolladores tienen acceso a una característica denominada Isolated Storage. Esto funciona igual que el almacenamiento aislado del 4 de Silverlight, pero sin un límite de tamaño.

Hay dos métodos principales que se debe guardar y recuperar los datos en el teléfono: SaveData y GetSavedData. De figura 4 muestra ejemplos que muestran cómo deberíamos utilizar estas características en la aplicación de la información de vuelos.

La figura 4 de almacenamiento y recuperación de datos locales

public static IEnumerable<Trips> GetSavedData() {
  IEnumerable<Trips> trips = new List<Trips>();
  try {
    using (var store = 
      IsolatedStorageFile.GetUserStoreForApplication()) {
      string offlineData = 
        Path.Combine("TravelBuddy", "Offline");
      string offlineDataFile = 
        Path.Combine(offlineData, "offline.xml");

      IsolatedStorageFileStream dataFile = null;

      if (store.FileExists(offlineDataFile)) {
        dataFile = 
          store.OpenFile(offlineDataFile, FileMode.Open);
        DataContractSerializer ser = 
          new DataContractSerializer(
          typeof(IEnumerable<Trips>));

        // Deserialize the data and read it 
        trips = 
          (IEnumerable<Trips>)ser.ReadObject(dataFile);
        dataFile.Close();
      }
      else
        MessageBox.Show("No data available");
    }
  }

  catch (IsolatedStorageException) {
    // Fail gracefully
  }

  return trips;
}

public static void SaveOfflineData(IEnumerable<Trips> trip) {
  try {
    using (var store = 
      IsolatedStorageFile.GetUserStoreForApplication()) {

      // Create three directories in the root.
store.CreateDirectory("TravelBuddy");

      // Create three subdirectories under MyApp1.
string offlineData = 
        Path.Combine("TravelBuddy", "Offline");

      if (!store.DirectoryExists(offlineData))
        store.CreateDirectory(offlineData);

      string offlineDataFile = 
        Path.Combine(offlineData, "offline.xml");
      IsolatedStorageFileStream dataFile = 
        dataFile = store.OpenFile(offlineDataFile, 
        FileMode.OpenOrCreate);

      DataContractSerializer ser =
        new DataContractSerializer(typeof(IEnumerable<Trip>));
      ser.WriteObject(dataFile, trip);
                   
      dataFile.Close();
    }
  }

  catch (IsolatedStorageException) {
    // Fail gracefully
  }
}

Tratamiento de errores de red

Las redes que utilizan los dispositivos móviles pueden tener conectividad muy variable, a veces, cada vez que no esté completamente disponible por ubicación, la congestión o incluso los usuarios desconectar manualmente (en el caso de un modo de avión, por ejemplo). Tiene que aceptar esto como una hecho de vida. Como desarrolladores de aplicaciones móviles debemos tener esto en cuenta al crear aplicaciones.

Otro tipo de error de red es un error de capa de servicio. Muchas aplicaciones móviles consumen datos de servicios de terceros. Estos servicios no pueden proceder con los acuerdos de nivel de servicio, lo que deja la aplicación a merced del proveedor. En otras palabras, si está fuera del control, y tiene que estar preparado para tratar las interrupciones.

Independientemente del origen del error de red, deberá proporcionar la mejor experiencia de usuario que sea posible. Debe proporcionar cierto nivel de funcionalidad en el caso de cualquier tipo de error de red. Para nuestra aplicación de estado de vuelo, esto significa que deseamos que el usuario pueda tener acceso a tanta información como sea posible, incluso si se pierde por el servidor o en el lado del cliente de conectividad de red.

Hay muchas formas de conseguirlo. Por ahora, se podrá concentrar en tres métodos sencillos en el que se puede lograr esto: obtener los datos mientras se pueden almacenar en caché datos de forma local y la caché de datos en un servidor de control.

Uso de notificaciones de inserción

Cuando el usuario escribe la información del viaje en la aplicación, la información se cargarán en un servicio de nube. El servicio, a continuación, se mantenga sondear los distintos servicios que proporcionan los datos de vuelo y el tiempo. También busca cambios en los datos a lo largo del tiempo, como, por ejemplo, un cambio de estado de vuelo o un aeropuerto que informa de un retraso.

Cuando se encuentra ningún cambio, en el que desea obtener esa información al usuario como el más eficaz posible y lo antes posible. Una forma de hacerlo es para que el servicio que se va a insertar la información a la aplicación de cliente. Esto proporciona el acceso de usuario para el conjunto de datos disponibles más actual el momento en que los datos estén disponibles. Debido a que los datos se ha insertado para el cliente, los datos están disponibles incluso si el usuario pierde su conexión de red.

Se puede lograr esto con nuestro servicio Azure de Windows mediante el uso de la notificación de inserción de teléfono de Windows. La característica de notificación de inserción de teléfono de Windows está formada por tres componentes: supervisar servicios, el servicio de notificación de inserción de Microsoft y un método de tratamiento de mensajes.

Un servicio de monitor es un servicio de la nube que constantemente se busca información nueva para nuestra aplicación. Trataremos esto detalladamente más adelante.

El servicio de notificación de inserción es parte de los servicios alojado de Microsoft que se utilizan para transmitir mensajes a los dispositivos de teléfono de Windows 7. Este servicio está disponible para todos los desarrolladores de aplicaciones de Windows 7 de teléfono.

El método de controlador de mensajes es su nombre sugiere: Simplemente recibe mensajes desde el servicio de notificación de inserción.

Hay tres tipos de notificación predeterminado en Windows 7 de teléfono: Notificaciones de mosaico, inserción y brindar. Las notificaciones son una parte importante de la experiencia del usuario y es necesario considerar su uso con cuidado. Las notificaciones repetitivas o intrusivas pueden degradar el rendimiento de la aplicación y otros usuarios que se ejecutan en el dispositivo. También pueden molestias a los usuarios. Tenga en cuenta la frecuencia en las notificaciones se envían y los tipos de sucesos que se va a obtener la atención de los usuarios.

En Windows 7 de teléfono, las notificaciones se entregan a través de procesamiento por lotes, por lo que la transacción no puede ser instantánea. No se garantiza la idoneidad de la notificación y la decisión acerca de cómo entregar la notificación al cliente se controla mediante el servicio;el servicio es el mejor rendimiento para determinar la rapidez con la puede entregar el mensaje al teléfono.

El flujo de trabajo para las notificaciones de inserción es:

  1. Aplicación cliente solicita una conexión de canal para el servicio de notificación de inserción.
  2. El servicio de notificación de inserción se responde con el URI del canal.
  3. La aplicación cliente envía un mensaje para el servicio de supervisión con el URI del canal de servicio de notificación de inserción, así como una carga.
  4. Cuando el servicio de supervisión detecta un cambio de información (cancelaciones de vuelo, retrasos de vuelo o avisos de tiempo en nuestra aplicación de ejemplo) termina un mensaje para el servicio de notificación de inserción.
  5. El servicio de notificación de inserción se transmite el mensaje para el dispositivo de teléfono de Windows 7.
  6. El controlador de mensajes procesa el mensaje en el dispositivo.

Almacenamiento en caché de datos local

Otra forma para que los datos disponibles para su aplicación está en memoria caché localmente por lo que siempre hay algunos datos en la interfaz de usuario. A continuación, puede utilizar otros medios en segundo plano para actualizar los datos locales (si es posible). La ventaja de este método es que la aplicación puede cargar y se pueda utilizar rápidamente, incluso si la actualización de la información tiene que se produzca de forma asincrónica en segundo plano.

En pocas palabras, utiliza el almacenamiento aislado para guardar el último conjunto de datos. Cuando se abre la aplicación, que toma los datos disponibles en el almacenamiento aislado local inmediatamente y lo representa. Mientras tanto, la aplicación llama a los servicios de Windows Azure para obtener información actualizada. Si se encuentra la información nuevo, se serializa y se transfiere al dispositivo de almacenamiento aislado se actualiza y se procesa la interfaz de usuario con información actualizada. Para una mejor experiencia de usuario, probablemente desee indicar en la interfaz de usuario, lo que se ha actualizado la información de fecha y hora.

En una nota al margen, si la aplicación utiliza el modelo de diseño Model-View-ViewModel (MVVM), la actualización de la interfaz de usuario puede pasar automáticamente a través de las funciones de enlace de datos de Silverlight. Para obtener más información sobre MVVM y Silverlight, vea artículo de Robert McCarter, “ problemas y soluciones con Model-View-ViewModel, ” en msdn.microsoft.com/magazine/ff798279 de .

El almacenamiento en caché de datos en el servidor

Hay un terreno medio entre la inserción de datos directamente a la aplicación cuando esté disponibles y almacenar datos en el dispositivo: recolección de datos de servicios de terceros y almacenarla en la aplicación de la nube hasta que la aplicación teléfono de Windows 7 lo solicite.

Esta técnica requiere una nueva capa de abstracción de la aplicación. En esencia, el objetivo es quitar la dependencia de un servicio de otro fabricante de la aplicación. El servicio se extrae y se almacena en caché los datos de las dependencias de servicios de terceros. Si el servicio de otro fabricante deja de funcionar, deberá hacer al menos algunos datos en la caché que se puede proporcionar a la aplicación en los dispositivos.

Un servicio como éste podría ser fácilmente clonado o extendida para extracción de los datos de varios servicios, por tanto, reducir la dependencia en cualquier proveedor o el origen de datos, lo que facilita mucho cambiantes de los proveedores.

Para obtener más información sobre la configuración de soluciones centradas en datos de Azure de Windows, vea “ alimentando su aplicación del motor con Windows Azure almacenamiento ” por Kevin Hoffman y Nathan Dudek (msdn.microsoft.com/magazine/ee335721 ). Además, aunque no directamente se centra en los escenarios de teléfono de Windows 7, artículo de Paul Stubb, “ Create a Silverlight 4 Web Part para SharePoint 2010, ” es una buena lectura sobre el diseño de enlace de datos de Silverlight y los servicios Web (msdn.microsoft.com/magazine/ff956224 ).

Supervisar el servicio

Como se mencionó anteriormente, la función de notificación es una parte importante de nuestra aplicación de estado de vuelo. Esta función es en realidad se compone de varios servicios diferentes dentro de la aplicación. Quizás más importante para la utilidad de la aplicación, el servicio de supervisión periódicamente sondea los servicios de datos de otros fabricantes y transmite la información como los retrasos de vuelo, retrasos de aeropuerto y avisos de tiempo al dispositivo.

En nuestra aplicación, el servicio de supervisión lee la lista actual de vuelos y los códigos de aeropuerto y utiliza esta información para recopilar los datos pertinentes. Esta información se almacena a continuación, en la base de datos de SQL Azure como una entrada de caché para que se puede recuperar el servicio de /Flight/CheckStatus mostrado anteriormente. Nuestro servicio de supervisión se implementa con una función de trabajo de Windows Azure. El objetivo principal de esta función de trabajo es extraer información de estado de los retrasos de vuelo y el estado de aeropuerto de la colección de vuelo de todos los usuarios. La frecuencia de la extracción de actualización aumenta a medida que aproxima a la hora de salida de vuelo programada.

Para algunas ideas acerca de cómo podría implementar un servicio, asegúrese de desproteger el proyecto Azure publicar y suscribir en CodePlex (azurepubsub.codeplex.com ) o lea el blog de Joseph Fultz, “ migrar el servicio de Windows a la función de trabajo Azure: Ejemplo de conversión mediante el almacenamiento de imágenes ” (bit.ly/aKY8iv ).

Montaje todos juntos

Espero que le hemos proporcionado una amplia introducción a los problemas que debe tener en cuenta al diseñar una aplicación de teléfono de Windows 7 controladas por datos. La respuesta de la interfaz de usuario, así como el acceso de tiempo a los orígenes de datos, se reproduce a hacer una experiencia de usuario excelente para la aplicación.

Para profundizar un poco, comience con artículo de Luis Partlow, “ Getting Started con Windows teléfono herramientas de desarrollo ” (msdn.microsoft.com/magazine/gg232764 ). También desea ver el artículo, “ desarrollar y distribuir Windows Azure aplicaciones en Visual Studio 2010, ” por Jim Nakashima, Hani Atassi y Danny Thorpe (msdn.microsoft.com/magazine/ee336122 ).

Para unir el desarrollo de Windows Azure y teléfono de Windows 7, eche un vistazo al artículo de Ramon Arjona, “ teléfono de Windows y de la nube: Introducción ” (msdn.microsoft.com/magazine/ff872395 ).

Danilo Diaz es un departamento de formación de desarrolladores del distrito Atlántico medio estado de Microsoft. En esta función, ayuda a los desarrolladores comprender la estrategia y las ofertas de productos de Microsoft.

Max Zilberman es un evangelista arquitecto en los distritos de Nueva York y los Estados del Atlántico central. Antes de unirse a Microsoft, Zilberman ocupó diversos puestos técnicos senior en un asegurador de salud de nivel superior.

Gracias al siguiente experto técnico para este artículo: Ramon Arjona