Arquitectura de aplicaciones AJAX

Cualquier administrador del sistema, diseñador o desarrollador, puede ver su trabajo afectado significativamente por AJAX. Los administradores tienen que asegurarse de que la el nivel de seguridad sea lo bastante alto como para afrontar los nuevos tipos de ataques posibles. Los administradores de la intranet tienen que garantizar que JavaScript no esté deshabilitado en ningún explorador. A los diseñadores web se les presentan nuevos desafíos que conseguir, ya que se encuentran con características que ahora son accesibles con AJAX que antes eran imposibles o impracticables. Y los desarrolladores disponen de una API nueva y una nueva perspectiva general de programación con la que familiarizarse. Dicho todo lo cual, ¿qué sentido tiene AJAX para los arquitectos?

Las aplicaciones de AJAX son un desafío porque introducen conceptos completamente nuevos y una base nueva. La función del arquitecto es esencial porque el paradigma de AJAX es un puente de unión entre los entornos de cliente y servidor. Tener una visión arquitectónica clara es vital para determinar qué lógica y procesamiento tienen lugar en el cliente y qué parte permanece en el servidor, así como qué objetos de datos pueden intercambiar el cliente y el servidor.

AJAX al rescate

Las Web se usó en un principio para compartir páginas estáticas de información. Durante los últimos años, evolucionó hacia un medio mucho más dinámico. Hoy, la web está compuesta por páginas muy interactivas; sin embargo, todavía depende mucho de un paradigma que se basa en la transición de páginas enteras. Cuanto más interactúa el usuario con una página, más frecuentemente deben crearse y servirse dichas páginas a su explorador. Hay muchas consecuencias negativas que se derivan de servir páginas interactivas de esta manera, como una actualización lenta de las páginas y el parpadeo. Se trata de una solución nada elegante que lleva con frecuencia a una experiencia de usuario pobre. AJAX implica un cambio muy deseado en este paradigma que permite obtener aplicaciones web más limpias y establecer la base para una generación nueva de aplicaciones. AJAX está realmente destinado al usuario final. Gracias a las características de AJAX, una aplicación web se vuelve mucho más interactiva y tiene mayor capacidad de respuesta. Es más rápida y fácil de usar. Se anima al usuario a hacer más cosas con la página, ya que la interacción y las respuestas (y la realimentación en el caso de operaciones lentas) se administran de un modo mucho más elegante. En términos generales, el usuario consigue tener una experiencia mucho mejor.

Con AJAX, se ejecuta más código en el explorador y esto requiere proporcionar más scripts a las páginas del cliente. Pero esto deja algunas preguntas importantes sin contestar. ¿Qué clase de script? ¿Quién escribirá este script? ¿Y a qué principios y pautas arquitectónicas se adherirá este script?

En esta columna, explicaré AJAX desde un punto de vista arquitectónico para ayudar a desarrolladores y arquitectos a hacer selecciones más reflexionadas. Al mismo tiempo, se dará a los diseñadores y administradores suficiente información de contexto para que puedan llevar a cabo sus trabajos con más facilidad. Al tratarse de un tema bastante importante, lo dividiremos en dos partes. No se pierda la columna del próximo mes, en la que vamos a continuar hablando de este tema.

La arquitectura de AJAX

Si está pensando en aplicar AJAX, vea la figura 1, que ilustra las implicaciones arquitectónicas del cambio. Una aplicación web tradicional realiza todas sus acciones en el servidor. Sólo ocasionalmente la aplicación es la que emite código de scripts para ejecutar una tarea en el cliente, por ejemplo, para administrar la validación de datos.

fig01
 

Una aplicación de AJAX usa un marco de cliente que se ocupa de emitir llamadas al servidor web. A continuación un marco de servidor de AJAX se preocupa de la solicitud y devuelve una alimentación de datos al cliente. Con frecuencia esto será una secuencia de datos de JavaScript Notation Object (JSON), pero pueden usarse otros formatos, como XML, RSS y CSV.

