Le salio competencia a XUL

Ya hace un tiempo que XUL ( XML-based User-interface Language) hizo su aparaicion a travez de Mozilla firefox, ha estgado esperando lograr su estandarizacion, pero aprarecido algo que “talvez”, tire al agua esta joven tecnologia, pues una desventaja actual de XUL, es que el motor de interpretacion pricipal, es el propio nevegador, osea Firefox es interprete de XUL, existen intrepretes externos al propio Mozilla FireFox, como XULRUNNER, pero nada estandar, bueno, la competencia de XUL o la piedra en el camino por lo que se ve, es BINDOWS, lo que si BINDOWS NO ES FREE, ni nada por el estilo, ventaja para XUL??, quien sabe, Observen esto:

Demos de BINDOWS

Ejemplo de XUL

Escrito en XUL. Etiquetas: . No hay comentarios »

Progamacion Orientada A Aspectos

Lo ultimo y mas nuevo miren esto, el paradigma de la programacion orientada a los aspectos, vean esto

 

Ver mas y algo mas de info, y mas info, otro documento

Creo que debere cambiar el titulo del blog :P

El Efecto Hawthorne

El Efecto Hawthorne

    Entre 1927 y 1932 se realizó un estudio en la Hawthorne Plant de la Western
Electric Company en Cicero, Illinois. En este estudio se investigó el efecto que
producían en la productividad los cambios ambientales introducidos por los
investigadores. Los investigadores comprobaban que aumentando el nivel de
intensidad luminosa en la planta, se aumentaba la productividad. La sorpresa
fue cuando se disminuyo la intensidad luminosa y se comprobó que la
productividad también aumentaba. Prácticamente se podía cambiar cualquier
aspecto de la metodología de trabajo de la planta y la productividad
aumentaba.

    ¿Cómo podía ser esto? La mayor conclusión de dicho estudio es que a los
trabajadores les agradaba la atención recibida durante el estudio y se
esforzaban por rendir más. Otra conclusión equivalente es que la novedad
introducida por el nuevo sistema saca a los trabajadores de su letargo
metodológico, que a la gente le gusta la novedad y le aburre hacer las cosas
siempre igual.

    A esto se le ha venido a denominar el Efecto Hawthorne.
¿No será este efecto lo que nos proporciona mejoras en todas y cada una de
las nuevas metodologías? Esto parecería consistente con el resultado a largo
plazo de estos sistemas, que son rápidamente olvidados y no parecen obtener
tan buenos resultados cuando se convierten en la norma de trabajo.
El libro Peopleware, uno de los libros sobre gestión de proyectos más
influyente en nuestro campo, ya nos advierte de este efecto y nos avisa de
cómo podemos aprovecharlo a nuestro favor: Empresas como Fujitsu han
convertido la novedad en norma y en todos sus proyectos introducen algún
aspecto experimental para evitar el tedio de los trabajadores.
Estemos pues atentos a lo que cada sistema es capaz de aportar en nuestro
trabajo diario, practiquemos un escepticismo creativo con dichos sistemas,
aplicando aquello que realmente nos va a ayudar en nuestra tarea y dejando de
lado las recetas milagrosas. Y no nos olvidemos de disfrutar en nuestro trabajo.
El aburrimiento en el trabajo del programador es lo que realmente disminuye la
productividad. Algunas pequeñas novedades introducidas en cada proyecto
pueden hacer más por este que cualquier metodología existente.

Articulo Publicado Originalmente aqui

Refactorizacion

Aqui les dejo un articulo encontrado por ahi, que habla de la refactorizacion, el “rehacer y sin modificar” , espero les siva, bye

Refactorización en la práctica: peligros y soluciones

            Jesús Pérez y Jorge Ferrer

