sábado, 17 de enero de 2015

Analisis de Rendimiento



Analisis de Rendimiento



Introducción


Empiezas un proyecto y empiezas a aplicar todo lo que has aprendido en la universidad y en los libros, blogs, consejos que has ido leyendo e intentar aplicar toda la ingeniera del software al nuevo desarrollo. Te creas tus diagramas de clases, secuencia, estás un minutos o más pensando que nombre dar a una clase, y las relaciones entre ellas.

Un mes despues..

Han surgido nuevos requisitos que estaban ocultos, otros se han derivado en otros requisitos y los jefes quieren ver resultados.  ¿Solucion? tiras lineas de código a casco porro, y a usar el copy&paste más que nunca (esto ya debería ser una señal de aviso..que algo no va bien). Sacas una versión, y los testeadores y usuarios: "esto parece que va más lento.."

Efectivamente, se ha dedicado el tiempo a tirar lineas de código y a sacar funcionalidad, sin reparar en el rendimiento de la aplicación.

Creo que durante todas las fases del desarrollo hay que parar de tirar lineas de código y mirar como va el rendimiento de la aplicación. El Visual Studio ofrece mucha información, que la verdad, uno casi se pierde entre tanta información. Y con este post, intentaré que me sirva para tener una especie de protocolo para cuando quiere hacer dicho analisis seguir esos pasos y hacerlo de la manera más efectiva. También, entender un poco más el tema del rendimiento.

Para ver el tema de rendimiento, me he creado un pequeño programa que genera 1000 primitivas, y según está generando las primitivas de la lotería, va dibujando la frecuencia de cada numero en la ventana. Y final de la simulación, se ve una casi distribución uniforme.



Así uno puede ver si tienes mucho histórico sobre las primitivas, la probabilidad se parece y si una tiene poco histórico, casi no tienes patrones para hacer cálculos y jugar a la Primitiva. En fin, en su día incorpore a un programa a la posición del Sol y de la Luna por los efectos gravitacionales sobre las bolas del bombo, pero nada...las variables a tomar en cuenta sin inmensas..pero bueno, nos entretenemos pensando en como...pero bueno, vamos al grano...



Variables


Hay muchas páginas que hablan sobre las variables, a si que, no voy enumerarlas, solo voy a comentar lo que me parecen y así, entenderlas mejor.

El método  public List<Primitive> Generate(int numberOfPrimis, onPrimitiveGenerated handle) es el método donde empieza a ejecutar todo. Y este método tarda alrededor de 7.062 milisegundos.

Lanzamos el profiler en modo "intrumentalización".

Paso 1:
Ponemos Current view a "Funtions"



Paso 2:
Ordenamos los resultados por la la columna "Funtion Name". Aquí algunos dirán por alguna columna donde están los resultados de los tiempos, pero como me quiero centrar solo en los tiempos de las funciones que he creado, lo ordeno por los nombres (seguro que hay una manera de filtrar, pero aún la desconozco).




Paso 3:

Buscamos la función que tenga el tiempo "Elapsed Inclusive Time", y este tiempo es el de la función
primiLotto.Kernel.PrimitivesGenerator.Generate(int32,class primiLotto.Kernel.onPrimitiveGenerated)

y sus tiempos en el profiler es de:

6.991,38(Elapsed Time Inclusive)

que, casualmente es muy parecido a con el otro tiempo calculado por el Stopwatch de 7062mseg.

Entonces, ya tenemos una correlacion. El "Elapsed Time Inclusive" mide el tiempo dentro de una función y también el tiempo de las funciones a las que llama. Es decir, el tiempo total, desde que se inicia hasta que termina.

De aquí, vamos a ver si derivamos el significado de las demás variables.

"Elapsed Exclusive Time" en el ejemplo para el método Generate es de 0.59 mseg. ¿como es posible?? esta variable lo que mide es el tiempo que es ha ejecutado el método, sin incluir las funciones hijas. Es como si cuando se llama a una función hija (en este caso por ejemplo al método generatePrimi ) es como si se parase el cronometro y a la vuelta de la función, se pone de nuevo el cronometro.