El cliente recibe alimentaciones de datos y actualiza la IU con JavaScript. El servidor responde a solicitudes devolviendo datos sin procesar y codificados en un formato concreto. El consumo del ancho de banda se minimiza, la velocidad de las aplicaciones aumenta debido a que las solicitudes tardan menos en completarse y las actualizaciones de IU pueden hacerse efectivas sin necesidad de ninguna devolución visible. Pero aunque esto resuelve muchos problemas, el aumento en la acción sobre el cliente genera también problemas nuevos, como prácticas nuevas de codificación, peligros nuevos de seguridad, problemas de accesibilidad, etcétera.

¿Qué es un marco de AJAX?

Para mantener AJAX activo en una página web deben cumplirse unas cuantas condiciones. En primer lugar, es necesario que el explorador sea compatible con JavaScript. También se requiere una conexión permanente a Internet, ya que las aplicaciones de AJAX no pueden funcionar sin conexión. Cuando se han hecho todas las solicitudes en el nivel de la página, igual que ocurre con aplicaciones que no son AJAX, el explorador puede ofrecer navegar por un conjunto de estas páginas en la memoria caché, y de esta forma se puede seguir trabajando sin conexión. Este mismo comportamiento tendría que codificarse explícitamente en el marco basado en el script que está asociado al explorador en una aplicación de AJAX. Se está trabajando mucho en esta área y se están desarrollando algunas nuevas herramientas de ayuda. La capacidad de usar aplicaciones AJAX sin conexión es un desafío para muchos proveedores de software.

Cualquier aplicación seria de AJAX requiere un marco especial. Generalmente, el marco elegido se articula en partes separadas para cliente y servidor.

Existen dos tipos principales de código de script en una página de AJAX: el código en el nivel del sistema del marco elegido y el código a nivel de usuario, que implementa el comportamiento previsto de la página. El código en el nivel del sistema proporciona el motor usado para enviar solicitudes asincrónicas al servidor web y así procesar cualquier respuesta. El código en el nivel de usuario actualiza la IU de la página, y lo hace usando esencialmente scripting de modelo de objetos del documento (DOM). Así que nos encontramos con una de las preguntas que mencionaba antes: ¿Quién escribe qué? Para tratar el tema, nos centraremos en un marco concreto de AJAX: las extensiones de AJAX de ASP.NET.

Extensiones de AJAX de ASP.NET

ASP.NET AJAX Extensions es una extensión de ASP.NET 2.0 que ofrece capacidades tanto a los sitios web nuevos como a los ya existentes. Hay dos modelos de programación para AJAX de ASP.NET: la representación parcial y los servicios remotos. Estos dos modelos suponen dos arquitecturas radicalmente diferentes en la aplicación y en consecuencia presentan diferentes pros y contras. (Probablemente ya se habrá visto que la mayoría de las características de AJAX conllevan tanto ventajas como desventajas).

En pocas palabras, la representación parcial permite mantener una arquitectura semejante a la de una aplicación clásica de ASP.NET 2.0. Simplemente ofrece un conjunto de herramientas nuevas de servidor que permiten implementar actualizaciones de página sin parpadeos.

Los servicios remotos, por otro lado, requieren un back-end orientado a servicios e invocado por un front-end de AJAX con un uso bastante profuso de scripts. Casi todos los procesos fundamentales de las aplicaciones, incluidas la autenticación, la paginación de datos y la clasificación, deben volver a diseñarse. Debe producirse código de servidor para los servicios específicos de la aplicación y debe también seleccionarse un formato (como, por ejemplo, JSON) para el intercambio de datos. Finalmente, debe organizarse un cliente y prestarse la atención requerida para limitar la codificación a tareas de nivel de IU y mantener la mayor parte de la lógica empresarial fuera del cliente.

El enfoque de los servicios remotos ofrece una experiencia AJAX más completa, mientras que la representación parcial ofrece una transición más fácil, con una mejora progresiva de las características de la aplicación existente.

