Git, PHP and C, with great power comes a great responsibility

Ver este artículo en castellano aquí

A few days ago I had the opportunity to share a conversation about version control systems with some colleagues, specifically about git, its complexity and the recommendation or not use them. A strong argument against said that git was a complex tool, which had a higher learning curve than others, that was very easy to make mistakes and that this mistake could mean a loss of data.

This made me think, and while it is true that git is a very powerful tool (with which I have a love-hate relationship for several years), the fact that a tool or language you allow certain liberties, does not imply that they are intended to be used always. Here is an example in this question of Stack Overflow:

http://stackoverflow.com/questions/1488753/how-to-merge-two-branches-without-a-common-ancestor

A -- B -- ... -- K -- L -- M1
                             \
                              M3 -- N' -- .. -- Z'
                             /
               I1 -- I2 -- M2 -- N -- .. -- Z

In this case we have 2 different branches without a common parent, which is a somewhat unusual case according to my (short) experience. Is it bad git for allowing this operation? No, should use an usual branching pattern? Either. In fact the majority of branches management patterns are based on having a /main branch as solid as possible, and have features, users or tasks into separate branches.

Another command that we have is rebase which allows us to rewrite the history of a branch, and integrate their changes in another branch, which may seem a genuine outrage for those who consider that a changeset is a permanent snapshot.

Git is not the only, since we have other tools and programming languages, that by design have allowed us to do certain things that have been heavily over-used:

PHP

The language that is the base of sites like Facebook, Yahoo, and Youtube has not been without controversy in the 18 years that has been on duty (since 1995). Looking for peculiarities of the language, I discovered that, among other things, PHP allows us to define globals from within a function as shown in the following code block:

function foo () {
    global $var;
    // rest of code
}

This breaks all the encapsulation and variable scope rules, that are studied on a standard programming course, and certainly its use has been harshly criticized, Is PHP a bad language by implementing this functionality? No, it is possible to find a specific scenario for this functionality, and then use the features provided by the language

C

The father, grandfather, and common ancestor of many of today’s programming languages and whose main book contains less than 300 pages (the famous K & R), has been receiving criticism since 1972. One of the most criticized features is, without doubt, the *goto** statement:

int big_function()
{
    int ret_val = [success];
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    return ret_val;
}

GoTo allows us to perform an unconditional jump to a portion of the file. To goto detractors state that breaks the flow of execution of a program and that can be a source of errors and hinders readability. On the other hand, it is useful in side scenarios, such as the Elimination of recursion.

Recap

In the same way that we should not use the same tool for all (golden hammer anti-pattern) we must be aware of the peculiarities of the language, and that what it gives us, it provides with a specific reason, not necessarily applicable to all scenarios.

Remember Uncle Ben when using one of these tools and languages:

Uncle ben

With great power comes a great responsibility

More information and interesting articles

And you, what curious things have you spotted in your favourite programming language or tool?

Git, PHP y C: Un gran poder conlleva una gran responsabilidad

Read this article in English here

Hace unos días tuve la ocasión de compartir con algunos compañeros una conversación sobre controles de versiones, concretamente sobre git, su complejidad y la recomendación o no de su uso. Un argumento de peso en contra decía que git era una herramienta compleja, que tenía una curva de aprendizaje mayor que otras, que era muy sencillo equivocarte y que esa equivocación podría implicar una pérdida de datos.

Esto me hizo pensar, y si bien es cierto que git es una herramienta muy poderosa (con la que he tengo una relación de amor-odio desde hace varios años), el hecho de que una herramienta o lenguaje te permita ciertas libertades, no implica que estén pensadas para ser usadas siempre. Veamos un ejemplo en esta pregunta de Stack Overflow:

http://stackoverflow.com/questions/1488753/how-to-merge-two-branches-without-a-common-ancestor

A -- B -- ... -- K -- L -- M1
                             \
                              M3 -- N' -- .. -- Z'
                             /
               I1 -- I2 -- M2 -- N -- .. -- Z

En este caso son 2 ramas sin padre común, lo cual es un caso un tanto atípico según mi (corta) experiencia. Es malo git por permitir esta operación? No, debemos usarlo como patrón de ramas habitual? Tampoco. De hecho la mayoría de patrones de gestión de ramas se basan en tener una rama /main lo más sólida posible, y tener las características, usuarios o tareas en ramas separadas.

