\subsection{Eficiencia Vs Diseño}
\label{EficienciaDisenyo}

% dgg: Te paso un esquema para la seccion:

% dgg: En resumen: Releete el capitulo en que Fowler habla de la eficiencia y escupelo aqui
% dgg: Algunos conceptos que salian:
% dgg: - Un diseño elegante pude pecar de poco optimo (ya lo has comentado), añade ejemplo de 'diseño por capas'
%        - Ejemplo diseño por capas, es elegante
%        - Cada capa resuelve un aspecto a la capa superior
%        - La separación de responsabilidades clarifica diseño y código y facilita la localización de errores
%        - Pero a menudo las capas añaden latencia
%        - Ejemplo concreto, torre OSI, que nadie implementa todas las capas separadas por eso, 
%          va bien para explicar academicamente pero a la hora de la verdad las implementaciones
%          juntan y mezclan capas porque no es práctico ni óptimo.
% dgg: - Un diseño elegante se puede refactorizar para ser optimo (ya lo has comentado pero puedes referirte al apache)
% dgg: - Un diseño optimizado anticipadamente pierde oportunidades de optimizacion (puedes referirte al IIS)
% dgg: - Cuando va bien optimizar? cuando el diseño del sistema esta ya maduro, hacia el final
% dgg: - Hasta donde se optimiza? hasta que el diseño empiece a sufrir
% dgg: Añadele lo que aportas:
% dgg: - Ambitos en que la optimizacion es clave: Multimedia, Realtime, Web servers...
% dgg: - Desarrollo iterativo XP en estos ambitos, las primeras entregas, como van a cliente, necessitan ser ya optimas
% dgg: - Si fowler decia que hasta el final del desarrollo no convenia optimizar, controlando la regresion de eficiencia, podemos moverla en medio de este
% dgg: - El proceso de optimizacion es costoso, una inversion que no queremos perder -> Miedo a modificar el codigo ya optimizado
% dgg: - Controlando la regresion de la eficiencia, perdemos el miedo a modificar codigo optimizado
% dgg: - Si durante una iteracion de desarrollo, haciendo un refactoring o añadiendo una funcionalidad, varia la eficiencia tenemos feedback y podemos actuar
% dgg: - Consecuencia: Podemos optimizar código sin perder agilidad en el diseño

Como ya hemos comentado anteriormente, el objetivo del proyecto presentado es introducir una nueva herramienta para evitar la regresión en cuanto a eficiencia del código.


La optimización del software ha sido uno de los campos a los cuales se les ha dedicado más esfuerzo  debido a que un sistema optimizado obtiene mejoras en diversos factores como la velocidad de ejecución, el espacio físico o el consumo de recursos.
Al principio de la informática estos factores eran críticos ya que el desarrollo tecnológico era limitado, con lo cual, el software debía centrarse en la optimización obviando el diseño.
Sin embargo, actualmente, la tecnología ha evolucionado de tal manera que, aunque la eficiencia siga siendo uno de los requisitos esenciales de cualquier sistema, el esfuerzo debe compaginarse entre la eficiencia y el diseño.

El objetivo por el cual se tiene en cuenta el diseño a la hora de programar es poder agilizar  el  mantenimiento del software.
Si tenemos un código limpio, sin redundancias y agrupando en métodos, clases y archivos, se agilizarán los procesos de entendimiento, debugging y ampliación del software.
El hecho de tener un buen diseño puede ser útil a la hora de mejorar la eficiencia del sistema, ya que será más sencillo refactorizar el código.
Sin embargo, en el caso que el esfuerzo se focalice o bien en la eficiencia o bien en el diseño, la mejora de uno se realizará en detrimento del otro y se provocará una confrontación entre diseño y eficiencia que debe ser evitado.

Por ejemplo, la herencia en la programación orientada a objetos puede ser una gran ayuda para obtener un diseño esquemático y claro, sin embargo, es contraproducente respecto a la eficiencia ya que, cuando un método de la clase padre se llama desde la clase hijo, hay que recorrer el árbol de herencia buscando el método.
En el caso que la herencia tenga varios niveles o haya herencia múltiple (una clase hijo tiene dos o más clases padre), el recorrido del árbol se complica y la disminución de eficiencia es relativa al número de clases pertenecientes a la herencia.

Otro ejemplo de diseño elegante que puede pecar de poco óptimo es el diseño por capas.
En el diseño por capas, cada capa resuelve un aspecto a la capa anterior.
Esta separación de responsabilidades clarifica el diseño y el código y facilita la localización de errores.
Sin embargo, a menudo, cada capa añade latencia al proceso, con lo cual, un abuso de capas puede conllevar consigo una regresión de eficiencia importante.
Un ejemplo concreto de este diseño es la torre OSI.
El modelo OSI divide las funciones de un protocolo en una serie de capas, donde cada capa tiene la propiedad de usar funciones de la capa inferior y de exportar las suyas a la capa superior.
Al ser un modelo muy estructurado, académicamente es perfecto para explicar las diferentes funcionalidades de un protocolo.
Sin embargo, al estar formado por siete capas, cada una de ellas añade latencia al proceso final, con lo cual, la eficiencia disminuye notablemente.
Por esa razón, en la práctica se unen y mezclan las capas con la finalidad de optimizar la ejecución.

