lunes, 29 de noviembre de 2010

Contro de codigo fuente

obtenido de aqui






¿Tienes más de 2 personas trabajando en un mismo proyecto? ¿Los programadores machacan su código fuente? ¿Quieres llevar un control de versiones de tu software? Necesitas tener bajo control tu código fuente.
Al principio no hay problemas, tú desarrollas solo, tienes todos los ficheros fuente. Añades, editas, borras ficheros fuente conforme te parece y vas necesitando. Esto funciona bien si el proyecto es pequeño y no tienes necesidad de más programadores.
Pero un día llega el momento en que el proyecto es un poco más grande y están trabajando simultáneamente con los ficheros fuentes 2 o 3 personas, y lo que antes era tan sencillo como editar un fichero fuente se convierte en una pesadilla.
Lo primero que se te ocurre es compartir un directorio en el que todo el mundo puede crear, editar y borrar ficheros a su parecer. A los 10 minutos te das cuenta que eso no funciona, lo más normal es que dos programadores estén editando el mismo fichero fuente y uno de los dos machaque el trabajo del otro, con el consiguiente enfado del perjudicado. Y más vale que esto no ocurra más de una vez porque si no el posible pequeño enfado se puede convertir en represalia y ya te puedes imaginar las consecuencias que esto tiene.
  
Así que en un alarde de imaginación organizativa decides que cada uno trabaje en su parte, que las partes sean distintas, de forma que nadie necesite editar ficheros que otro esté editando (sniff...) y que si alguien va a editar algún fichero "general" que avise a los demás para que no lo editen al mismo tiempo. No hace falta pensar mucho para darse cuenta que al rato esto nos lleva a la situación del principio, machacándose unos ficheros a los otros.
Primero porque la separación en partes disjuntas no está clara y sobre todo porque cuando tienes que avisar a los demás de que vas a editar un fichero común, a veces se te olvida y no lo haces, o piensas que sólo lo abres para verlo y no vas a tocar nada, pero que luego resulta que si modificas.
Así que si tienes más de un programador necesitas que alguien controle el acceso a los fuentes para evitar estos problemas.
Afortunadamente existen herramientas que permiten realizar este control sobre los ficheros fuente. Estas herramientas evitan que nadie machaque código de otro inconscientemente, también permiten saber qué modificó cada programador, guardar versiones anteriores que se pueden recuperar posteriormente, etiquetar conjuntos de ficheros fuente bajo un mismo nombre.
Voy a presentaros algunas opciones para que podáis elegir la que más se ajuste a vuestras necesidades.
  • RCS. Revision Control System. Uno de los más antiguos (1980) y también de los más sencillos de usar. Desarrollado para entornos UNIX aunque también está portado a Windows. Recomendado para proyectos no muy complejos en entorno UNIX bajo la misma máquina.
    Página oficial y descarga gratuita: http://www.gnu.org/software/rcs/rcs.html
  • MS Visual SourceSafe. La alternativa Microsoft. Se integra muy bien, como sería de esperar, con las herramientas de desarrollo de Microsoft. Si tu entorno de desarrollo es Microsoft, esta es tu primera opción. Es viejo, feo (estilo W95) y mil veces parcheado, pero es lo que hay. Funciona decentemente bien y no da muchos problemas.
    Página oficial: http://msdn.microsoft.com/ssafe/default.asp
  • CVS. Concurrent Versions System. Posiblemente sea uno de los mejores. Además de hacer lo que los anteriores también puede funcionar como cliente/servidor a través de Internet, puede manejar distintas ramas y realizar mezclas de ellas cuando sea necesario, y otras muchas cosas. Si bien los clientes pueden correr en muchos sistemas operativos de la familia UNIX y de la familia Windows, el servidor ha de estar en un sistema de la familia UNIX. Existen versiones que corren bajo Windows pero recomiendan no usarlas en entornos de producción. Añadir que por su buena integración en Internet, es una de las herramientas más usadas en el desarrollo de proyectos geográficamente distribuidos como puede ser los proyectos de software libre.
    Página oficial y descarga gratuita: http://www.cvshome.org/
  • IBM Rational ClearCase. El caro. Con estos dos padres IBM y Racional, que más podemos decir. No lo he usado en entornos productivos, pero he estado trasteando con la versión de evaluación y la verdad es que parece muy bueno. Con las capacidades de CVS y además un entorno gráfico amigable. Se integra bien con las herramientas de Microsoft aunque no tan bien como SourceSafe.
    Página oficial: http://www.rational.com/products/clearcase/prodinfo.jsp