Entonces, el método que tenga mayor "Elapsed Exclusive Time" es la que me va a decir, que función esta siendo un cuello de botella.

Si ahora nos fijamos en que función tiene mayor ""Elapsed Exclusive Time" , esta es:

Y la función es drawProbability con un tiempo de 23.77mseg. Pero ojo!, hay si tiempo "Elapsed Inclusive Time", es de 1042.92, con lo cual, hay hay 'algo' en la función, que la hace ir más lenta.



Pero vamos a ver que nos dice el Visual Studio, generando el el árbol con las llamadas más costosas.






Nos dice el VS que el cuello de botella está en efectivamente en drawProbability . Y las llamadas a la API del GDI+ es lo que le está haciendo ir más lento. Mirando el código se ve que en cada iteración del bucle, se crea Pen y Brush que se puede crear al principio, ahorrando la creación de estos objetos 49 veces.

Optimizando


Creando los objetos Pen y Brush fuera del bucle en el método drawProbability , en tiempo "Elapsed Time Inclusive" es de 6564 msg.

7062 - 6564 = 498 msg ahora más rápido para 1000 simulaciones.

Truquito

Una de las cosas que se podría hacer para detectar a tiempo que una función está tardando mucho es por poner lo siguiente

public void DoSameThink()
{

    Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

  //codigo de la función
//...............................
//...............................

    stopwatch.Stop();

Debug.Assert(stopwatch.ElapsedMilliseconds < 1000, "El método DoSameThink ha superado 1 segundo");

}

ejemplo:



Conclusión

No he contado nada que este escrito por otros blogs, libros, pero a mí me ha servido para asimiliar mejor el tema del rendimiento, de como analizar y ver los cuellos de botella. Si tu también estabas en ese caso y te ha ayudado, estupendo!!!

Como se ve, hay muchas variables que da el visual studio que aquí no se han nombrado, pero ya con estas dos variables que hemos nombrado, podemos mejorar algo el rendimiento de nuestro código.

El código fuente por está aquí por alguien quiere bajarlo y trastear con ello modificandolo.

En próximas, a ver si me adentro más en este campo.

Félix Romo
felix.romo.sanchezseco@gmail.com




martes, 6 de enero de 2015

Como construir un control Acordeon (Accordion control)