Otro comando con el que contamos es rebase que nos permite reescribir la historia de una rama, e integrar los cambios de otra, lo cual puede parecer una auténtica atrocidad para aquellos que consideren que un changeset es una foto inamovible.

Git no es el único, ya que tenemos otras herramientas y lenguajes de programación, que por diseño nos han permitido hacer ciertas cosas que se han ido de las manos:

PHP

El lenguaje que permite que sitios como Facebook, Yahoo, o Youtube no ha estado exento de polémica en los 18 años que lleva prestando servicio (desde nada más y nada menos que 1995). Buscando peculiaridades del lenguaje, descubrí que, entre otras cosas, PHP nos permite definir variables globales desde dentro de una función como muestra el siguiente bloque de código:

function foo () {
    global $var;
    // rest of code
}

Esto rompe con todas las reglas de encapsulación, y de alcance de las variables de una función que se estudian habitualmente, y desde luego, está duramente criticado su uso, Es PHP un mal lenguaje por implementar esta funcionalidad? No, es posible que encontremos un caso de uso específico para esta funcionalidad, y de ahí que el lenguaje nos de el soporte para la misma.

C

El padre, abuelo y antepasado común de muchos de los lenguajes de programación de hoy en día, y cuyo libro de cabecera contiene poco menos de 300 páginas (El famoso K & R), lleva recibiendo críticas desde 1972. Una de las funcionalidades más criticadas es, sin duda, la función goto:

int big_function()
{
    int ret_val = [success];
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    return ret_val;
}

Goto nos permite realizar un salto incondicional a una porción del fichero. Los detractores a goto opinan que rompe el flujo de ejecución de un programa y que puede ser una fuente de errores, además de que dificulta la legibilidad. Por otra parte, es útil en escenarios secundarios, como la eliminación de la recursividad.

Conclusiones

De igual manera que no debemos usar la misma herramienta para todo (antipatrón del martillo) debemos ser conscientes de las peculiaridades de los lenguajes, y en que lo que se nos aporta, se aporta con una razón en concreto, no necesariamente para aplicarlo a todos los escenarios.

Recordemos al Tío Ben cuando estemos desarrollando o usando una herramienta:

tio ben

Un gran poder conlleva una gran responsabilidad

Y tú, qué peculiaridades de estos (u otros) lenguajes te parece que han sufrido abuso por parte de los desarrolladores?

Más información y artículos interesantes

Merges un poco más inteligentes para C#

Las operaciones de merge son muy comunes en los sistemas de control de versiones distribuidos, y si hay muchos cambios a nivel de pocos ficheros (equipos trabajando en una misma funcionalidad) podemos tener muchos conflictos. Para ayudar a mejorar la productividad en estas operaciones ayer hemos anunciado la disponibilidad a todo el público de la beta de SemanticMerge.

La idea es simplificar la resolución del conflicto entendiendo el código, resolviendo de manera automática aquellos en los que sea posible y permitir al usuario, de manera sencilla, encargarse de los conflictos restantes. En este artículo veremos de un vistazo la herramienta sus características, los casos que cubrimos y cómo la hemos desarrollado.

Una interfaz sencilla

La herramienta, formada básicamente por un panel donde se muestran los conflictos y diferencias, y un visor de código, permite por una parte resolver conflictos, y por otra ver en detalle los cambios sucedidos en cada fichero respecto a la base.

Para ayudar al usuario, cada conflicto tiene, en la cabecera, un campo identificado por una letra y un color por cada cambio que lleven al conflicto, en el ejemplo, un cambio concurrente en un método.

Semantic Merge tool

La magia

Para poder mostrar estos conflictos y resolver de manera automática aquellos en los que sea posible, analizamos los ficheros que el usuario nos pasa por parámetros, o a través de la pantalla inicial, si iniciamos sin parámetros (origen, destino y base).

Una vez hemos leído los ficheros y comprobado que no haya errores de análisis, creamos, para cada uno, un árbol semántico, similar a la ventana de clases que se puede ver en Visual Studio.

Semantic tree