Así que ya sabes, si tienes un equipo de trabajo necesitas que tus ficheros fuente estén bajo control. Elige el que más se ajuste a tus necesidades y muchos de tus problemas con la gestión del código fuente desaparecerán.
Asegúrate que tu herramienta de desarrollo se integra bien con tu gestor de código fuente y todo el mundo será feliz. Si no, los desarrolladores se van a quejar y eso significa que no lo usaran y entonces volverás a estar como al principio.

Patrones de diseño mas comunes

obtenido de aqui 




Patrones de diseño o más comúnmente conocidos como "Design Patterns". ¿Qué son los patrones de diseño? Son soluciones simples y elegantes a problemas específicos y comunes del diseño orientado a objetos. Son soluciones basadas en la experiencia y que se ha demostrado que funcionan.
Es evidente que a lo largo de multitud de diseños de aplicaciones hay problemas que se repiten o que son análogos, es decir, que responden a un cierto patrón. Sería deseable tener una colección de dichos patrones con las soluciones más óptimas para cada caso. En este artículo presentamos una lista con los más comunes y conocidos.
Los patrones de diseño no son fáciles de entender, pero una vez entendido su funcionamiento, los diseños serán mucho más flexibles, modulares y reutilizables. Han revolucionado el diseño orientado a objetos y todo buen arquitecto de software debería conocerlos.
A continuación una lista con los patrones de diseño a objetos más habituales publicados en el libro "Design Patterns", escrito por los que comúnmente se conoce como GoF (gang of four, "pandilla de los cuatro").

Patrones de creación
  • Abstract Factory. Proporciona una interfaz para crear familias de objetos o que dependen entre sí, sin especificar sus clases concretas.
  • Builder. Separa la construcción de un objeto complejo de su representación, de forma que el mismo proceso de construcción pueda crear diferentes representaciones.
  • Factory Method. Define una interfaz para crear un objeto, pero deja que sean las subclases quienes decidan qué clase instanciar. Permite que una clase delegue en sus subclases la creación de objetos.
  • Prototype. Especifica los tipos de objetos a crear por medio de una instancia prototípica, y crear nuevos objetos copiando este prototipo.
  • Singleton. Garantiza que una clase sólo tenga una instancia, y proporciona un punto de acceso global a ella.

Patrones estructurales
  • Adapter. Convierte la interfaz de una clase en otra distinta que es la que esperan los clientes. Permiten que cooperen clases que de otra manera no podrían por tener interfaces incompatibles.
  • Bridge. Desvincula una abstracción de su implementación, de manera que ambas puedan variar de forma independiente.
  • Composite. Combina objetos en estructuras de árbol para representar jerarquías de parte-todo. Permite que los clientes traten de manera uniforme a los objetos individuales y a los compuestos.
  • Decorator. Añade dinámicamente nuevas responsabilidades a un objeto, proporcionando una alternativa flexible a la herencia para extender la funcionalidad.
  • Facade. Proporciona una interfaz unificada para un conjunto de interfaces de un subsistema. Define una interfaz de alto nivel que hace que el subsistema se más fácil de usar.
  • Flyweight. Usa el compartimiento para permitir un gran número de objetos de grano fino de forma eficiente.
  • Proxy. Proporciona un sustituto o representante de otro objeto para controlar el acceso a éste.