Como construir un control Acordeon (Accordion control c#)

Introducción


A lo largo del desarrollo de un proyecto, van surgiendo nuevos requisitos, o normalmente, son ampliaciones de los requisitos existentes. También por esto, es muy conveniente, antes de escribir código, contar hasta diez, es decir, diseñar, hasta que el diseño sea estable y pueda soportar los requisitos presentes y los posibles futuros (también hay que diseñar para estos). Aunque claro, muchos jefes, verán este trabajo como no productivo por que no hay lineas de código escritas, pero puede ahorrar días e incluso meses, a lo largo de la vida del código. Pero en fin, esto es otra historia...

Algo que me paso en un proyecto. Había que mostrar unos resultados de datos en una ventana provenientes de unos cálculos, podrían ser un resultado o muchos, y luego también añadir más resultados o borrar resultados que no interesaban. Aquí estime que uno de los controles que podrían encajar era de tipo acordeón.

Estupendo, ya tengo la idea que tendrá la vista, la diseño a portaminas y folio, y aquí que vemos que .Net no tiene un control de acordeón. Entonces, investigando por la red, para ver otros desarrolladores lo hacían. Me encontré con varios ejemplos, pero quería desarrollar el mío propio y así, ya tendríamos el control total sobre este control por si la vista necesitaba algo adicional que no tuviesen los demás controles.

Al lío..

Una de las fuentes en las que me base para construir el mío fue este:

http://sourceforge.net/projects/accordion/

Y empecé a investigar como estaba diseñado, una vez que capte la idea general, empeze a desarrollar el mío propio.


Las clases principales son:
Accordion: es la clase que representa el control..claro..

CheckBox: es una clase de .Net que aquí se usa como control que cuando se hace click, se oculta o aparece el control que hay debajo de este.
Control2: es una clase que une los objetos CheckBox y FLP.
FLP: es un clase que representa un FlowLayoutPanel. Mejor dicho deriva. Y es quién controla, cuando aparece un control o se oculta.

A partir de esta idea, empeze a desarrolar mi acordeón....


Mi Accordion Control



ownAccordion: clase que representa al control acordeón.
TitleControl: clase que representa el control que se va a quedar como cabezera de los controles que se añadan. Aquí se usa un usercontrol y asi poder añadir botones. En este caso, '+' y '-' para asi, añadir más controles al propio acordeón o borrarlos directamente.
myFLP: es la clase que deriva de un FlowLayoutPanel, y controla el añadir o borrar los objetos Control que se añaden al acordeón. En este ejemplo, los objetos ClientDataControl

Sé que le falta mucho a este control para que tenga una buena apariencia, pero creo que la base para seguir desarrollando. Aquí, por ejemplo, en un equipo de desarrollo, este control lo desarrollaría un programador senior, analista/programador, ingeniero software o el mismo jefe de proyecto (los cuales lo desarrollarían no acoplado el proyecto actual, sino de forma que se pueda usar en otros proyectos), y luego pasarlo otro desarrollado para que lo vaya ampliando, y además, aprendiendo. Una forma de ser mentor también.

¿Como queda?



La parte izquierda es de http://sourceforge.net/projects/accordion/

El código fuente se puede descargar de aquí.


Conclusión


Aparte de leer libros, revistas, investigar códificando, probando,..el leer código que hay por la red, intentar desarrollar los mismo, es otra forma de aprender. Y además, te habrá la mente a hacer las cosas de otra manera y lo mismo, más fácil.

Félix Romo
felix.romo.sanchezseco@gmail.com


viernes, 26 de diciembre de 2014

Antonio Recio, no pico código

Antonio Recio, no pico código

Hace semanas, escuche la frase "no, pero yo ya no pico código". Es como sí el picar código, estuviera en la más bajo del escalafón de la programación, y de hecho, en España, se percibe de esta manera. Solo hay que echar un vistazo a las ofertas de empleo cuando ofertan un puesto de programador, o analista/programador, y ver el rango de retribución económica que ofrecen.

Y tener está visión, ¿que consecuencias tiene?. Primeramente, yo no soy muy indicado para hablar de esto, y lo hago desde mi experiencia personal. Además, escribiendo este post, hago una reflexión interna sobre este asunto.

Cuando una empresa busca el kilo de programador a lo más barato, la verdad, no sé lo que está pensando sobre lo que hace o deja de hacer un programador. Solo alcanzo a imaginar que piensan que es escribir lineas de código para añadir/modificar/arreglar un software. Si esto es así, bien, la verdad que no están tampoco equivocados, pero bajemos unos niveles más.

Cuando un programador (llamo programador a todo a quién pica código, desde un programador junior a un project leader, que pica las partes clave de programa) esta escribiendo código, también esta diseñando, está definiendo una arquitectura. Pero como será esta arquitectura, ¿compleja o habría otro método más fácil? ¿la está documentando para que sea entendible por otro programador?

Y aquí, es donde se ve la diferencia entre un programador bueno y otro menos bueno.

Un código escribo por un menos bueno programador a la larga, será:
 - Más difícil de añadir nuevas funcionalidades,
- De encontrar bugs y reproducirlos.
- Más propenso a tener futuros bugs.

Esto hace que se extienda el tiempo haciendo más caro el software, y que el cliente este más descontento. Y si el cliente está descontento, mala cosa. ¿De quién es la culpa? todos lo sabemos, del programador! solo y exclusivamente. No de quién (una parte claro) no alcanza a ver la diferencia entre un buen programador y uno menos bueno.

Pero que sucede si hace está diferencia. Si en un equipo hay un buen programador y otro menos bueno, el bueno ayudará y guiará al menos bueno, el menos bueno se sentirá motivado para aprender más. El código será más mantenible, antes de programador algo nuevo, harán pruebas y luego las incorporaran, y además será menos propenso a errores, acortando tiempos de desarrollo y reparaciones de bugs. Con lo cual,el cliente estará más contento.

Entonces, desde este punto de vista, uno puede decir con orgullo: "Soy Félix, y pico código".

Aunque, me he referido aquí a programadores, al final, todos tendemos o queremos ser un buen ingeniero software. Que lo mismo, el problema, es que todavía no se ve el desarrollo de software como una ingeniería, donde convergen o se tocan diferentes disciplinas,  y se piensa que es 'solo' picar código.

Está imagen, me resulta muy ilustrativa.



¿Y que visión hay en otros países?
Una de las primeras diferencias, por lo menos, lo que yo ví en UK, es que, en la mayoría de las empresas IT, antes de hacer una entrevista cara a cara (ya previamente pasada la del telefono...), es que te envían un ejercicio de programación, te dan un tiempo, y tienes que enviarlo de vuelta con el código fuente. Si es verdad, que en España, me he encontrado con dos empresas, una de juegos y otra una IT.

Y para contestar a está pregunta, hay personas que dan una respuesta muy ilustrativa.

Los Reyes del Mambo: los programadores mejor pagados

"Lo que más llamó su atención fue que, al contrario que aquí en España, ser programador era una profesión que no estaba asociada a un rango bajo ni a salarios vergonzosos."

"Existe una enorme confusión sobre lo que es o no es un programador. En España, la programación se considera un primer nivel: programador, analista, jefe de proyecto, y gerente. Una actividad mal pagada. En la universidad, muchos profesores recomiendan a sus alumnos huir de la programación. En Estados Unidos, en cambio, hay un auténtico culto al programador: muchos de los grandes emprendedores tecnológicos lo son gracias al hecho de saber programar."

"La falacia del Programador Perdido"
"Es cierto que en España es difícil encontrar buenos programadores. Difícil, pero no imposible. Si quieres encontrar un buen programador, básicamente sólo tienes que hacer una cosa: pagarlo. "


Ahora, leyendo las siguientes noticias, creo necesario que no solamente se tenga en cuenta a los buenos programadores y su importancia, sino a todos los que componen el equipo de un desarrollo software. Y solo son noticias de los pasados 4 meses...y de los cuales nos hemos enterado por la prensa...¿Y de los que no nos enteramos?

24/11/2014
Un fallo en el sistema informático de la DGT impide el pago de tasas y multas a los ciudadanos

30/08/2014
Retrasos de hasta una hora en Barajas por un fallo en el sistema de radares

22/12/2014
Un fallo informático ha impedido pagar esta tarde los billetes premiados

18/12/2104
El Portal de la Transparencia arrastra desde su inauguración un grave problema de seguridad


Un saludo

Félix Romo

felix.romo.sanchezseco@gmail.com

domingo, 23 de noviembre de 2014


Personalizar el DataGridView


Introducción


Algunas veces, en un datagrid, queremos visualizar diferentes informaciones en una celda y no simplemente un valor por celda.

Por ejemplo, un ejemplo, sería un grid donde con una cierta frecuencia, el contenido numérico va a variar, pero, ¿qué sucede si para el usuario es importante no solamente la nueva cifra sino el incremento?




Suponiendo que tenemos una aplicación donde lleva el saldo de los Pitufos. Para el usuario de la aplicación, lo mismo sería interesante, no solamente ver el nuevo saldo, sino el tanto por ciento que ha variado.

Con los controles que nos ofrece .Net, una de las formas, sería añadir una nueva columna "% Balance", donde refleje la variación. Pero otra forma, sería, que en la misma celda, en letra más pequeña y con una flecha (hacía arriba para incrementos positivos y hacía abajo para incrementos negativos) para mostrar esta información.

Quedaría como:






Personalizar la celda del data Grid


Paso 1:

Crear una clase que derive de alguna de las siguientes clases, 

      System.Windows.Forms.DataGridViewButtonCell
      System.Windows.Forms.DataGridViewCheckBoxCell
      System.Windows.Forms.DataGridViewComboBoxCell
      System.Windows.Forms.DataGridViewHeaderCell
      System.Windows.Forms.DataGridViewImageCell
      System.Windows.Forms.DataGridViewLinkCell
      System.Windows.Forms.DataGridViewTextBoxCell

En este ejemplo, se eligio derivar de DataGridViewTextBoxCell, ya que era la clase que más acercaba a lo que queríamos representar. Dependiendo de lo que contendrá la celda, asi será la clase elegida para derivar.

class DataGridViewCellDoubleIncrement : System.Windows.Forms.DataGridViewTextBoxCell


Paso 2:

Sobreescribimos el método Paint. Este método será llamado siempre que la celda vaya a ser pintada. Aquí estará el código donde dibujaremos la información del incremento del %.

protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, System.Windows.Forms.DataGridViewElementStates cellState, object value, object formattedValue, string errorText, 
            System.Windows.Forms.DataGridViewCellStyle cellStyle, System.Windows.Forms.DataGridViewAdvancedBorderStyle advancedBorderStyle, System.Windows.Forms.DataGridViewPaintParts paintParts)
        