Estos dos enfoques pueden combinarse hasta cierto punto. Por ejemplo, se puede mantener la misma arquitectura tradicional de web, agregar algunas actualizaciones sin parpadeos aquí y allá, y entonces tomarse tiempo para volver a producir algunas características claves orientadas a los servicios. Las extensiones de AJAX de ASP.NET proporcionan varios ingredientes claves, pero las partes más elementales de este trabajo para crear unas aplicaciones magníficas de AJAX todavía dependen de usted. La figura 2 muestra los componentes del cliente y del servidor del marco de ASP.NET AJAX Extensions.

Una ojeada a la representación parcial

La columna Código malvado de Jeff Prosise de junio de 2007 (msdn.microsoft.com/msdnmag/issues/07/06/WickedCode)
ofrece un excelente debate acerca de la representación parcial con AJAX
de ASP.NET. Desde un punto de vista arquitectónico, la representación
parcial no agrega nada nuevo. Se trata sólo de una manera interesante
de mejorar las aplicaciones heredadas con algunas capacidades de AJAX,
la más importante de las cuales es la actualización de páginas sin
parpadeos.

La representación parcial no requiere
aprender muchas técnicas nuevas y tiene un impacto muy limitado en el
código existente. También ofrece un mecanismo de reserva sencillo para
tratar aspectos de una aplicación que pueden verse afectados a raíz de
la adopción de AJAX, por ejemplo la seguridad y la accesibilidad.
Básicamente, si en el proceso de actualización surgen problemas al
convertir algunas partes del código existente a AJAX, simplemente se
pueden dejar los bloques de código tal y como estaban y seguir adelante.

Una
solicitud de representación parcial a menudo se conoce como una
devolución de AJAX. El término es bastante apropiado y representa
perfectamente lo que sucede en realidad. Una devolución de AJAX es como
una devolución clásica de ASP.NET, salvo porque la lleva a cabo una
parte de código de script definida en la biblioteca del cliente de AJAX
de ASP.NET. Aunque se presenta disfrazada como una llamada remota pura
de AJAX, una devolución de AJAX se parece a una solicitud regular de
devolución para los componentes del tiempo de ejecución de ASP.NET. Una
vez en el servidor, la solicitud pasa por el ciclo de vida habitual de
las solicitudes de devolución y origina eventos como Init, Load y
PreRender. En el servidor, una devolución de AJAX difiere de una
devolución clásica de ASP.NET sólo en el algoritmo que usa para
representar el marcado final. Este algoritmo diferente es clave para la
mejora del rendimiento y la ausencia de parpadeo en la página. Sin
embargo, el modelo de la aplicación sigue siendo el mismo que en
ASP.NET. La figura 3 muestra el ciclo de vida modificado de una solicitud de devolución de AJAX.

Todo es igual en las devoluciones de AJAX y de
ASP.NET, salvo en lo que se refiere a la implementación de la fase de
representación. Una devolución de AJAX todavía inicia eventos de
notificación como Load y PreRender, y aún procesa la información de
viewstate y activa eventos de estados cambiados y de devolución como
TextChanged y Click.

Una página de AJAX de
ASP.NET debe incluir una instancia del control ScriptManager. Este
control es el auténtico centro neurálgico de las páginas de AJAX de
ASP.NET. Se ocupa de vincular la página a cualquier archivo de script
del marco que sea necesario y organiza la representación parcial si
detecta que se está produciendo una devolución de AJAX. El control
ScriptManager comprueba si hay un encabezado HTTP en la solicitud para
determinar si se trata de una devolución de AJAX. Lo que viene a
continuación es un resumen del archivo MicrosoftAjaxWebForms.js que
establece el encabezado HTTP antes de activar la solicitud de AJAX:

   request.get_headers()['X-MicrosoftAjax'] = 
'Delta=true';

Para ver qué hace que el estadio de
representación sea diferente en una devolución de AJAX, observe más de
cerca el resumen siguiente del ensamblado System.Web.Extensions:

   protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (IsInAsyncPostBack)
PageRequestManager.OnPreRender();
}