Patrones de comportamiento
  • Chain of Responsibility. Evita acoplar el emisor de una petición a su receptor, al dar a más de un objeto la posibilidad de responder a la petición. Crea una cadena con los objetos receptores y pasa la petición a través de la cadena hasta que esta sea tratada por algún objeto.
  • Command. Encapsula una petición en un objeto, permitiendo así parametrizar a los clientes con distintas peticiones, encolar o llevar un registro de las peticiones y poder deshacer la operaciones.
  • Interpreter. Dado un lenguaje, define una representación de su gramática junto con un intérprete que usa dicha representación para interpretar las sentencias del lenguaje.
  • Iterator. Proporciona un modo de acceder secuencialmente a los elementos de un objeto agregado sin exponer su representación interna.
  • Mediator. Define un objeto que encapsula cómo interactúan un conjunto de objetos. Promueve un bajo acoplamiento al evitar que los objetos se refieran unos a otros explícitamente, y permite variar la interacción entre ellos de forma independiente.
  • Memento. Representa y externaliza el estado interno de un objeto sin violar la encapsulación, de forma que éste puede volver a dicho estado más tarde.
  • Observer. Define una dependencia de uno-a-muchos entre objetos, de forma que cuando un objeto cambia de estado se notifica y actualizan automáticamente todos los objetos.
  • State. Permite que un objeto modifique su comportamiento cada vez que cambia su estado interno. Parecerá que cambia la clase del objeto.
  • Strategy. Define una familia de algoritmos, encapsula uno de ellos y los hace intercambiables. Permite que un algoritmo varíe independientemente de los clientes que lo usan.
  • Template Method. Define en una operación el esqueleto de un algoritmo, delegando en las subclases algunos de sus pasos. Permite que las subclases redefinan ciertos pasos del algoritmo sin cambiar su estructura.
  • Visitor. Representa una operación sobre los elementos de una estructura de objetos. Permite definir una nueva operación sin cambiar las clases de los elementos sobre los que opera.

el codigo apesta por que se corrompio el diseño del software

obtenido de aqui


¿Qué le pasa al software? El diseño de muchas aplicaciones comienza con una imagen clara en la mente del diseñador. En este estado el diseño es claro, conciso y elegante. Diseñadores y programadores desean verlo funcionar. Algunos de estos proyectos mantienen esta pureza de diseño hasta la primera versión.
Pero algo comienza a pasar. Al principio apenas es perceptible. Un parche por aquí, una ñapa por allá, aunque el diseño todavía mantiene la filosofía inicial. El software comienza a pudrirse. Las ñapas continúan y poco a poco el software se corrompe mas y mas hasta llegar un punto en el que afecta a toda la aplicación. El programa se convierte en una ingente masa de código que cada vez es más difícil de mantener. Entonces el esfuerzo requerido para hacer el más simple de los cambios es tal que los responsables de producto se plantean hacer un rediseño de la aplicación.
Los rediseños normalmente no fructifican. Aunque las intenciones de los diseñadores son buenas se dan cuenta de que es una tarea imposible. El sistema continua evolucionando, cambiando y el nuevo rediseño nunca termina. Un día la cantidad de problemas vuelve a ser tal que se los diseñadores lloran por otro rediseño.

Síntomas de un mal diseño