Paso 3:

Sobre escribimos el método:

protected override System.Drawing.Size GetPreferredSize(System.Drawing.Graphics graphics, System.Windows.Forms.DataGridViewCellStyle cellStyle, int rowIndex, System.Drawing.Size constraintSize)


Este método será llamada para cuando se necesite saber el tamaño que tendrá la celda. Como vamos a añadir más información a la celda, necesitará más espacio. Entonces, aquí es donde se añada ese espacio extra para mostrar la información del %.

Paso 4:

Crear una clase que derive de .DataGridViewColumn, y está clase representará la columna que contendrá nuestro nuevo tipo de celda para visualizar el incremento del %.

 public class DataGridViewColumnDoubleIncrement : System.Windows.Forms.DataGridViewColumn


Paso 5:
Para que la columna sepa DataGridViewColumnDoubleIncrement  que tipo de celdas debe de crear, en el constructor se añade la línea:

this.CellTemplate = new DataGridViewCellDoubleIncrement();

Con lo anterior, ya tendríamos lo básico para personalizar la forma en que queremos visualizar los datos en cada celda.

Como ver el código, es más explicativo que párrafos y párrafos, en este link está el código fuente.

Conclusión

Como se ha visto, con un poco de trabajo, puede resultar de gran efecto visual en el interface de usuario y además, que el usuario, vea la información más cercana a su modelo mental, creando una mejor experiencia de usuario.