Ya con estos árboles, comparamos el origen y el destino con la base para obtener lo que denominamos un árbol de diferencias. Finalmente comparamos estos árboles de diferencias para obtener los posibles conflictos y las diferentes formas de solucionarlos.

Escenarios

Hemos empleado cientos de horas de análisis, y procesado millones de repositorios para obtener las operacions y los conflictos más comunes, entre los que destacan:

  • Movidos divergentes: Si estamos haciendo refactor de nuestro código y movemos a diferentes partes del mismo (desarrollador A los prefiere por orden alfabético y desarrollador B los prefiere por orden de scope) detectamos el cambio y damos al usuario la opción de elegir.
  • Movidos/borrados: En caso de que un elemento (método, clase…) se haya movido en origen y se haya borrado en destino, lo detectamos y damos al usuario la opción de conservar el movido o el borrado.
  • Movidos + cambiados: En el caso de que un desarrollador mueva un método a otra clase y otro realice cambios en el mismo, se detectará automáticamente, y no habrá conflicto :)

Hay mucho más, disponible en semanticmerge.com

Integración

De momento, tenemos tutoriales sobre cómo integrarlo en Git, PlasticSCM, TFS y Perforce, y pronto deberíamos tener para Mercurial y SVN. Si usas otro sistema de control de versiones, avísanos!

Personalización

Mediante los parámetros de entrada, podemos especificar una herramienta de diff y merge personalizada, a través de los parámetros -emt y -edt de entrada. Además se puede especificar el tipo de fichero que estamos procesando aunque no tenga la extensión adecuada mediante el parámetro -t. En estos momentos el único lenguaje de programación soportado es C#, así que en este caso el único valor válido será text/csharp.

One more thing: Diferencias semánticas

Otra de las cosas que incorporamos es una herramienta de diff, que dados dos ficheros nos permite obtener las diferencias entre ellos.

difftool-included

Cómo se hizo

Aunque la idea ha estado en fase de análisis y diseño varios años, el desarrollo principal del proyecto se ha llevado a cabo en los úitimos 6 meses, en el que una buena parte del equipo de Códice ha estado implicada. Hemos estado divididos en dos grupos, uno encargado de las operaciones de merge y del backend de la herramienta, y otro grupo, que hemos estado cubriendo el diseño y la usabilidad de la herramienta.

Además, llevamos varias semanas usando la herramienta como herramienta de merge por defecto de manera interna, y las primeras betas privadas que distribuimos han tenido una acogida muy buena por parte de los voluntarios.

Bajo el capó

El lenguaje usado para todo el desarrollo de la app es C#, de ahí nuestro interés con que sea el primer lenguaje de programación soportado (llevamos semanas probando la herramienta a nivel interno).

La interfaz está desarrollada en WPF con algunos toques de Windows Forms, y para la ventana sin marco usamos la integración con Windows a través de Windows.Shell.

Las herramientas utilizadas han sido PlasticSCM como control de versiones, Visual Studio 2010 – 2012 como entorno de desarrollo y Blend 4 como herramienta de diseño de interfaces,

Pasos adicionales

Estamos en fase beta, con lo cual hay muchas cosas que pulir, además seguimos trabajando en mejorar la herramienta, la usabilidad, el diseño, la velocidad, así como el soporte para lenguajes adicionales y escenarios más complejos. Para ello hemos habilitado un portal en uservoice para recibir feedback de nuestros usuarios.

Presentamos GitSync: Ahora PlasticSCM habla Git

index

En Códice Software desarrollamos Plastic SCM, un sistema de control de versiones enfocado a un entorno corporativo, que comparte filosofía con sistemas como Git o Mercurial, al ser un sistema pensado para su uso de manera distribuida.

A diferencia de estos, contamos con una serie de características dirigidas a entornos corporativos, por ello, nos adaptamos a sus infraestructuras integrándonos con mecanismos de autenticación existentes como LDAP o Active Directory, así como los diferentes sistemas de bases de datos disponibles, desde soluciones embebidas como Firebird o SQL CE, hasta soluciones basadas en Oracle. Además tenemos nuestra propia capa de seguridad a nivel de repositorio, rama o servidor, de tal manera que se pueden aplicar permisos específicos a diferentes roles de usuarios (por ejemplo, la rama de integración solamente la pueden tocar los chicos de Dev-Ops).