AgileSpain (http://www.agile-spain.com/)

Introducción a la refactorización
La refactorización es uno de los nuevos conceptos que se han introducido en la terminología del mundo del desarrollo apoyado por las metodologías ágiles. Extreme Programming, una de las metodologías ágiles más extendida, la incluye dentro del decálogo de prácticas que propone como fundamentales. Sin embargo la idea de refactorización no es nueva, lo que resulta novedoso es la forma en que se lleva a cabo, una forma ágil y agresiva, pero al tiempo ordenada y segura. Refactorizar es una idea apoyada por una técnica que debemos controlar si queremos llevar a cabo un diseño evolutivo y un desarrollo ágil de nuestra aplicación.

        ¿Qué significa Refactorizar? La mejor definición la obtenemos de uno de los padres de esta técnica, Martin Fowler, que dijo: “Refactorizar es realizar modificaciones en el código con el objetivo de mejorar su estructura interna, sin alterar su comportamiento externo”. De esta definición extraemos ideas muy importantes y conceptos que a veces estaban equivocados. Refactorizar no es una técnica para encontrar y corregir errores en una aplicación, puesto que su objetivo no es alterar su comportamiento externo. De hecho, no modificar el comportamiento externo de la aplicación es uno de los pilares de cualquiera de las prácticas que forman parte de la técnica, para lo que en muchas ocasiones se hace uso de las pruebas unitarias. La esencia de esta técnica consiste en aplicar una serie de pequeños cambios en el código manteniendo su comportamiento. Cada uno de estos cambios debe ser tan pequeño que pueda ser completamente controlado por nosotros sin miedo a equivocarnos. Es el efecto acumulativo de todas estas modificaciones lo que hace de la Refactorización una potente técnica. El objetivo final de Refactorizar es mantener nuestro código sencillo y bien estructurado.
Refactorizar nos propone seguir las técnicas matemáticas que consiguen reducir fórmulas muy complejas en fórmulas equivalentes pero más sencillas. En el entorno matemático estas simplificaciones consiguen eficiencia, además de facilitar el cálculo de problemas libre de errores, muy fáciles de cometer cuando las formulas son muy complejas. No obstante conseguir un código sencillo es una tarea muy compleja

Como dice Carver Mead:
“Es fácil tener una idea complicada. Es muy, muy complicado tener una idea simple.”

¿Por qué debemos Refactorizar nuestro código? Existen muchas razones por las que deberíamos adoptar esta técnica:

           - Calidad. La más importante. Conseguir ser un buen profesional pasa inevitablemente por conseguir que tu trabajo sea de calidad. Refactorizar es un continuo proceso de reflexión sobre nuestro código que permite que aprendamos
de nuestros desarrollos en un entorno en el que no hay mucho tiempo para mirar hacia atrás. Un código de calidad es un código sencillo y bien estructurado, que cualquiera pueda leer y entender sin necesidad de haber estado integrado en el equipo de desarrollo durante varios meses. Se acabaron los tiempos en que lo que imperaba eran esos programas escritos en una sola línea en la que se hacia de todo, tiempos en los que se valoraba la concisión aun a costa de la legibilidad.

           - Eficiencia: Mantener un buen diseño y un código estructurado es sin duda la forma más eficiente de desarrollar. El esfuerzo que invirtamos en evitar la duplicación de código y en simplificar el diseño se verá recompensado cuando tengamos que realizar modificaciones, tanto para corregir errores como para añadir nuevas funcionalidades.

            - Diseño Evolutivo en lugar de Gran Diseño Inicial: En muchas ocasiones los requisitos al principio del proyecto no están suficientemente especificados y debemos abordar el diseño de una forma gradual. Cuando tenemos unos requisitos claros y no cambiantes un buen análisis de los mismos puede originar un diseño y una implementación brillantes, pero cuando los requisitos van cambiando según avanza el proyecto, y se añaden nuevas funcionalidades según se le van ocurriendo a los participantes o clientes, un diseño inicial no es más que lo que eran los requisitos iniciales, algo generalmente anticuado. Refactorizar nos permitirá ir evolucionando el diseño según incluyamos nuevas funcionalidades, lo que implica muchas veces cambios importantes en la arquitectura, añadir cosas y borrar otras.

          - Evitar la Reescritura de código: En la mayoría de los casos Refactorizar es mejor que rescribir. No es fácil enfrentarse a un código que no conocemos y que no sigue los estándares que uno utiliza, pero eso no es una buena excusa para empezar de cero. Sobretodo en un entorno donde el ahorro de costes y la existencia de sistemas lo hacen imposible.

Refactorizar es por tanto un medio para mantener el diseño lo más sencillo posible y de calidad. ¿Qué se entiende por sencillo y de calidad? Kent Beck define una serie de características para lograra un código los mas simple posible:

- El código funciona (el conjunto de pruebas de la funcionalidad de nuestro código pasan correctamente).
- No existe código duplicado.
- El código permite entender el diseño.
- Minimiza el número de clases y de métodos.

A pesar de todo ello, refactorizar parece ser muchas veces una técnica en contra del sentido común. ¿Por qué modificar un código que funciona? (si funciona no lo toques) ¿Por qué correr el riesgo de introducir nuevos errores?, ¿cómo podemos justificar el coste de modificar el código sin desarrollar ninguna nueva funcionalidad?
No siempre es justificable modificar el código, no se reduce a una cuestión estética.

Cada refactorización que realicemos debe estar justificada. Sólo debemos refactorizar cuando identifiquemos código mal estructurado o diseños que supongan un riesgo para la futura evolución de nuestro sistema. Si detectamos que nuestro diseño empieza a ser complicado y difícil de entender, y nos está llevando a un situación donde cada cambio empieza a ser muy costoso. Es en ese momento cuando debemos ser capaces de frenar la inercia de seguir desarrollando porque si no lo hacemos nuestro software se convertirá en algo inmantenible (es imposible o demasiado costoso realizar un cambio).

       Tenemos que estar atentos a estas situaciones donde lo más inteligente es parar, para reorganizar el código. Se trata de dar algunos pasos hacia atrás que nos permitirán tomar carrerilla para seguir avanzando. Los síntomas que nos avisan de que nuestro código tiene problemas se conocen como “Bad Smells”.

¿En qué momento debemos Refactorizar?, ¿es necesario planificar tareas específicas de refactorización?
La Refactorización no es un proceso que podemos aislar como una tarea. Es necesario que lo incluyamos como una actividad que realizaremos cuando estemos desarrollando. No tiene que ser exactamente en el mismo instante en que identifiquemos un “Bad Smell”, ya que como se ha apuntado anteriormente, la funcionalidad no debe verse modificada. Por ello, debemos acabar lo que estemos haciendo (recuerda, pasos pequeños). Una vez finalizado el paso que nos ocupa, es el momento de abarcar la refactorización que debe realizarse de forma natural como parte del mismo desarrollo.

        La adopción de la refactorización como parte de nuestros desarrollos no resulta muchas veces sencilla, puesto que intuitivamente no proporciona la sensación de avanzar en la finalización de nuestro desarrollo. No obstante el tiempo empleado en refactorizaciones se verá muy justificado a la hora de seguir con el diseño, realizar modificaciones o buscar errores en el código para subsanarlos. Como dice el refrán: “Vísteme despacio que tengo prisa”.
¿Cuales son estos “Bad Smells”?, ¿cuáles son los síntomas de que la evolución de nuestro desarrollo se encamina hacia un caos?, ¿cuándo nuestro código empieza oler?. En [Fowler] podemos encontrar una lista de ellas como Código Duplicado, Métodos largos, Clases Largas, Cláusulas Switch, Comentarios, etc.

       Existen herramientas en “Ant” como “checkstyle” que permiten automatizar la identificación de algunos “Bad Smell” (con “checkstyle” es posible fijar el numero máximo de líneas de un método, o el máximo número de parámetros de un método).

        Una vez identificado el “Bad Smell” deberemos aplicar una refactorización que permita corregir ese problema. Para comenzar a Refactorizar es imprescindible que el proyecto tenga pruebas automáticas, tanto unitarias como funcionales, que nos permitan saber en cualquier momento al ejecutarlas, si el desarrollo sigue cumpliendo los requisitos que implementaba. Sin pruebas automáticas, Refactorizar es una actividad que conlleva un alto riesgo. Sin pruebas automáticas nunca estaremos convencidos de no haber introducido nuevos errores en el código al término de una refactorización, y poco a poco dejaremos de hacerlo por miedo a estropear lo que ya funciona. “Refactorizar sin tener un conjunto de pruebas asociado al proyecto debe dejárselo a los profesionales y no intentarlo en su casa”, claro que los profesionales lo primero que harán para Refactorizar será implementar las pruebas automáticas que cubran la funcionalidad que se ve cubierta por el código objetivo de la refactorización.

        ¿Cómo debe aplicarse una refactorización?, ¿cuáles son los pasos a seguir?

        La mejor forma de comprender el proceso es llevar a cabo una refactorización.
Ejemplo de aplicación de una Refactorización, Refactorizar es una práctica, por lo que la mejor forma de entender esta técnica es aplicarla. Lejos de pretender enumerar aquí todos esos patrones, mostraremos uno de ellos a modo de ejemplo: Reemplazar los condicionales con polimorfismo.
Esta refactorización nos convierte el tradicional autómata de estados realizado con “switchs” en algo extensible y orientado a objetos, más fácil de mantener y de arreglar al adoptar el patrón State. Para centrar ideas, supongamos que tenemos que actualizar un control de las puertas del suburbano de alguna ciudad. El problema es que está realizado a la antigua usanza, con un método que se encarga a base de “ifs” (que podemos ver como un caso degenerado de “switches” que funcionaría tanto con cadenas como con otro tipo de objetos) de pasar de un estado a otro:

public class Metro {
private int estado;
static final private int PARADO = 0;
static final private int EN_MARCHA = 1;
static final private int PARANDO = 2;
static final private int ARRANCANDO = 3;
public void cambiaEstado() {
if(estado==PARADO) {
estado = ARRANCANDO;
} else if(estado==EN_MARCHA) {
estado = PARANDO;
} else if(estado==PARANDO) {
estado = PARADO;
} else if(estado==ARRANCANDO) {
estado = EN_MARCHA;
}

        else {
throw new RuntimeException(”Estado desconocido”);
}
}
}

Tras cada paso de los que vamos a dar, ejecutaremos los tests para ver que se pasan convenientemente.
Lo primero que deberíamos hacer sería separar las condiciones en un único método y subir dicho método lo más alto posible en la jerarquía. En nuestro ejemplo no es necesario dado que ya cumple las condiciones pedidas.
A continuación creamos una clase por cada posible estado y sustituimos los “==” por “instanceof” y las variables estáticas enteras por referencias a instancias de esas clases.
Obviamente, necesitaremos una interfaz base para nuestras clases de estado que por ahora será un simple marcador.

Public interface Estado {}
public class Parado implements Estado {}
etc…
public class Metro {
private Estado estado;
static final private Estado PARADO = new Parado();
static final private Estado EN_MARCHA = new EnMarcha();
static final private Estado PARANDO = new Parando();
static final private Estado ARRANCANDO = new Arrancando();
public void cambiaEstado() {
if(estado instanceof Parado) {
estado = ARRANCANDO;
} else if(estado instanceof EnMarcha) {
estado = PARANDO;
} else if(estado instanceof Parando) {
estado = PARADO;
} else if(estado instanceof Arrancando) {
estado = EN_MARCHA;
} else {
throw new RuntimeException(”Estado desconocido”);
}
}
}

Nuestro siguiente y penúltimo paso será proveer de control a las clases nuevas para que sean ellas las que decidan el paso de un estado a otro. Implementando el patrón Estado (las diferencias entre éste y el Estrategia son de interpretación), asignaremos un método a la interfaz creada que nos devuelva el siguiente estado, y daremos contenido a dicho método en las clases de estado:

public interface Estado {
public Estado siguiente();
}

public class Parado implements Estado {
// Por eficiencia, implementamos ya el patrón singleton
private static final Parado instance=new Parado();
public static Parado getInstance() { return instance; }
private Parado() {}
public Estado siguiente() {
return Arrancando.getInstance();
}
}
etc…
public class Metro {
private Estado estado;
public void cambiaEstado() {
if(estado instanceof Parado) {
estado = estado.siguiente();
} else if(estado instanceof EnMarcha) {
estado = estado.siguiente();
} else if(estado instanceof Parando) {
estado = PARADO;
} else if(estado instanceof Arrancando) {
estado = estado.siguiente();
} else {
throw new RuntimeException(”Estado desconocido”);
}
}
}
Por fin tenemos nuestro código casi refactorizado. Ahora nos falta eliminar los “ifs” inútiles y hacer desaparecer el “throw” que no se va a dar nunca si hemos implementado bien los distintos estados:
public class Metro {
private Estado estado;
public void cambiaEstado() {
estado = estado.siguiente();
}
}
La refactorización ya ha terminado. Por la simplicidad del código que requiere un ejemplo escrito sería discutible si esta refactorización era necesaria. Pero en la práctica es muy habitual encontrar máquinas de estados más complejas codificadas en forma de switches muy difíciles de mantener. Esta refactorización demuestra cómo es posible organizar ese código paso a paso y con poco riesgo.
Implantación de la refactorización
Además de conocer los aspectos teóricos de la refactorización, también es importante profundizar sobre los aspectos más prácticos de la aplicación de esta técnica en un proyecto de desarrollo real.
En el caso de comenzar un proyecto desde cero, la refactorización continua es una práctica que conlleva un gran número de beneficios y evita de forma natural algunos peligros mencionados. Sin embargo, no siempre se parte de cero, y lo habitual es encontrarnos con código cuyo diseño y/o estructura está lejos de ser los más apropiados. Esta situación puede darse cuando tenemos que ampliar la funcionalidad de código previamente existente o simplemente porque en un proyecto empezado desde cero no se detectó la necesidad de refactorizar a tiempo.. En estos casos nos encontramos con una
refactorización a posteriori y deben tomarse medidas específicas para que afecte lo menos posible al ritmo normal de desarrollo.
Pasos para implantar la refactorización en un equipo
Implantar la refactorización debe realizarse de una manera progresiva. Nuestra experiencia en la implantación de esta técnica nos dice que es necesario seguir los siguientes pasos:
* Escribir pruebas unitarias y funcionales. Refactorizar sin pruebas unitarias y funcionales resulta demasiado costoso y de mucho riesgo.
* Usar herramientas especializadas (más información en [PerezFerrerColado60]). Las refactorizaciones en muchas ocasiones obligan a pequeñas modificaciones muy simples en muchas clases de nuestro código. Con herramientas especializadas estas refactorizaciones se realizan automáticamente y sin riesgo.
* Dar formación sobre patrones de refactorización y de diseño. Una buena base teórica sobre las refactorizaciones más comunes permite al programador detectar “Bad Smells” de los que no es consciente y que harán que su código se degrade progresivamente.
* Refactorizar los principales fallos de diseño. Nuestra recomendación es comenzar realizando refactorizaciones concretas que corrijan los principales fallos de diseño, como puede ser código duplicado, clases largas, etc que son refactorizaciones sencillas de realizar y de las que se obtiene un gran beneficio.
* Comenzar a refactorizar el código tras añadir cada nueva funcionalidad en grupo. Una vez corregido los errores del código existente, la mejor manera de aplicar Refactorirzacion suele ser al añadir una nueva funcionalidad, de manera que se desarrolle de la manera mas eficiente. Realizar discusiones en grupos sobre la conveniencia de realizar alguna refactorización suele ser muy productivo.
* Implantar refactorización contínua al completo. Esta es la última fase y es cuando cada desarrollador incorpora la Refactorizacion como una tarea mas dentro del su proceso de desarrollo de Software.
Refactorización continua
Refactorizar de forma continuada es una práctica que consiste en mantener el diseño siempre correcto, refactorizando siempre que sea posible, después de añadir cada nueva funcionalidad. Esta no es una práctica nueva pero esta adquiriendo mayor relevancia de mano de las metodologías ágiles..
Dado que una refactorización supone un cambio en la estructura del código sin cambiar la funcionalidad, cuanto mayor sea el cambio en la estructura más difícil será garantizar que no ha cambiado la funcionalidad. Dicho de otra forma, cuanto mayor sea la refactorización, mayor es el número de elementos implicados y mayor es el riesgo de que el sistema deje de funcionar. El tiempo necesario para llevarla a cabo también aumenta y por tanto el coste se multiplica.
Cuando un diseño no es óptimo y necesita ser refactorizado, cada nueva funcionalidad contribuye a empeorar el diseño un poco más. Por ello cuanto más tiempo esperamos mayor es la refactorización necesaria.
Esta es la mayor de las justificaciones de una refactorización contínua, que trata de evitar las refactorizaciones grandes haciendo refactorizaciones pequeñas muy a menudo.
En concreto se refactoriza de forma inmediata a la inclusión de una nueva funcionalidad. Esta práctica tiene dos ventajas principalmente:
•El código afectado es el mismo que el que se modificó para añadir la funcionalidad y por tanto se reduce o evita completamente los inconvenientes para otros desarrolladores.
•El tiempo que se debe dedicar es reducido dado que en ese momento se tiene un conocimiento preciso del código que se verá afectado.
Las claves para poder aplicar refactorización contínua son:
•Concienciación de todo el equipo de desarrollo.
•Habilidad o conocimientos necesarios para identificar qué refactorizaciones son necesarias.
•Compartir con todo el equipo de desarrollo la visión de una arquitectura global que guíe las refactorizaciones en una misma dirección.
Lo más habitual es que este tipo de refactorizaciones surjan nada más implementar una funcionalidad y dejar los tests pasando satisfactoriamente. Estos mismos tests nos garantizarán que el código sigue funcionando después de la refactorización.
Sin embargo no siempre resulta evidente para todos los desarrolladores la necesidad de una refactorización. En estos casos el uso de herramientas como javastyle y jcsc pueden emplearse como ayuda para identificar bad smells además de unificar criterios entre todo el equipo. En cualquier caso es importante que estas herramientas no sustituyan nunca al sentido común y se usen únicamente como ayuda.
La refactorización continua también es una muy buena estrategia para evitar la proliferación de ventanas rotas. Este término, presentado por Dave Thomas y Andrew Hunt en The Pragmatic Programmer, representa todo aquel aspecto del código que un desarrollador percibe como negativo. Según Thomas y Hunt un desarrollador no tiene muchos escrúpulos en dejar una ventana rota más, en un código en el que él percibe o es consciente de muchas otras ventanas rotas. Sin embargo cuando el código no tiene ninguna, ningún desarrollador quiere ser el primero en romper una ventana.
El principal riesgo de la refactorización continua consiste en adoptar posturas excesivamente exigentes o criterios excesivamente personales respecto a la calidad del código. Cuando esto ocurre se acaba dedicando más tiempo a refactorizar que a desarrollar. La propia presión para añadir nuevas funcionalidades a la mayor velocidad posible que impone el mercado es suficiente en ocasiones para prevenir esta situación.
Si se mantiene bajo unos criterios razonables y se realiza de forma continuada la refactorización debe tender a ocupar una parte pequeña en relación al tiempo dedicado a las nuevas funcionalidades.
El desarrollo dirigido por pruebas incluye de forma natural la refactorización continua, es lo que se conoce como TDD (Test Driven Development), práctica en la que se se hace la prueba, se añade la funcionalidad necesaria para satisfacerla, se generaliza la prueba y se refactoriza. La consecuencia inmediata de la aplicación de está práctica suele ser la evolución de la arquitectura inicial, en beneficio de un código bien estructurado, de una arquitectura orientada en todo momento a la funcionalidad implementada y por tanto, clara y sencilla, características necesarias para que un código sea mantinible y extensible.
Dificultades de la refactorización en la práctica
Si para afirmar que sabemos refactorizar basta con conocer los principales patrones y seguir una serie de sencillos pasos, para refactorizar con éxito es necesario tener en cuenta otros muchos factores propios de los proyectos de desarrollo reales.
En un proyecto real hay que ser consciente de que no refactorizar a tiempo un diseño degradado puede tener consecuencias muy negativas, pero a la vez debe tener en cuenta que el tiempo dedicado a refactorizar no suele ser considerado como un avance del proyecto, por los usuarios, clientes o gestores del mismo. Otros factores clave para una correcta aplicación de la refactorización son la forma en que afecta a otros miembros del equipo, el hecho de que un desarrollador realice refactorizaciones sobre código en el que todos están trabajando, el que una refactorización provoque que el código esté mucho tiempo sin funcionar o el efecto negativo de no refactorizar, en el ánimo de los desarrolladores por la sensación de no estar haciendo un trabajo de calidad.
Pero antes de tratar estos temas y cómo base para entender sus verdaderas implicaciones comenzaremos por tratar un factor raramente considerado en los libros o artículos sobre refactorización: el factor humano. Es decir, cómo afecta al desarrollador o equipo de desarrollo el refactorizar poco o demasiado, el hacerlo pronto o tarde, etc.
El factor humano
Una realidad a veces olvidada es que cualquier desarrollador prefiere hacer código de calidad. También es cierto que esta realidad a veces queda oculta debido a condiciones de presión excesiva o menosprecio del trabajo técnico.
En este sentido refactorizar es una forma de mejorar la calidad y por tanto es una forma de hacer que el desarrollador esté más orgulloso de su trabajo. Puede decirse que la refactorización bien realizada, rápida y segura, genera satisfacción.
Pero también hay un peligro en este hecho: el exceso de celo para conseguir un resultado de calidad puede llegar a suponer un número excesivo de refactorizaciones dando vueltas sobre diseños similares una y otra vez.
Una posible solución consiste en mantener la refactorización bajo control, definir claramente los objetivos antes de comenzar a refactorizar y estimar su duración. Si se excede el tiempo planificado es necesario un replanteamiento. Quizá haya ocurrido que la refactorización era más complicada de lo esperado pero también es posible que se esté refactorizando más de lo necesario.
Además de la evidente pérdida de tiempo, refactorizar demasiado suele llevar a dos efectos negativos. El primero es que la modificacion del codigo incremente la complejidad de nuestro diseño, que es justo el efecto contrario del que intentabamos lograr al refactorizar. Por otro, es habitual fomentar la sensación bien del desarrollador o bien de todo el equipo de que no se está avanzando. Una sensación que conduce a repercusiones anímicas negativas.
Trabajo en equipo
Un equipo de desarrollo debe ser uno. Todos los miembros del equipo deben conocer la arquitectura en cada momento, el estado actual, los problemas que tenemos y el objetivo que se busca. Una reunión diaria es una práctica que facilita la comunicación entre
todos los miembros del equipo, y supone una práctica que proporciona un momento a todos los miembros del grupo para plantear sus ideas, dudas e inquietudes respecto al proyecto.
Cuando un desarrollador refactoriza, afecta al resto del equipo. En este sentido, las refactorizaciones internas a una clase son menos problemáticas, pero con las arquitecturales es necesario tener mucho cuidado. Este tipo de refactorizaciones supone cambios en un gran número de ficheros y por tanto es probable que se afecte a archivos que están siendo modificados por otros desarrolladores. La comunicación y coordinación entre los afectados es fundamental para que esto no se convierta en un problema. Por tanto es necesario que en la reunión diaria del equipo (u otro mecanismo de comunicación equivalente) se planteen las refactorizaciones de este tipo. De esta forma se sabrá en todo momento quienes son los afectados y cual es el objetivo de la refactorización. De esta forma se promueve la colaboración de todos en la refactorización arquitectural que se va a llevar a cabo. A veces, el comentar con el resto del equipo una refactorización que parece muy necesaria, puede hacernos ver que lo que parecía una muy buena idea, no lo es tanto por otros factores que ven otros compañeros y de los que no eramos conscientes. Esto evita también refactorizaciones en sentidos contrarios propias de equipos en los que falta comunicación.
Las refactorizaciones en sentidos contrarios suelen estar motivadas por tener cada miembro del equipo una idea diferente del diseño hacia el que debe dirigirse ese código. Este problema de comunicación puede tener repercusiones bastante negativas en el diseño resultante. Una vez ocurre debe volverse a una situación en la que todo el equipo comparta una misma visión de la arquitectura y diseño del sistema. Para ello la mejor manera es parar el desarrollo y reunir al todo equipo para alcanzar un acuerdo común. En estas reuniones es muy útil el uso de pizarras y diagramas UML si son conocidos por el equipo. Incluso los miembros del equipo que no se habían visto involucrados en la situación aprenderán de la experiencia para evitar que vuelvan a darse en el futuro.
Una vez extraidas conclusiones, es posible que sea necesario realizar una refactorización más para devolver el código y el diseño a parámetros acordes con nuestros requisitos de calidad.
Refactorización a posteriori
En este apartado nos referimos con el término refactorización a posteriori a todas aquellos cambios estructurales que se realizan un tiempo después de la implementación de la funcionalidad existente. Existen varios motivos para encontrarse con esta situación. Algunos de ellos son:
•Un equipo comienza a trabajar con código desarrollado por un equipo anterior que o bien no tiene buena calidad o bien no está preparado para que se incorporen nuevas funcionalidades.
•Se ha aplicado refactorización continua pero la calidad del código o el diseño se ha degradado porque no se identificó a tiempo la necesidad de una refactorización o bien se equivocó la refactorización necesaria.
Este tipo de refactorizaciones tiene un riesgo mucho mayor que los que nos encontramos con refactorización continua.
Otra característica de estas refactorizaciones es que afectan no sólo al desarrollador o desarrolladores que van a aplicar la refactorización, sino a todos aquellos que trabajan con la parte del código afectada: por un lado no pueden trabajar con el código o deben
hacerlo con mayor precaución durante un tiempo; y por otro cuando vuelvan a trabajar con él se encontrarán con un diseño desconocido.
La mejor estrategia a seguir en estos casos es tratar de dividir la refactorización en el mayor número de pequeños pasos posible. Tras cada paso el código debe seguir funcionando sin fallos.
Antes de abordar cada uno de estos pasos se debe comunicar a todas las personas afectadas por los cambios que se van a realizar. De esta forma se evita que cuando vuelvan a trabajar con ese código se encuentren con un panorama completamente desconocido. En ocasiones también es recomendable dar explicaciones después de la refactorización para explicar el diseño final. Si este tipo de explicaciones son necesarias con demasiada asiduidad, la solución no es no realizarlas sino identificar los motivos de tanta refactorización a posteriori. Probablemente sea necesario un mayor grado de refactorización continua.
La refactorización por pasos tiene la ventaja de afectar menos al ritmo normal de desarrollo y permite ser intercalada con la implementación de nuevas funcionalidades. El principal inconveniente es que extiende en el tiempo la existencia de código imperfecto. Por ello siempre que sea posible debe completarse la refactorización en el menor tiempo posible.
Cuando una refactorización es difícil técnicamente y lleva un tiempo considerable se corre el riesgo de entrar en lo que podríamos denominar la espiral refactorizadora. Esta situación ocurre cuando una refactorización se complica y conduce a nuevas refactorizaciones hasta que llega un momento en el que no es posible o es muy difícil estimar cuanto tiempo queda para terminar de refactorizar.
Toda situación durante un desarrollo de software en la que no puede estimarse la finalización debe evitarse. En este caso la situación se ve agravada porque se frena la adición de nueva funcionalidad en el código que está siendo refactorizado durante un tiempo indeterminado.
Hay varias medidas que pueden adoptarse para evitar caer en la espeial refactorizadora. La primera de ellas es declarar el objetivo de una refactorización antes de empezar. Si durante la misma aparece nuevo código susceptible de ser refactorizado debe dejarse sin modificar, por ahora sólo apuntaremos esta necesidad para no olvidarnos de hacer la refactorización más adelante. Cuando se considere más oportuno.
Otra práctica muy útil consiste en introducir el código en el sistema de control de versiones antes de emprender cualquier refactorización que podamos considerar grande.
Si cuando se está llevando a cabo una refactorización se dispersan los objetivos iniciales, se llevan muchas horas o incluso días sin tener un código que funciona o resulta imposible estimar cuanto queda para terminar es necesario asumir que la refactorización no va por buen camino. Para volver a la normalidad se debe devolver el código a un estado en el funcionara correctamente. Esto resulta muy fácil si se siguió el consejo anterior de comenzar con código guardado en el sistema de control de versiones. No deben tenerse reparos en tirar las modificaciones empezadas, estaremos cambiando un poco de tiempo de trabajo por recuperar una situación estable que nos permite seguir avanzando sin incertidumbres. Lo más importante será lo aprendido de la refactorización fallida, que nos será muy valioso para volver a intentarlo.
La mejor forma de enfocar correctamente una refactorización y evitar caer en espirales
de refactorizaciones, es conocer muy bien los patrones de diseño. Los patrones de diseño no son sino soluciones que funcionan para problemas comunes que todos encontramos cuando estamos desarrollando. Conocer perfectamente los patrones de diseño nos permite identificar y ver con claridad el objetivo de la refactorización, mejora la comunicación entre los miembros del grupo al compartir una base de conocimiento muy importante y además nos hace más eficientes en la resolución no sólo de problemas conocidos, sino también de problemas desconocidos al haber adquirido una forma mejor arquitecturada de enfocar los problemas.
Refactorización y pruebas unitarias
La existencia de pruebas automatizadas facilita enormemente las refactorizaciones. Los principales motivos son:
•El riesgo de la refactorización disminuye, dado que es posible comprobar cuando esta concluye que todo sigue funcionando satisfactoriamente.
•El desarrollador que realiza la refactorización puede comprobar que no ha estropeado la funcionalidad implementada por otros. Evita efectos colaterales.
•El tiempo necesario para comprobar que todo sigue funcionando es menor lo que permite avanzar en pasos más pequeños si se desea.
•Refactorizar sin tests es una actividad de alto riesgo y no debe hacerse salvo para las refactorizaciones más sencillas y realizadas con herramientas especializadas. En ocasiones incluso algunas refactorizaciones muy pequeñas pueden provocar la aparición de bugs muy difíciles de identificar a posteriori.
Sin embargo las pruebas también pueden llegar a ser un estorbo a la refactorización si se emplean de forma inadecuada.
En este sentido es muy importante resaltar la importancia de que las pruebas tanto funcionales como unitarias comprueben que el código bajo prueba funcione correctamente independientemente de cómo esté implementado. Cuanto mayor sea el acoplamiento de la prueba con la implementación, mayores serán los cambios que habrá que realizar en esta cuando se lleve a cabo.
Pero incluso aunque no exista este acoplamiento las refactorizaciones grandes, que afectan al diseño del código significativamente, obligarán a realizar cambios en las pruebas. Esto provoca una situación incómoda, las pruebas que deben ser una ayuda se convierten en este caso en un estorbo a la refactorización. La mejor solución es prevenir aplicando refactorizaciones continuas y más pequeñas. Pero una vez nos encontramos con esta situación, es recomendable cambiar las pruebas antes o a la vez que el código. De esta forma las pruebas colaborarán guiando la refactorización.
En este sentido también resulta útil pensar antes de refactorizar en cómo van a afectar a los tests y cómo podemos usarlos en nuestro beneficio en vez de dejar que se conviertan en un problema.

Conclusiones
El problema de abordar una refactorización es que supone un esfuerzo que no se ve compensado por ninguna nueva funcionalidad y por ese motivo muchas veces es complicado de justificar. Sin embargo si introducimos la refactorización como parte del desarrollo conseguiremos que nuestro código sea de calidad y la experiencia dice que
este tiempo que vamos empleando a lo largo del desarrollo será recuperado con creces según el proyecto avance.
Se puede afirmar que refactorizar nos facilita enormemente el mantenimiento de un código siempre correctamente estructurado. El hecho de que el código esté bien estructurado es una ventaja por su mantenibilidad y extensibilidad. Sin embargo, esta técnica que parece tan ventajosa, requiere de su aplicación continua, el empleo de pruebas que proporcionen seguridad a su aplicación un buen conocimiento de los patrones de diseño que van a permitir al desarrollador saber hacia donde camina y por último importantes dosis de comunicación con todos los miembros del equipo.

Referencias
[Fowler] Martin Fowler: Refactoring: Improving the Design of Existing Code. Addison-Wesley Co.[1999] http://www.refactoring.com
[Wiki] Páginas Wiki sobre Refactorización
http://c2.com/ppr/wiki/WikiPagesAboutRefactoring
[IntelliJ] Uno de los mejores Entorno de Desarrollo Java para Refactorizar
http://www.intellij.com
[Refactoring] Página de Refactorización en Español.
http://refactoring.blog-city.com
[PerezFerrerColado58] Jesús Pérez, Jorge Ferrer, César Colado. “Introducción a la refactorización”, Mundo Linux nº 58. Revistas Profesionales.
[PerezFerrerColado60] Jesús Pérez, Jorge Ferrer, César Colado. “Refactorización en la práctica”, Mundo Linux nº 60 (pendiente de publicación). Revistas Profesionales.

Berly v/s Aero

Para los Fans de lo GNU/Linux, observen esto,

Como dice el video, para que quieres windows si tienes GNU/Linux??, lo quieres??, aqui esta, bajalo, pero comprueba tu version de linux

Proyecto Berly

Cambiar colores del MenuStrip y otros controles de windows

Hola, o hi en inglish, mostrare un ejemplo de como cambiar el color de los menuStrip en VB.NET, ustedes haran la conversion a otros lenguajes, recuerden que esto se puede hacer en cualquier lenguaje aderido a la CLS (Common Languege Specification), no se si lo escribi bien, pero es la Especificacion comun del lenguaje, esto hace que todos los lenguajes de .net tengan soporte para las mismas librerias y “casi”, se logren los mismos resultados con cualesquiera lenguaje que se trabaje, siempre y cuando esten bajo la plataforma .NET.

Bien a lo que nos convoca:

1) Paso 1; Deberemos crear una clase de nombre (lo que quieran es su programa) Colores, como? asi:

Public Class Colores

End Class

2) Paso 2; Ahora heredaremos la clase que trae .NET llamada “ProfessionalColorTable”, asi;

Public Class Colores

Inherits ProfessionalColorTable

End Class

3) Paso 3; Sobreescribiremos las propiedades que contiene la clase (o como dice .NET “Overrides”) y que establecen el color o los colores de los controles, se preguntaran y que a controles les puedes cambiar el color??, mas adelante, ahora sigamos;

Public Class Colores

Inherits ProfessionalColorTable

Public Overrides ReadOnly Property ButtonCheckedGradientBegin() As System.Drawing.Color

Get
Return Color.AliceBlue

End Get

End Property

End Class

Como veran la propiedad ButtonCheckedGradientBegin es sobrescrivida, y es establecida a un color pasado en return, al momento de escribir property, veran como la super duper ayuda de MICROSOFT VISUAL STUDIO .NET 2005, o la version que tengan, les mostrara la lista completa que las propiedades que pueden modificar a su gusto, pero?? y cual corresponde a que parte del control??, esto talvez les ayudara:

Nombre Descripción
Propiedad pública ButtonCheckedGradientBegin Obtiene el color de inicio del degradado utilizado cuando se activa el botón.
Propiedad pública ButtonCheckedGradientEnd Obtiene el color final del degradado utilizado cuando se activa el botón.
Propiedad pública ButtonCheckedGradientMiddle Obtiene el color medio del degradado utilizado cuando se activa el botón.
Propiedad pública ButtonCheckedHighlight Obtiene el color sólido utilizado cuando se activa el botón.
Propiedad pública ButtonCheckedHighlightBorder Obtiene el color de borde que se va a utilizar con ButtonCheckedHighlight.
Propiedad pública ButtonPressedBorder Obtiene el color de borde que se va a utilizar con los colores ButtonPressedGradientBegin, ButtonPressedGradientMiddle y ButtonPressedGradientEnd.
Propiedad pública ButtonPressedGradientBegin Obtiene el color de inicio del degradado utilizado cuando se presiona el botón.
Propiedad pública ButtonPressedGradientEnd Obtiene el color final del degradado utilizado cuando se presiona el botón.
Propiedad pública ButtonPressedGradientMiddle Obtiene el color medio del degradado utilizado cuando se presiona el botón.
Propiedad pública ButtonPressedHighlight Obtiene el color sólido utilizado cuando se presiona el botón.
Propiedad pública ButtonPressedHighlightBorder Obtiene el color de borde que se va a utilizar con ButtonPressedHighlight.
Propiedad pública ButtonSelectedBorder Obtiene el color de borde que se va a utilizar con los colores ButtonSelectedGradientBegin, ButtonSelectedGradientMiddle y ButtonSelectedGradientEnd.
Propiedad pública ButtonSelectedGradientBegin Obtiene el color de inicio del degradado utilizado cuando se selecciona el botón.
Propiedad pública ButtonSelectedGradientEnd Obtiene el color final del degradado utilizado cuando se selecciona el botón.
Propiedad pública ButtonSelectedGradientMiddle Obtiene el color medio del degradado utilizado cuando se selecciona el botón.
Propiedad pública ButtonSelectedHighlight Obtiene el color sólido utilizado cuando se selecciona el botón.
Propiedad pública ButtonSelectedHighlightBorder Obtiene el color de borde que se va a utilizar con ButtonSelectedHighlight.
Propiedad pública CheckBackground Obtiene el color sólido que se utilizará cuando se active el botón y se utilicen los degradados.
Propiedad pública CheckPressedBackground Obtiene el color sólido que se utilizará cuando se active y seleccione el botón y se utilicen los degradados.
Propiedad pública CheckSelectedBackground Obtiene el color sólido que se utilizará cuando se active y seleccione el botón y se utilicen los degradados.
Propiedad pública GripDark Obtiene el color que se va a utilizar para los efectos de sombra del control (controlador de movimiento).
Propiedad pública GripLight Obtiene el color que se va a utilizar para los efectos de resaltado del control (controlador de movimiento).
Propiedad pública ImageMarginGradientBegin Obtiene el color de inicio del degradado utilizado en el margen de la imagen de un ToolStripDropDownMenu.
Propiedad pública ImageMarginGradientEnd Obtiene el color final del degradado utilizado en el margen de la imagen de un ToolStripDropDownMenu.
Propiedad pública ImageMarginGradientMiddle Obtiene el color medio del degradado utilizado en el margen de la imagen de un ToolStripDropDownMenu.
Propiedad pública ImageMarginRevealedGradientBegin Obtiene el color de inicio del degradado utilizado en el margen de la imagen de un ToolStripDropDownMenu cuando se revela un elemento.
Propiedad pública ImageMarginRevealedGradientEnd Obtiene el color final del degradado utilizado en el margen de la imagen de un ToolStripDropDownMenu cuando se revela un elemento.
Propiedad pública ImageMarginRevealedGradientMiddle Obtiene el color medio del degradado utilizado en el margen de la imagen de un ToolStripDropDownMenu cuando se revela un elemento.
Propiedad pública MenuBorder Obtiene el color que es el color de borde que se va a utilizar en MenuStrip.
Propiedad pública MenuItemBorder Obtiene el color de borde que se va a utilizar con ToolStripMenuItem.
Propiedad pública MenuItemPressedGradientBegin Obtiene el color de inicio del degradado utilizado cuando se presiona un ToolStripMenuItem de nivel superior.
Propiedad pública MenuItemPressedGradientEnd Obtiene el color final del degradado utilizado cuando se presiona un ToolStripMenuItem de nivel superior.
Propiedad pública MenuItemPressedGradientMiddle Obtiene el color medio del degradado utilizado cuando se presiona un ToolStripMenuItem de nivel superior.
Propiedad pública MenuItemSelected Obtiene el color sólido que se va a utilizar cuando se seleccione un ToolStripMenuItem distinto del ToolStripMenuItem de nivel superior.
Propiedad pública MenuItemSelectedGradientBegin Obtiene el color de inicio del degradado utilizado cuando se selecciona el ToolStripMenuItem.
Propiedad pública MenuItemSelectedGradientEnd Obtiene el color final del degradado utilizado cuando se selecciona el ToolStripMenuItem.
Propiedad pública MenuStripGradientBegin Obtiene el color de inicio del degradado utilizado en el control MenuStrip.
Propiedad pública MenuStripGradientEnd Obtiene el color final del degradado utilizado en el control MenuStrip.
Propiedad pública OverflowButtonGradientBegin Obtiene el color de inicio del degradado utilizado en el control ToolStripOverflowButton.
Propiedad pública OverflowButtonGradientEnd Obtiene el color final del degradado utilizado en el control ToolStripOverflowButton.
Propiedad pública OverflowButtonGradientMiddle Obtiene el color medio del degradado utilizado en el control ToolStripOverflowButton.
Propiedad pública RaftingContainerGradientBegin Obtiene el color de inicio del degradado utilizado en el control ToolStripContainer.
Propiedad pública RaftingContainerGradientEnd Obtiene el color final del degradado utilizado en el control ToolStripContainer.
Propiedad pública SeparatorDark Obtiene el color que se va a utilizar para los efectos de sombra en el ToolStripSeparator.
Propiedad pública SeparatorLight Obtiene el color que se va a utilizar para los efectos de resaltado en el ToolStripSeparator.
Propiedad pública StatusStripGradientBegin Obtiene el color de inicio del degradado utilizado en el control StatusStrip.
Propiedad pública StatusStripGradientEnd Obtiene el color final del degradado utilizado en el control StatusStrip.
Propiedad pública ToolStripBorder Obtiene el color de borde que se va a utilizar en el borde inferior de ToolStrip.
Propiedad pública ToolStripContentPanelGradientBegin Obtiene el color de inicio del degradado utilizado en el control ToolStripContentPanel.
Propiedad pública ToolStripContentPanelGradientEnd Obtiene el color final del degradado utilizado en el control ToolStripContentPanel.
Propiedad pública ToolStripDropDownBackground Obtiene el color de fondo sólido del ToolStripDropDown.
Propiedad pública ToolStripGradientBegin Obtiene el color de inicio del degradado utilizado en el fondo de ToolStrip.
Propiedad pública ToolStripGradientEnd Obtiene el color final del degradado utilizado en el fondo de ToolStrip.
Propiedad pública ToolStripGradientMiddle Obtiene el color medio del degradado utilizado en el fondo de ToolStrip.
Propiedad pública ToolStripPanelGradientBegin Obtiene el color de inicio del degradado utilizado en el control ToolStripPanel.
Propiedad pública ToolStripPanelGradientEnd Obtiene el color final del degradado utilizado en el control ToolStripPanel.
Propiedad pública UseSystemColors Obtiene o establece un valor que indica si utilizar SystemColors en lugar de colores que coincidan con el estilo visual actual.