Félix Romo
felix.romo.sanchezseco@gmail.com



miércoles, 5 de noviembre de 2014


La API de tu interfaz (UserControls)


Introducción


Cuando uno desarrolla una aplicación de escritorio, piensa que el interfaz será estable, que una vez que se implemente, no se modificará y si se modifica son algunos detalles. Si se sigue este principio durante el desarrollo del UI, tendremos un problema. Ya que al cabo de una año o dos, por razones comerciales, de un cliente especial, de un nuevo jefe, se modifique gran parte del UI.

Un ejemplo, supongamos que estamos desarrollando un software para la gestión del video club, y en una parte del interfaz tenemos un ListView con el titulo de la pelicula, director, etc. Esta ListView se rellena desde una base de datos. Creo que el típico error aquí, es hacer visible la ListView con el resto de la aplicación. Es decir, seguir estos pasos:

- Leer información de las peliculas de la base de datos
- Añadir información a la ListView.



Pero vamos a complicar un poco la cosa. Ahora, una vez que se la información principal de la película, queremos que en otra parte de la pantalla, se muestre el argumento de la película.
Con lo cual, lo más normal es capturar el evento de selección de la ListView para actualizar y visualizar el argumento de la película seleccionada.



private void ON_lvFilms_SelectedIndexChanged(object sender, EventArgs e)
        {
            showPlotFromFilm();
        }