En concreto, el
fragmento de código que se mostraba anteriormente procede del control
ScriptManager. Como puede apreciarse, el director de scripts registra
un controlador de eventos de representación preliminar. Al iniciarse,
el controlador detecta si está comprometido con una devolución de AJAX
y, si es así, invoca un método desde la clase interna de
PageRequestManager. El método de OnPreRender de la clase
PageRequestManager hace lo siguiente:

   internal void OnPreRender()
{
_owner.SetRenderMethodDelegate(
new RenderMethod(this.RenderPageCallback));
}

Es bastante simple, el método establece
una subrutina específica para representar el marcado para la solicitud
actual. SetRenderMethodDelegate es un método definido en la clase
System.Web.UI.Control. Como no está destinado a un uso público, este
método asigna básicamente un controlador de eventos que la página o el
control usarán para representar su contenido. En el fragmento de código
anterior, se invoca al método en la página actual que acaba invalidando
todo el proceso de representación para la solicitud actual. El
verdadero código responsable del marcado de una devolución de AJAX se
define por lo tanto en el método RenderPageCallback, un método interno
de la clase PageRequestManager. (Para obtener más información sobre el
control de ScriptManager, consulte el artículo de Ben Rush sobre este
tema en MSDN® Magazine).

Básicamente
el proceso de representación modificado para una devolución de AJAX
establece bucles en todos los paneles de actualización de la página
implicados en la devolución y acumula el marcado de cada uno. Todos los
fragmentos del marcado, junto con campos ocultos y cualquier
información de errores, se empaquetan en una secuencia de respuestas y
se pasan al cliente. Diseccionemos ahora una llamada habitual de
representación parcial en el contexto de una página de muestra.

Puede usar diversas herramientas para supervisar
paquetes HTTP entrantes y salientes. Para esta columna, usé la
herramienta Web Development Helper de Nikhil Kothari, que puede
descargarse de forma gratuita en projects.nikhilk.net/Projects/WebDevHelper.aspx.La
respuesta de una devolución de AJAX es una secuencia de texto que puede
consultarse como una tabla de registros con las columnas Size, Type, ID
y Content. Cada registro se conoce como nodo delta.

Un nodo delta identifica un cambio posible sucedido
durante la devolución de AJAX. No todas las respuestas incluyen el
mismo conjunto de nodos delta; depende de lo que sucede durante el
ciclo de vida del servidor de la solicitud y la estructura del marcado
original.Técnicas de optimización para la representación parcial

Después de examinar la figura 6,
observará que la respuesta está compuesta por dos bloques grandes:
marcado y viewstate. Los datos de validación de eventos (una
característica relacionada con la seguridad de ASP.NET 2.0), los campos
ocultos personalizados, los scripts y otros tipos de nodos normalmente
ocupan unos cuantos bytes en total. El tamaño de viewstate es un viejo
problema que tienen las páginas de ASP.NET. Por desgracia, la
representación parcial con AJAX de ASP.NET, no hace nada para
corregirlo. Todavía necesitará mantener un viewstate eficaz y compacto
para poder mejorar el tiempo de descarga. Así que, ¿qué se puede hacer
para reducir el marcado de una página? Básicamente, se pueden tener
paneles más pequeños que devuelvan sólo la cantidad mínima de marcado
necesario para ese clic particular.

Observe de nuevo el código de la figura 4.
La lógica en la página es bastante sencilla, pero ilustra lo que
queremos decir. Básicamente, cuando el usuario hace clic en el botón,
se usa todo el contenido del TextBox para actualizar la etiqueta.

La
página sólo contiene un control UpdatePanel que lo incluye todo: cuadro
de texto, botón, separador y etiqueta. Hablando desde el punto de vista
de la lógica, esto puede ser aceptable. Si se desea identificar una
región de la página para actualizarla autónomamente, puede ser una
opción válida. Si embargo, si se define de este modo, la región
contiene una parte considerable de código que no se actualiza entre
devoluciones. Los controles TextBox y Button, por ejemplo, no se
actualizan en esta página, y el separador <hr> es un texto
estático sin formato.