Hay cuatro indicios principales que nos indican que el software se esta pudriendo. No son independientes y están relacionados unos con otros, son: rigidez, fragilidad, inmovilidad y viscosidad.
Rigidez. Es la tendencia del software a ser difícil de cambiar, incluso en las cosas más sencillas. Cada cambio produce una cascada de cambios en módulos dependientes. Lo que parecía un cambio de dos días en un módulo resulta ser varias semanas de cambios de módulos tirando del hilo a través de la aplicación.
Cuando el software toma este camino, los gestores temen decir a los programadores que arreglen pequeños problemas que no son críticos. Esto ocurre porque ellos no saben con seguridad cuando acabaran los programadores. Todo el mundo hace "check-in" y nadie hace "check-out".
El miedo del gestor puede llegar a ser tan agudo que se niegue a realizar modificaciones en la aplicación. De manera que, lo que empezó siendo un diseño ineficiente acaba siendo una mala política de gestión.
 Fragilidad. Muy relacionada con la rigidez está la fragilidad. La fragilidad es la tendencia que tiene el software a romperse por muchos sitios cada vez que se cambia algo. Muchas de las roturas ocurren en sitios que no están relacionados conceptualmente con el área que se está cambiando. Cada vez que los gestores autorizan un cambio tienen miedo de que el programa se rompa por algún lugar inesperado.
Conforme la fragilidad empeora, la probabilidad de que el software se rompa incrementa con el tiempo, acercándose cada vez más a 1. Este software es imposible de mantener. Cada arreglo lo hace peor, introduciendo más problemas de los que son solucionados.
Este software causa que los gestores y los clientes tengan la impresión de que los desarrolladores han perdido el control del software, perdiéndose así la credibilidad de los desarrolladores. Y frases como "Rompes más de lo que arreglas", comienzan a ser habituales.
Inmovilidad. La inmovilidad es la resistencia del software a ser reutilizado en otros proyectos o parte de otros proyectos. Pasa muchas veces que un programador descubre que necesita un módulo que es muy parecido a otro que ha desarrollado otro programador. Sin embargo, también pasa muchas veces que el módulo en cuestión depende demasiado de la aplicación en la que está integrado. Después de mucho trabajo los desarrolladores descubren que el trabajo necesario para separar las partes reutilizables de las partes no reutilizables es demasiado alto. Y entonces el software simplemente se rescribe en vez de ser reutilizado.
Viscosidad. La viscosidad de diseño es la dificultad de mantener la filosofía del diseño original. Cuando se afronta un cambio los programadores encuentran normalmente más de una manera de realizarlo. Algunas de estas formas preservan la filosofía del diseño y otras no. Cuando las formas de implementar el cambio preservando el diseño son más difíciles de realizar que las que no lo preservan, entonces la viscosidad del diseño es alta. Es fácil hacerlo mal y difícil hacerlo bien.
Estos cuatro síntomas son reveladores de un diseño de arquitectura pobre. Cualquier aplicación que muestra estos síntomas adolece de un diseño pobre.

¿Qué causa que el diseño se deteriore?

Requisitos cambiantes

La causa de la degradación del diseño es muy conocida. Los requisitos han ido cambiando de manera que no estaba previsto en el diseño inicial. A menudo los cambios necesitan hacerse rápidamente y hechos por programadores que no están familiarizados con el diseño original. Entonces, aunque los cambios funciona, violan el diseño original. Poco a poco los cambios continúan y las violaciones se acumulan hasta que el diseño se rompe.
Aún así no podemos echar la culpa a que los requisitos cambian y cruzarnos de brazos. Como desarrolladores, todos sabemos que los requisitos van a cambiar. Así que debemos realizar un diseño que soporte modificaciones sin que este pierda su consistencia.

Control de dependencias

¿Qué tipos de cambios hacen que un diseño se pudra? Los cambios que introducen nuevas e imprevistas dependencias. Cada una de las cuatro causas mencionadas anteriormente están relacionadas directa o indirectamente con dependencias entre módulos del software. Son las dependencias de la arquitectura lo que se degrada y con ellas el mantenimiento del software.
Para anticiparse a la degradación de las dependencias del diseño de la arquitectura, deben ser controladas las dependencias entre módulos de una aplicación. Este control consiste en la creación de "cortafuegos" de dependencias. A través de estos cortafuegos las dependencias no se propagan.
El diseño orientado a objetos esta repleto de principios y técnicas que nos permiten construir estos cortafuegos y controlar estas dependencias.