Así, el método showPlotFromFilm accederá al control listview, para obtener el titulo de la película y asi buscar en la base de datos o en memoria y mostrar el argumento. Aquí, hemos introducido un acoplamiento de miedo.

El problema viene cuando al cabo de un mes o un año, por el motivo que sea, hay que cambiar la listview por un treeview, ya que se ha decidido ver las películas por géneros y el treeview es por el momento el que más se ajusta.

Entonces, si hay que cambiarlo, habría que mirar todo el programa, desde donde es visible el listview para ahora engancharlo a un treeview. Podría llevar mucho tiempo, más luego los posibles bugs por un cambio que afecta tanto.

¿Cómo disminuir este riesgo?

Crear la API del UI para tu Aplicación


Para disminuir este riesgo, una opción (la verdad que otra de momento no alcanzo a verla) es crear un control de interfaz de usuario que su responsabilidad sea la de visualizar películas.

Al igual que existen los controles para visualizar texto (TextBox) o un fichero .jpg (PictureBox), nos creamos un control para representar un objeto del dominio del problema, en este caso, una conjunto de película (no escribo 'lista' para no sugerir que en la implementación que sea una lista).

El control que visualizará la lista de películas será FilmControl.cs (deriva de UserControl)

Y tendrá una propiedad:

public List<Kernel.Film> Films

Que de hay el control rellenará la lista de las peliculas en la lista que tiene interna, pero si en el futuro se cambia a un arbol, no afectaría externamente, es decir, fuera del ámbito del control.

Y luego tendría el evento:


[Description("Se selecciono una pelicula en el control.")]
public event selectFilmHandle ONselectFilm;




Que se dispara cuando el usuario seleccione una película en la listview. Si en el futuro fuese una arbol, la implementación por dentro, detectaría la selección en el arbol y lanzará despues el evento ONselectFilm.



Esta ha sido una forma algo simple de intentar explicar la buena practica de crear partes del interfaz de usuario que manejen directamente conceptos a nivel del dominio del problema y no de implementación.

En este ejemplo se ve por ejemplo en ONselectFilm, donde es un evento que se lanza cuando se selecciona una pelicula, pero por el contrario si fuese ON__lvFilms_SelectedIndexChanged, es un evento que se lanza cuando se selecciona un elemento de la lista, y lista es ya un elemento de la implementación, y sin embargo en ONselectFilm, no se hace referencia a ningún elemento de implementación del interfaz, sino que solamente se ha selecionado, ya sea por un ListView o un TreeView o cualquier otro UI más extraño. Así, hemos reducido el acoplamiento entre partes del programa enormemente.

Para descargar el código fuente de videoClub aquí.

Conclusión


Como experiencia, esta forma de trabajar me ha ahorrado bastantes horas de trabajo, ya que se intento crear una api UI para los objetos del dominio del problema (en la carpeta Kernel del ejemplo), de esta forma si una parte del interfaz se quiere llevar a otro sitio del interfaz, o recolocar la interfaz, será más rápido y menos propenso a errores (que los habrá claro).

Félix Romo

felix.romo.sanchezseco@gmail.com









miércoles, 28 de agosto de 2013

Detectar noticias interesantes con un clasificador Naive Bayes


Detectar noticias interesantes con un clasificador Naive Bayes

Hace mucho tiempo, cuando empezo el auge de internet y solo tenía acceso a las redes desde el trabajo, me ví que no podía acaparar toda información a la que tenía acceso. ¿Qué solución me podría proporcionar?
ChotaWeb, una aplicación que tuviese todas las páginas web en las cuales estuviese interesado y luego el programa detectase si en alguna página habría alguna noticia interesante. Y si fuese así, avisarme por mensaje o por un correo.

El sistema que idee en aquella época era de los más simple: por palabras clave. Aún el interfaz de usuario conserva sus reminiscencias.



Pero hasta que hace poco, retome esté proyecto personal y mejorarlo de forma que de verdad detectara las noticias que me interesasen. Entonces, me tope con el clasificador Naive Bayes.