Una mejor opción sería
reducir UpdatePanel para que sólo incluya el control Label, es decir,
el único control del servidor que se actualiza en cualquier devolución
activada por el botón. En general, deben identificarse con cuidado las
relaciones de las devoluciones entre los controles: examinar
básicamente cuál actualiza cuál y diseñar paneles que puedan
actualizarse para incluir un número mínimo de controles para una acción
determinada de un usuario. En el contexto del ejemplo que se muestra en
la figura 4, aquí hay un esquema mejor:

<asp:TextBox runat="server" ID="TextBox1" /> 
<asp:Button runat="server" ID="Button1" Text="Update"
OnClick="Button1_Click" />
<hr />
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>

El control UpdatePanel ahora contiene
sólo el control Label. Esto significa que ningún marcado (sin
modificar) será devuelto para los controles textbox y button. De forma
predeterminada, un control UpdatePanel se actualiza cuando uno de sus
controles secundarios causa una devolución o se actualiza otro
UpdatePanel de la página. Este comportamiento puede alterarse con
algunas propiedades públicas, por ejemplo, UpdateMode,
ChildrenAsTriggers y Triggers.

En particular,
UpdateMode determina si UpdatePanel se establece para actualizar de
forma incondicional (el predeterminado) o sólo bajo ciertas
condiciones. Si desea realizar un actualización condicionada, es decir,
una configuración clave para optimizar los paneles que se van a
actualizar, empiece por establecer UpdateMode en Conditional:

<asp:UpdatePanel runat="server" ID="UpdatePanel1" 
UpdateMode="Conditional">

Observe que, sin embargo, las actualizaciones condicionadas son relevantes sólo si se tienen diversos paneles en una página.

Puede
que haya situaciones donde parezca difícil dividir una página en un
conjunto de paneles normalizados. Una técnica que podría ayudarle en
estos casos es evitar que los elementos secundarios activen
devoluciones. La propiedad ChildrenAsTriggers es una propiedad booleana
(establecida en verdadero de forma predeterminada) que determina si los
controles secundarios de un panel actúan como activadores de eventos de
devolución de AJAX. En el fragmento de código siguiente, el control
Button1 no hace que se actualice el panel:

<asp:UpdatePanel runat="server" ID="UpdatePanel1" 
ChildrenAsTriggers="false">
<ContentTemplate>
<asp:Button runat="server" ID="Button1" Text="Update"
OnClick="Button1_Click" />
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
</asp:UpdatePanel>

Al hacer clic en un
botón secundario de un panel configurado de esta forma, tiene lugar una
devolución de AJAX para ejecutar cualquier código de devolución adjunto
en el botón, por ejemplo, el método Button1_Click, pero no se devuelve
ningún marcado para actualizar el panel.

La
tercera propiedad implicada en la actualización condicionada es
Triggers. Se trata de una propiedad de recopilación y muestra los
eventos de control que ordenarán un actualización del panel, como ésta:

<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>

En este caso, el
evento Click de Button1 actualizará el panel. El control Button1 puede
colocarse en cualquier lugar de la página. Tenga en cuenta que estamos
hablando de eventos del servidor. Es decir, si se desea actualizar un
panel cuando el usuario cambia la selección en una lista desplegable,
debe agregarse primero el atributo AutoPostBack a la lista desplegable.

Todavía
puede configurar un panel para que se actualice cuando un evento de
estado cambiado tenga lugar en el servidor durante una devolución de
AJAX. Observe el siguiente código:

<asp:TextBox runat="server" ID="TextBox1" /> 
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger
ControlID="TextBox1"
EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>

La etiqueta se actualiza siempre que el contenido TextBox1 cambia:

Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles TextBox1.TextChanged
Label1.Text = TextBox1.Text
End Sub

El evento
TextChanged, así como otros eventos de estado cambiado, son eventos del
servidor que se inician como resultado de una devolución. La página aún
necesita un botón, o un control de devolución automática, para activar
la devolución y así actualizar la etiqueta.

El gráfico de la figura 7
resume las posibles ventajas que pueden obtenerse de aplicar técnicas
de optimización a los paneles que pueden actualizarse. Mediante la
representación parcial, el tamaño del paquete de solicitudes aumenta
poco, pero incluso en el caso menos optimizado la respuesta que se
obtiene es más pequeña que la de una situación típica de ASP.NET. Y,
por supuesto, los usuarios no experimentan más parpadeos.