por otro lado, y como les dije esta clase de framework .net, le proporciona los colores utilizados para los elementos de visualización de Microsoft Office, y como usar la clase que hemos hecho??, bien miren:

4) Paso y (y ultimo): para usar la clase con las definiciones de colores que esten dispuestos a cambar (los colores que no definan, se usara los que esten establecidos por defecto en la case “ProfessionalColorTable”, no piensen que quedan en color blanco), para usarlo, usaremos un ejemplo bien practico, en el evento load de un formulario y supuniendo que tenemos un menu llamado “main_menu”, miren, asi;

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
main_menu.Renderer = New ToolStripProfessionalRenderer(New Colores)
End Sub

Como veran se crea una nueva instancia de la clase Colores la quien heredo de la clase “ProfessionalColorTable”, instancia la cual fue pasada como parametro al constructor de la case “ToolStripProfessionalRenderer” y el resultado de esto se paso a la propiedad renderer del objeto main_menu, el cual es una propiedad de tipo ToolStripRenderer, la cual es clase base abstracta de las anteriores, como ven calza todo, :), espero que les sirva, pues cuando quise hacer esto, no enconstraba informacion de esto, pero como buen chileno, busco en todas partes menos donde se debe si tiene el MSDN Visual Studio .NET miren esto

ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.es/dv_fxmclictl/html/94e7d7bd-a752-441c-b5b3-7acf98881163.htm

Ejecuntenlo desde menu->ejecutar y hasta la proxima, chao ;)

Escrito en VB.NET. 1 comentario

Mi Primer Post

Hola a todos, aqui comienza mi vida en internet, mi primer post, espero que le sea de ayuda, la informacion que aqui, tratare de dar a conocer al mundo, gracias a todos por sus visitas, y no olviden de dejar sus comentarios..