% dgg: - Un diseño optimo puede pecar de poco mantenible (ya lo has comentado), añade ejemplo 'diseño monolitico'
% dgg: - Introduce el ejemplo de este articulo desde el punto de vista de optimizacion (no de seguridad)
%          http://blogs.zdnet.com/threatchaos/index.php?p=311
%        Fijate en los dos grafos de llamadas. (Incluyelos en la memoria por favor, referencia incluida)
%         http://blogs.zdnet.com/images/SysCallApache.jpg
%         http://blogs.zdnet.com/images/SysCallIIS.jpg
%      - Discute:
%        Cual es mas facil de mantener? Cual ha intentado hacer optimizaciones antes de tiempo? 
%        Cual tiene mas capas? Cual define mejor las interficies? Cual acaba siendo mas rapido?
%        Los graficos, te explico, representan el grafo de llamadas al sistema que implica una peticion http al servidor
%        recuerda que una llamada al sistema es que el programa llama a una funcion del sistema operativo

En el otro extremo, se puede focalizar el esfuerzo en la eficiencia en detrimento del buen diseño.

En estos casos el problema radica principalmente en el mantenimiento del software.
Como ya ha sido comentado, que el desarrollo del software se centralice en la optimización del sistema puede ser debido a limitaciones de hardware.
Este hecho provocará que la estructuración del código pase a un segundo plano, con lo cual, el desarrollo del software se realizará a base de parches que complicarán el código gradualmente hasta que el mantenimiento sea insostenible y, cuando el programa quede obsoleto, la única solución será empezar el desarrollo de cero, lo que conlleva un coste en horas de programación que podría haber sido evitado si el diseño hubiera creado teniendo en cuenta futuras ampliaciones.

Un ejemplo de este caso es un diseño monolítico, es decir, un diseño creado con el menor número de funciones posibles, cuya consecuencia directa es la repetición de código.
El hecho de tener menos llamadas a función implica que el proceso se ejecute más rápido,
sin embargo, el mantenimiento del software será muy costoso, ya que, el hecho de no tener el código dividido en funciones, dificulta tanto la búsqueda de bugs, como la modificación del código.

\begin{figure}[!ht] 
	\centering
	\fbox{\pdfimage width 6in {Imagenes/SysCallApache.jpg}}
	\caption{Grafo de llamadas al sistema de un servidor Linux con Apache} 
	\label{fig:SysCallApache}
\end{figure} 

\begin{figure}[!ht] 
	\centering
	\fbox{\pdfimage width 6in {Imagenes/SysCallIIS.jpg}}
	\caption{Grafo de llamadas al sistema de un servidor Windows con IIS} 
	\label{fig:SysCallIIS}
\end{figure} 


Como hemos visto en los ejemplos anteriores, diseño y optimización pueden estar enfrentados entre sí.
Sin embargo, también es cierto que un diseño elegante, además de facilitar el rendimiento, se puede refactorizar con mayor facilidad para que llegue a ser más óptimo.
 
Como ejemplo podemos comparar los grafos de llamadas al sistema de Apache e IIS extraídos de la web \cite{ApacheVsIIS}.
Ambas imagenes muestran el mapa de llamadas al sistema producido por la subida de una página html con una imagen a un servidor web.
La imagen \ref{fig:SysCallApache} muestra las llamadas de sistema del servidor Linux,
mientras que la imagen \ref{fig:SysCallIIS} muestra las llamadas de sistema del servidor Windows.
Observando las imágenes, comprobamos que el servidor Linux es más mantenible debido a que el número de llamadas a sistema es menor y tiene una estructura más clara. Esto es debido a que la optimización parte de un diseño bien estructurado y mantenido, con lo cual, al optimizar el sistema, el diseño no ha salido perjudicado.
Por contra, el servidor Windows ha sido optimizado con anticipación y descuidando el diseño, 
de manera que la estructura del sistema se ha ido complicando gradualmente, dificultando así el mantenimiento del sistema tanto en diseño como en optimización.

Con este último ejemplo comprobamos que optimizar incorrectamente, perjudica tanto al mantenimiento del diseño como a la eficiencia del sistema.
Por esta razón, Fowler \cite{Refactoring} propone comenzar a optimizar cuando el diseño del sistema está ya maduro, algo que sucede hacia el final del desarrollo.
Sin embargo hay ámbitos en los que la optimización es clave (sistemas de codificación multimedia, sistemas de interacción en tiempo real, servidores web...).
El proyecto presentado está orientado para que, en estos casos, la optimización esté presente desde el principio del proyecto.
El problema de la optimización es que es un proceso muy costoso,
con lo cual, se tiene miedo a cambiar código que ya esté optimizado para que no sufra una regresión.
Con los tests de eficiencia presentados en este proyecto, se controla constantemente que no haya regresión de eficiencia, con lo cual,
si durante una iteración de desarrollo, haciendo un {\it Refactoring} o añadiendo una funcionalidad, varía la eficiencia negativamente tenemos feedback y podemos actuar antes de agravar el problema.
Este hecho permite al desarrollador optimizar el código sin perder agilidad en el diseño y, por lo tanto, hace que el proceso de optimización no sea tan costoso.