Encontre este tutorial en pdf el cual me sirvio para implementar un proyecto de prueba en C#, Bayes.sln

Tutorial on Naive Bayes Classification


El cual cuando se ejecuta para comprar que da los mismos resultados que el tutorial, tiene este aspecto:



Este proyecto se puede descargar el código fuente aquí

Una vez, desarrollado el algoritmo núcleo que determinará si una noticia es interesante o no, habrá que codificar el algoritmo anterior de C# a c++, ya que ChotaWeb está en c++ con MFC.


El formato que usa ChotaWeb en el fihero .cht es:

9    <numero de páginas>
http://elpais.com/tag/astronomia/a/ 
http://www.expansion.com/ 
http://www.noticias.com 
http://www.elmundo.es 
http://www.elmundo.es/navegante 
http://www.newscientist.com/news/ 
http://news.bbc.co.uk/ 
http://news.bbc.co.uk/2/hi/technology/default.stm 
http://news.bbc.co.uk/2/hi/health/default.stm 

03:00   <tiempo que se activa automáticamente para inspeccionar cada página>
1  <1 para que cada vez que se inicie windows se ejecute chotaweb. Aunque no funciona muy bien por el tema del directorio que tiene por defecto. Bug conocido>


El aspecto que tiene es el siguiente y donde se muestra una página que habla sobre los planetas extrasolares y como se ha entrenado al clasificador de Bayes con un documento que habla sobre los planetas extrasolares. Entonces, si todo va bien, en la inspección, debería de avisaros de que en dicha página hay una noticia que nos interesa.



Para su descarga el ejecutable del ChotaWeb y ver un poco mejor como funciona, aquí.

Necesitará que el fichero TrainingDocuments.xml contenga más documentos para que así, de unos resultados más precisos. Esos resultados, una vez mostrados el usuario, se guardan en disco para no volverlos a mostrar.

Creo que el crear otro proyecto en C# para investigar, probar un algoritmo, es bastante útil, ya que uno no 'guarrea' el código del proyecto en el que está trabajando. Además, el diseño del algoritmo se verá menos condicionado al proyecto en curso, y solo se centrará en el algoritmo.

Un saludo
Félix





lunes, 10 de diciembre de 2012

Patrón de software - Visitor


Patrón de software - Visitor


Muchas veces, cuando queremos mostrar un ejemplo de programación orientada a objetos, se sale con el ejemplo de dibujar en pantalla diferentes figuras, como triangulos, cuadros y circulos. Que si estamos programando en C# pasaremos un objeto Graphics para su dibujado y ya está, ya que cada objeto tendrá su posición. Y de esta forma, usaríamos el poliformismo.

En este ejemplo, tendremos, como todos sabemos, una clase abstracta Figura y las clases hijas, Triangle, Square y Circle.

Pero, ¿qué pasa cuando el rectangulo representa una zona de una ciudad, es decir, sus medidas están en metros?. Ya no se podrá dibujar un rectangulo de 100x100 metros, habrá que escalar las medidas a pixeles.
¿pero donde se hace esa transformación? ¿en las clases hijas?¿la del padre?

Creo que una forma sería tener una clase, en este caso, FigureView, donde tendría la responsabilidad de dibujar y de guardar todas las figuras. Y el metodo dibujar sería


void Draw(Graphcis g)
{
foreach(Figure figure in _figures)
{
       f.Draw(g,this);
}
}

aquí le pasamos el this, el objeto a un objeto FigureView que será el Visitor del patrón de diseño.

ya que luego el metodo Draw de Triangle será:

void Draw(Graphics g,FigureView view)
{
     view.Draw(g,this);
}

Y aquí, viene la importante, las clases hijas llamaran a los siguientes métodos sobrecargados de FigureView:

void Draw(Grapchis, Triangle t);
void Draw(Grapchis, Circle c);
void Draw(Grapchis, Square s);

así, se deja en FigureView la responsabilidad de dibujar, y hacer los cálculos en la escala que precise.

y también importante, en un solo bucle, podemos dibujar las distintas figuras que conforman la vista.

saludos y happy coding!