Además contamos con una interfaz muy limpia, elegante y completa, así como integración con entornos como Visual Studio, Eclipse o InteliJ IDEA.

Siempre intentamos ir un paso más allá, y es por eso que presentamos GitSync, un sistema por el cual se puede sincronizar un servidor de Plastic SCM con un servidor remoto de git. Esto nos permite compartir con otros desarrolladores que usen git para trabajar, subir nuestro código a sistemas como Github o Bitbucket, y aprovechar servicios que son compatibles con Git, como es el caso de Heroku, AppHarbor o, recientemente, Windows Azure.

Esta sincronización es bidireccional, y continua, no se trata de un importador/exportador (aunque eso, también lo hacemos). Sincronizamos todo el repositorio: ramas, changesets y etiquetas

En estos momentos estamos en fase de beta privada, a la que se puede acceder en este enlace. Valoramos mucho el feedback de nuestros usuarios, y por ello regalamos un iPhone 5 a aquellos que nos ayuden a mejorar nuestra herramienta. Quieres el tuyo?

DVCS: La herramienta definitiva para un hackathon

Un hackaton es un evento social donde programadores y diseñadores compiten en grupos durante 24 – 48h en el desarrollo de la mejor aplicación para la plataforma elegida por los organizadores. En este tipo de eventos el tiempo es un factor clave, y la posibilidad de que un error en los últimos 5 minutos destroce horas de desarrollo es muy alta, ya que se viven momentos de muchísima tensión.

En estos casos es útil contar con un sistema de control de versiones para poder tener un registro de la evolución del proyecto, y evitar perder el rumbo original.

En el último Hackatón al que asistí hace unos días pude experimentar la frustración de grupos que usaban Team Foundation Services Preview, un sistema de control de versiones centralizado y en la nube. Es una herramienta muy potente para gestión de código fuente aunque muestra algunas debilidades para este escenario en concreto:

  • Necesita una conexión a internet estable y constante, ya que de otra manera no se puede realizar un check-in ni un checkout, y cada operación añade una carga adicional a la red.
  • Es centralizado, con lo cual cada vez que se hace un check-in se integra todo el código, y si había cambios en el servidor es necesario obtener primero la última revisión y luego integrarlo en local (manejando posibles conflictos, por supuesto) antes de poder enviar los cambios de vuelta, perdiendo ese preciado tiempo del que no se dispone.

Todo esto hace que se emplee el repositorio como una herramienta de sincronización, no como un control real de las versiones del código.

Veamos el mismo escenario con un sistema de control de versiones distribuido (DVCS):

  • Cada miembro del equipo puede desarrollar su código de manera independiente en una rama, y hacer commits frecuentes asegurando un mejor historial.
  • El resto de los miembros del equipo pueden replicar los cambios usando la red local, sin que sea necesario usar el ancho de banda, ni servidores externos.
  • Se puede controlar que otros equipos en la misma red no accedan al código, aunque compartan conexión a internet, mediante listas de control de acceso (ACL).
  • Las operaciones de merge son menos constantes, al hacer integración de componentes terminados, evitando riesgos de introducir errores de regresión. Además con tecnologías como Xmerge se puede detectar código refactorizado e integrar de una manera más sencilla.
  • Se pueden integrar los cambios en una rama principal sin que ello afecte al desarrollo del proyecto (una persona puede dedicarse a esa tarea, aunque no es necesario que lo haga de manera exclusiva).

PlasticSCM permite todas las características comentadas anteriormente y más, aunque hay otras herramientas como Git o Mercurial disponibles en el mercado.

Cuando el desarrollo es ágil (nada más ágil que un evento de esta magnitud) tener las herramientas adecuadas puede ser la diferencia entre una aplicación buena y una espectacular.

Para la próxima hackatón, te propongo usar un DVCS, y si escoges PlasticSCM, puedes dejar críticas y sugerencias en los comentarios.

Más información:

Git, un sistema de control de versiones peculiar

Si desarrollas software (de manera profesional, como parte de la carrera o como hobby) habrá un antes y un después de los sistemas de Control de código fuente, control de versiones o, para los amigos, SCM.

Continuar leyendo «Git, un sistema de control de versiones peculiar»