Debo advertir, sin embargo, que las páginas con un
viewstate grande quizás no se beneficien de la representación parcial.
Puede que ahorre 5 KB de marcado, pero no es mucho si tiene que cargar
con 30 KB de viewstate.

Pero a veces, viewstate
es sólo un cabeza de turco inocente de un problema que se originó en
otra parte. Supongamos que tiene un control de calendario en una página
de ASP.NET y se usan paneles que pueden actualizarse para mantener una
actualización sin conflictos:

<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Calendar runat="server" ID="Calendar1" />
</ContentTemplate>
</asp:UpdatePanel>

El marcado para este fragmento no es
menor de 7 KB, y puede crecer hasta 10 KB si se agregan algunos
estilos. Ahora bien, si se desactiva el viewstate del calendario, se
ahorrará aproximadamente 1 KB de datos, que es sólo un 10 por ciento
del tamaño total. Esto es así porque Calendar es un control pesado en
términos de marcado. El viewstate tiene poco que ver con este problema.
Una página de ASP.NET AJAX no debería usar controles Calendar para las
funciones de selección de fechas. En vez de eso, AJAX Control Toolkit
ofrece un extensor, el control CalendarExtender, que, cuando se ha
agregado a un TextBox sin formato, permite seleccionar fechas,
ahorrando 10 KB de marcado.

Este código hace emerger un calendario siempre que el cuadro de texto recibe el foco de entrada:

<asp:textbox runat="server" ID="TextBox1" />
<act:CalendarExtender ID="CalendarExtender1" runat="server"
TargetControlID="TextBox1"
OnClientDateSelectionChanged="updateLabel"
Format="dd/MM/yyyy" />

<asp:UpdatePanel runat="server" ID="UpdatePanel1"
UpdateMode="Conditional">
<ContentTemplate>
<asp:label runat="server" ID="Label1" />
</ContentTemplate>
</asp:UpdatePanel>

El calendario se
crea completamente en el cliente y sólo requiere la descarga de un par
de iconos pequeños. El extensor escribe automáticamente la fecha
seleccionada en el TextBox complementario. Sin embargo, con un poco de
código de JavaScript, puede administrar el evento de la selección de
fechas de cliente y hacer cualquier cosa que necesite.

Compensación de la representación parcial

La
representación parcial es la manera más rápida de adornar un sitio web
de ASP.NET con capacidades de AJAX. No requiere ni habilidades nuevas
ni una arquitectura nueva. En vez de eso, se presta a mejorar
progresivamente un sitio web existente. Pero comparado con un enfoque
puro de AJAX (llamadas del cliente directo a los servicios remotos) la
representación parcial sufre penalizaciones considerables en su
rendimiento.

Como norma general, se recomienda la
representación parcial como el mejor enfoque para crear una primera
versión sólida de AJAX de un sitio. Progresivamente puede irse alejando
de la arquitectura clásica de ASP.NET y empezar a crear un conjunto de
servicios back-end y un nivel de presentación sólido. En la entrega
siguiente de Cutting Edge, exploraremos los servicios remotos
relacionados con AJAX. Es fantástico desde el punto de vista de la
arquitectura, pero puede requerir volver a diseñar completamente la
aplicación y origina unos cuantos problemas nuevos.

About justindeveloper

I am MCP (Microsoft Certified Professional). MCTS (Microsoft Certified Technology Specialist) and MCPD (Microsoft Certified Professional Developer), also I am SAP Business One Certified!! Desarrollando desde el IDE de Visual Studio NET 2003 hasta ahora con el Visual Studio NET 2010. Desde Microsoft SQL Server 2000 hasta ahora con el Microsoft SQL Server 2008 R2 y tambien con SharePoint, desde WSS 3.0 y MOSS 2007 y ahora familirizandome con el Sharepoint Foundation 2010 & Sharepoint Server 2010. The software development will follow being every time more wonderful!
This entry was posted in Development. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s