The Plastic SCM blog

martes, abril 10, 2012

Plastic contra Perforce

Esto de crear un producto para desarrolladores tiene su gracia: no hay productos 'locales' así que a la fuerza tu software tiene que ser global.

Y para un equipo en el Parque Tecnológico de Boecillo, Valladolid, la idea de competir en la liga mundial suena genial (suena a palabras mayores, la verdad).

Pero el tema es que, efectivamente, en cada oportunidad nos vemos con Perforce, AccuRev, ClearCase, Mercurial, Git, Subversion, TFS... cada uno de ellos de un tamaño comparativamente considerable.

Vamos, que vas a la empresa de la puerta de al lado y usan o piensan en usar uno de los de la lista anterior... y el hecho de "estar cerca", no juega casi nunca a tu favor.

Perforce

Perforce es uno de los sistemas de control de versiones más utilizados. Por supuesto Mr. Torvalds también lo criticó a muerte en su famosa charla (eso de destruir empresas, empleos y no llevarse nada a cambio se le da bien :P), lo que no quiere decir que sea un producto muy, muy, muy potente.

Se usa en muchísimas industrias pero en la que es casi el estándard es en videojuegos. Casi cualquier equipo que se precie ;) tiene un P4 instalado.

Las características particulares que se usan en gaming son:

  • Manejo de ficheros muy, muy gordos
  • Velocidad... tiene que ser rápido

    Plastic entra en acción

    Competir contra Perforce (una empresa que factura unas cuantas decenas de millones, 200 empleados, fundada en el 95) no es sencillo, pero la oportunidad viene por:
  • No es muy bueno manejando ramas (hasta hace poco hasta decía que eran 'evil').
  • No es distribuido (vale, puedes montar un proxy pero no es lo mismo... un proxy es la aproximación 'pobre') (ojo, nosotros, además de ser distributed, también tenemos un proxy, por aquello de tener 'de todo').
  • Tampoco es que sea brutal con los merges

    De hecho, una de las características de Perforce solía ser "the fast scm", pero claro, con Git a la vista... lo de "the fast" quedó fuera... y supongo que tampoco se iban a poner "the furious", así que pasaron a "version everything" (por cierto, un slogan no muy bueno que nosotros también usamos en nuestros screencasts hace aaaaaaños, aunque no, no nos han copiado ;P).

    No obstante, aunque la batalla de la velocidad es complicada, a nosotros siempre nos gusta entrar al trapo. Esto son unos tests hechos con un repo de ejemplo basado en el código de uno de nuestros clientes:

    Y es una de las razones por las que algunos equipos que usan Perforce no pueden usar ramas: no pueden esperar 30 minutos para crear una rama cuando otros productos lo hacen en 2 segundos...
  • Que las ramas te dejen ver el bosque

    Ya, ya, ya sé que el dicho no es así... pero es que en el mundo de desarrollo de software se está imponiendo justo lo contrario.

    Habéis visto las release notes de Bamboo 4.0? Pues efectivamente: es todo sobre branching y merging.

    Me gusta mucho leer esto porque cuando arrancamos Plastic hace ya unos cuantos años, nuestro objetivo era precísamente ese: ramas por todos lados.

    Hace mucho tiempo escribí sobre cómo hacer "branch per task" con CruiseControl (Bamboo no estaba tan de moda... ¿existía?) y hace poco Luis preparó el plugin de Bamboo (versión 3!) para monitorizar ramas independientes, así que, como decía, leer sobre Bamboo soportando ramas "por defecto", me ha encantado!

    Ramas malditas

    "Branches are evil" era el lema de Subversion y también de Perforce hace unos pocos años... "No crees ramas, son malas, malditas, dan miedo y te llevarán al infierno" (o algo peor) era lo que los profetas del "mainline" predicaban todos los días. Trabaja en "mainline" (línea principal, vamos, que una sóla rama y hagas checkin), decían.

    Como casi siempre que alguien dice "no hagas esto" es por una razón bastante patética: Subversion es horrible manejando ramas (Perforce también es horrible manejando ramas: crea una rama en un repo de 100mil ficheros... media horita de nada... es por eso que las empresas de video-juegos están saltando del barco como si fuera el Titanic).

    (Aquí entra el punto en el que los que usáis SVN os cabreáis y decís "sí, si que se puede, eso no es verdad". Entonces tengo que explicar un rollo del tipo: "vale, te sirve para escenarios 'hola mundo' con 3 ramitas de juguete. Prueba con 1000 ramas, o 5000, y con un montón de ficheros, y prueba a hacer refactor de verdad, renombrando un fichero y modificándolo en una rama, cambiándolo en otro... y haz merge... Se rompe, ¿verdad? Pues eso, de juguete". Si te pones pesado con el tema de SVN invocaré al sumo pontíce: "tío, Torvalds hizo Git justo porque el merge de SVN era una porquería...". Normalmente eso funciona.)

    Así que... sí, afrontémoslo: los predicadores de Subversion engañaron a una generación entera de programadores en todo el mundo (2000-2008) mutilando su forma de pensar, haciéndoles creer en la religión única de "las ramas son malignas".

    Es momento de abrir los ojos.

    Parche tras parche

    Como eso de manejar ramas era una castaña y las versiones se rompían todos los días, hubo que poner un poco de pegamento alrededor.

    Y así nació la integración continua, que como idea está genial, pero que la ausencia de ramas es un pegote: haz checkin continuamente y pasa tu test-suite mágica y si rompes el build, enciende un semáforo (o que te electrocute tu ratón) y lo arreglas en un plis-plas antes de que tus colegas te cuelguen de la pizarra de tareas del scrum.

    A ver... es mejor que no hacer tests, seguro, y como muchos vivíamos en la inmundicia sin esto... pues era un avance.

    Lo malo es que se convirtió en religión: "no, no necesito ramas porque hago CI".

    Y bueno... duró un poco la cosa.

    El tema es: haces checkin, petas un test, el sitema de CI te avisa pero... ¡¡tienes a todos tus compañeros echando humo porque has petado el build!!

    Es reactivo. Lo rompes, lo arreglas.

    No está mal en ausencia de algo mejor, pero supone que:

  • Te da miedo hacer checkin por si rompes el build
  • Haces checkin mucho menos frecuentemente que cuando aprendes CI siguiendo el ejemplo del "hola mundo", del "juego de póker" o de cualquier otro invento de esos que funcionan siempre
  • No usas el control de versiones más que para... entregar código... que bueno, ha sido lo que la generación subversion ha aceptado como bueno... a falta de algo mejor

    Regreso al futuro

    Hace unos años en la casi-biblia de continuous integration, el señor Duvall (no confundir con el actor) veía un futuro pre-claro en el que para evitar el problema de los broken builds en CI usando un "two phase commit".

    Independientemente de que lo que diga tenga o no sentido, usó una receta mágica: nadie en su sano juicio le lleva la contraria a alguien que dice "commit de dos fases", no vaya a ser que encima le toque explicar el algoritmo!! Así que, cuando alguien usa "two phase commit", seguro que no es en vano... creámosle! :P

    Bien, el mecanismo del futuro perfecto consiste en:

  • Evita romper los builds
  • Creando un "almacenamiento temporal" en el que tus cambios viajan hasta el CI server, se compilan, se prueban y, si todo va bien, se completa el checkin

    Hablé del tema hace tiempo y la sigo pensando lo mismo: puede usted hacerlo más complicado todavía introduciendo una paloma mensajera para enviarte los resultados de build de vuelta...

    ¡¡Vaya montaje por no usar ramas!!

    El invento, y de ahí lo de "regreso al futuro" llevaba años inventado: usa ramas para tus tareas y déjate de cuentos!

    Ya estaba inventado

    Si hoy dices "ClearCase" tu índice de "cool" cae en picado... así que no lo digas.

    Pero ClearCase era un sistema de control de versiones que ya hacía ramas y merges buenísimos en el año 95, 5 años antes del "Subversion doom's day".

    Casi todo lo que sepas sobre control de versiones ya lo hacía ClearCase (CC para los amigos) hace 15 años. Es como el "xerox park" de los controles de versiones, parece que no se inventó nada después...

    El tema es que ClearCase era caro. Caro de narices. Caro como cuando se pagaba por el software una fortuna. Una licencia de CC costaba entre 3 y 4mil Euros por usuario. 5mil si era de multi-site (capacidad distributed, con réplica y todo, pero en plan pantalones campana).

    Hacer algo mejor que ClearCase pero rápido y barato fue nuestra primera motivación para desarrollar Plastic...

    Al tema: CC ya podía crear todas las ramas que quisieras, y mezclarlas bien. Lo que pasa es que CC tenía algunos problemillas:

  • Tiraba una barbaridad de la red (vistas dinámicas y otras maravillas), así que en una LAN bien configurada (difícil de configurar) iba bien... pero muy pocos sysadmins de verdad eran capaces
  • Cuando la red no iba bien... era leeeeeento
  • Instalarlo era un dolor. En 8 horitas, con experiencia, montas uno sin problema. Sí, 8 horas... (para que luego digan que instalar plastic, en 40 segundos, es lento :P)
  • Cambió de manos: lo compró primero Rational, le pusieron una capa "metodológica" por encima, para hacerlo más sencillo, y se lo cargaron. Nació UCM, con streams, sobre 2000. Un sistema con todas las desventajas de ClearCase y Subversion juntas... Lo mataron.
  • He dicho que era caro?

    Así que el "xerox park" del control de versiones cabó su propia tumba...

    No obstante, hasta hace bien poco, incluso en el máximo esplendor de Subversion, para que os hagáis una idea de lo que es la pasta..., CC facturaba el 50% del negocio del control de versiones, frente a un 0,7% de SVN... mucho ruido y pocas nueces, que se dice.

    El segundo advenimiento de Torvalds

    Y entonces en 2005 todo cambió.

    Los "falsos profetas" de SVN tuvieron que ver como regresaba el mesías del open source para dividir las aguas y cargarse a SVN rápidamente: una charla de Torvalds anunciando, en google, eso sí, que había creado, en 3 días (muy trascendente) un nuevo control de versiones que:

  • Manejaba bien las ramas
  • Hacía bien los merges
  • Era distribuido

    Y mató a SVN en 3 años.

    Todos, sí, todos, los proyectos open source importantes del mundo dejaron SVN y pasaron a Git (o Mercurial, el hermano siniestro de Git) antes de que terminase 2008.

    No está mal para Mr. Torvalds, el tío que más pasta ha hecho ganar a otros con su software y que menos se ha quedado... todo un mesías.

    Vete por las ramas!

    Git es distribuido, que mola, porque puedes tener tu repo en tu máquina y hacer push y pull con el central, pero trabajar totalmente desconectado.

    Pero, el principal tema no es que sea "dvcs" (que sí, que mola!) es que maneja muy, muy bien las ramas.

    Crea ramas para lo que quieras, para cada tarea (sí, por cada entrada en tu issue tracker favorito, una rama), y trabaja en ellas, y luego haz merge, sin problema.

    De eso va el cambio. De usar ramas.

    Así que los "profetas de svn" se quedaron compuestos y sin novia.

    SourceForge se fue a pique frente a GitHub (el sitio por antonomasia que logra que un sistema distribuido sea, uhm... centralizado!), la gente de Perforce ya no tiene narices para decir "branches are evil" y dice todo lo contrario (con el mismo producto, eso sí, que lo hace igual de mal que antes), "distributed" y dvcs son las palabras de moda (hasta SVN intentó convencer de que era dvcs... por tener un puerto abierto... argh!), y el control de versiones ya no es "una herramienta coñazo" sino lo que hace que tu proyecto sea "cutting edge". Tela!

    Dónde estábamos nosotros?

    A nosotros, con Plastic, no nos suena raro. En 2005 queríamos hacer algo tan potente como ClearCase pero rápido, fácil, simple de instalar y asequible. Pronto vimos como Git nacía y nos pisó nuestro sueño de versionar el Kernel de Linux, aunque era un sueño loco dadas las guerras religiosas que se montaron alrededor del control de versiones (nota: años después, en la otra punta del mundo, plastic 4 versiona repositorios comerciales que incluyen todo el código de linux, android, chromium, el quake y hasta el grep y el tar... 300 mil ficheros... no está mal!).

    El caso es que la base era la "rama por tarea": hacer ramas bien, rápidas, muy rápidas, poder tener muchísimas, y poder hacer bien los merges también. Y además hacerlo fácil.

    Así que en 2006, cuando lanzamos Plastic 1.0, la gente nos miraba raro en las demos cuando les decíamos lo de "sí, sí, crea ramas".

    Ahora, años después, y gracias a Git, Mercurial y el cambio total de tendencia, lo que nos piden es precísamente eso: ramas, ramas, ramas.

    Nuestro objetivo era diferente al de Git (vale, y no podemos decir lo que nos de la gana en una charla, como Torvalds, y quedarnos tan anchos... porque no hemos creado un sistema operativo) porque al final siempre hemos estado centrados en crear un sistema no para proyectos open sino para empresas: de cualquier tamaño, pero empresas.

    Se hace "mainstream"

    Así que ahora la gente de los "continuous integration systems", como Atlassian y su Bamboo, por fin ha pillado el rollo y adapta su sistema a "branching". El paso natural. La puntilla final, espero, para los que viven anclados en el pasado "sin ramas", y un paso adelante enorme que evangelizará a muchísimos usuarios.

    Espero que por fin el legado "evil" de SVN se diluya...

  • miércoles, septiembre 21, 2011

    Plastic internals: de 3.0 a 4.0

    Hoy va a ir de programación y estructuras de datos :). Voy a explicar en qué consiste el cambio fundamental en el que hemos estado trabajando en Plastic 4.0. Un cambio “core” de verdad que tiene mucho impacto y que creo que es muy interesante. Afecta al rendimiento, al sistema de réplica (lo que nos hace un DVCS), al mantenimiento del código, a la usabilidad…

    Os habéis fijado en el nuevo Branch Explorer de 4.0? Dibujo una comparativa debajo:

    Además de que los gráficos son mejores, ¿qué más veis? Los cuadrados de 3.0 son changesets y se han convertido en óvalos en 4.0, más grandes, porque ahora son más importantes. Pero hay otro tema: hay unas flechas entre los changesets que antes no existían. Esas flechas indican “parentesco”.

    Es decir, ahora Plastic “sabe” que un changeset es padre de otro, mientras que antes no se guardaba esa relación.

    Pero voy a bajar más, a las profundidades del sistema.

    Almacenamiento de versiones

    Un control de versiones guarda los cambios que haces en un árbol de código. Es decir, tú tienes un proyecto con ficheros y directorios, y por cada cambio se van guardando “revisiones” (que tienen muchas utilidades, desde volver atrás, revisar, etc, etc, pero no es el tema ahora).

    Un ejemplo como el siguiente:

  • Primero tenemos un repositorio vacío.
  • Luego añadimos /src y /src/foo.c
  • Luego se modifica foo.c

    ¿Cómo se guarda eso en Plastic?

    ¿Qué hay en la base de datos de Plastic?

    Instalad 3.0, con el backend de base de datos que más os guste (ya sabéis, Firebird, SQLite, MySQL, SQLServer… hay unos cuantos) y ejecutad las siguientes queries:

    “select * from revision”

    “select * from item”

    “select * from childrenitem”

    En lugar de conectaros al backend, es posible ejecutar las consultas con el comando “cm query” o “cm q” (hay que tener el permiso “advanced query” para poder hacerlo, cuestiones de seguridad).

    Si veis las tablas que usa plastic veréis que son muy pocas. Ahora me centro sólo en tres que se pueden definir con el siguiente diagrama entidad-relación (no muy ortodoxo).

  • Cada elemento en el sistema es un ítem. Es decir, el directorio raíz (/) del ejemplo anterior es un ítem, “src” es un ítem y “foo.c” es un ítem. Pero un ítem es una “entrada abstracta”, es “que existes” pero no tienes ni un nombre asociado. (Ahora os he perdido, pero para dejarlo sencillo, un ítem es “la clase” y una revisión es “el objeto”).
  • Un ítem puede tener una o varias revisiones. Es decir, de “foo.c” podemos tener miles de revisiones (por eso sacar la historia en plastic es muy sencillo: “select * from revision where fiditem=xxx”).
  • Un ítem puede representar a un fichero o a un directorio.
  • Una revisión, si es fichero, puede ser texto o binario, si es directorio sólo directorio (es un poco más complejo porque también soportamos links y cosas así, pero de momento sirve).
  • Si la revisión es un fichero, tendrá un dato asociado (tabla revisiondata, los datos divididos en blobs de máximo 4Mb).
  • Si la revisión es un directorio entonces empieza lo bueno: puede tener una o más entradas “childrenitem”.

    Al principio dije que “el ítem es abstracto” porque no tiene ni nombre ni datos. La revisión tampoco conoce su nombre, el nombre, en realidad, se guarda en el childrenitem.

    Me explico: un fichero “foo.c” puede llamarse más adelante “bar.c” pero sigue siendo el mismo ítem, es más, ni siquiera se crea una revisión nueva del fichero al hacer un renombrado, sino una nueva versión del directorio que lo contiene y que le da nombre.

    ¿Ahora se entiende mejor?

    Volviendo al ejemplo original:

  • Al principio sólo tenemos un ítem (el “famoso” ítem raíz) y una revisión (revisión cero) de ese ítem raíz en el changeset 0.
  • Entonces añadimos src y src/foo.c. ¿Qué quiere decir? Que se añaden dos ítems nuevos y dos revisiones nuevas.

    ¿Qué ocurre con los “children ítems”? Aquí viene lo interesante.

    En el changeset 0 la tabla childrenitem está vacía.

    En el changeset 1 la tabla childrenitem tiene el siguiente aspecto (recordad, acabamos de añadir /src y /src.foo.c al sistema):

    ¿Qué quiere decir?

  • Hemos creado la “revisión 1” del directorio raíz (antes era la revisión 0, se crea una nueva al añadir “src”).
  • Esa revisión 1 (DirRevId) tiene como dato una entrada llamada “src”, que es el itemId 10.
  • A su vez el directorio “src” tiene una primera revisión (revisión DirRevId = 2 en este caso (estoy usando un nº global para referirme a las revisiones, que es lo que usa plastic internamente)) que tiene como dato una entrada llamada “foo.c” del itemId 11.

    Es decir, el directorio raíz es el ítem 0. “src” es el ítem 10. “foo.c” es el ítem 11. Sabemos que hemos creado una nueva revisión de “/” (raíz) que es la “1”. Y una revisión de “src” que es la “2” (no incluyo la revisión creada con los datos de foo.c porque no tiene que ver con “childrenitem”).

    De este modo es como Plastic asocia los nombres de elementos (ítems) a entradas de directorio concretas.

    Un segundo checkin

    En el changeset 2 lo que ocurre es que se crea una nueva revisión del fichero src/foo.c.

    ¿Cómo se altera la tabla “revision”? Simple: se crea una nueva entrada para almacenar el nuevo cambio de foo.c

    ¿Cómo se altera la tabla “childrenitem”? No se modifica. No hay cambio en la estructura, luego no se modifica.

    El selector entra en escena

    Si habéis usado Plastic habréis visto alguna vez que cada workspace tiene asociado un “selector”. Ese selector es un texto que le indica al sistema “qué debe cargar” en el workspace. Es algo como:
    repository "doc@diana.codicefactory.com:9092"
      path "/"
        branch "/main"
        checkout "/main"
    

    Para muchos esto lo que hace es que le dice a Plastic que debe trabajar en la rama “main” y listo.

    Pero en realidad no es tan simple.

    Al estudiar “childrenitem” habréis visto que hay una relación entre el directorio y los ítems que debe cargar pero… ¿cómo sabemos qué revisión de un ítem determinado se debe cargar?

    Es decir, si yo cargo la revisión 1 del root ítem, sé que debo cargar una entrada del ítem “src” (ítem 10). Esa información me la da la primera línea de “childrenitem”. Pero, ¿qué revisión de “src” debo cargar?

    Es más, si nuestro repositorio ahora mismo (changeset 2) es algo como (en plan diagrama de objetos):

    ¿Cómo sabemos qué se debe “montar” como árbol de ficheros en un momento dado?

    Es ahí donde entra en acción el selector. Las siguientes reglas:

    repository "doc@diana.codicefactory.com:9092"
      path "/"
        branch "/main"
        checkout "/main"
    

    En realidad quieren decir: “carga lo último de la rama “main” para todo lo que esté bajo el path “/” “.

    Al resolver un selector Plastic lo primero que hace es buscar el “root ítem”:

  • ¿Está el root ítem? Sí, es el ítem 0. (En caso contrario se daría un error fatal)
  • Cuál es la última revisión del root ítem? En nuestro caso la revisión 1.
  • Ok, coger la revisión 1.
  • ¿Tiene datos? – Sí, es un directorio y como “dato” tiene la entrada de children ítem “src”.
  • ¿Qué ítem es src? – Es el ítem 10.
  • Ahora el proceso se repite recursivamente para cada directorio: ¿cuál es la última revisión de “src”? Es la revisión 2.
  • ¿Tiene datos la revisión 2? Sí, tiene una entrada “foo.c –item 11”.
  • ¿Cuál es la última revisión de foo.c? Es la revisión 4, la que hemos creado en el changeset 2.

    Por tanto, el selector anterior cargaría el siguiente árbol:

    Que es el árbol que se resuelve en el changeset último en este momento o changeset 2.

    (No he incluido el manejo de ramas en todo el ejemplo, pero sería lo mismo, realmente el selector no dice “cuál es la última revisión del ítem 10” sino “cuál es la última revisión del ítem 10 en la rama main”)

    Qué pasaría si ahora modificásemos el selector de la siguiente forma:

    repository "doc@diana.codicefactory.com:9092"
      path "/"
        branch "/main" changeset “1”
        checkout "/main"
    

    Ocurriría que la respuesta a las preguntas anteriores nos daría el siguiente árbol:

    Destacando lo que ha cambiado respecto al selector anterior.

    Un grafo dinámico

    Es decir, Plastic NO puede resolver un árbol de directorios si no se le indica un “selector” que le ayude a “seleccionar” la revisión adecuada al ir cargando cada nivel de directorios.

    La carga de árboles (resolución de selector o “solvepath” como le llamamos en el equipo) no funciona exactamente como la he descrito. Es decir, sí que funciona así a nivel lógico pero está optimizada para minimizar las consultas a la base de datos, utiliza cachés intermedias, etc, etc (ha sido uno de los campos de optimización desde los primeros pasos del proyecto).

    Este grafo dinámico da una enorme flexibilidad: un movido, un renombrado, se trazan a nivel de directorio, pero no se tiene que crear una nueva revisión de los ficheros implicados (o directorios).

    Mediante esta estructura (y un uso adecuado de selectores) es como se implementa el sistema de “herencia de ramas”:

  • Al cargar la “última revisión de /main/tarea001” de foo.c lo que se hace es: ¿hay una revisión en la rama “tarea001”? Sí, cogerla.
  • No? Entonces coger la última (o la correspondiente según la estructura de la “smartbranch” task001) de la rama “padre” /main.

    Y así es como funciona la herencia de ramas…

    Los selectores y la estructura de gráfico dinámico dan una gran flexibilidad: es posible tener estructuras diferentes del árbol montando “diferentes reglas”: podrías coger un directorio de una rama, que cargue el contenido de los ficheros de otra, montando una estructura totalmente dinámica.

    En realidad una cosa es lo que “existe” en el repositorio y otra lo que el usuario “ve” en el workspace, muy al estilo de las “vistas” del viejo ClearCase.

    Como veis, el sistema hasta 3.0 tenía una enorme flexibilidad.

    Cambios en 4.0

    Pero a cambio de esa “flexibilidad” también había una gran “complejidad”. Por un lado se necesita un tiempo para acostumbrarse al mecanismo “grafo dinámico” aunque mediante nuestras herramientas intentamos hacerlo lo más transparente posible.

    Por otro, impone ciertas complicaciones a la hora de trabajar en modo distribuido (DVCS), como por ejemplo garantizar que un changeset en un repositorio es exactamente igual al replicarlo a otro, porque dependerá de las revisiones que existan en el destino y de cómo se carguen. Un pequeño lío.

    Además la carga, aunque optimizada, era pesada…

    ¿¿Qué hemos cambiado en 4.0??

    Pues en realidad usamos la misma base de datos!!!

    En serio, la misma estructura, pero con un pequeño “hack” en cuanto al significado.

    ¿Recordáis la tabla childrenitem?

    Pues hay un pequeño cambio en 4.0: en lugar de que cada entrada apunte a un itemid, apunta a un revid… (¡!!!!)

    ¿Qué significa esto?

    Significa que nos ahorramos la fase de resolución porque ahora cada árbol es “hardcoded” una vez que se hace checkin. Un changeset tiene una estructura fija, más sencilla de entender, más rápida y eficaz, mucho mejor en la réplica. No hay que interpretar una serie de reglas para resolver un árbol.

    Perdemos algo de flexibilidad, es cierto, no se pueden hacer maravillas como modificar un directorio en una rama, cambiando el nombre a un fichero y nada más, y poder montar un selector complejo que altere el nombre de un ítem concreto sólo en nuestra vista jugando con esas ramas. No puede hacerse y me dolió mucho quitarlo pero… era una flexibilidad con un gran poder y… muy poca responsabilidad ;)

    4.0 es más “DAG” (algún Git fan por aquí?), más rápido, más simple, y este pequeño cambio (un solo significado dentro de una tabla) define un nuevo mecanismo de merge, de réplica, de checkin, de diferencias… de sincronización con otros SCMs… de todo!!!

  • lunes, septiembre 12, 2011

    Merges parciales?

    El tema, al primer vistazo, puede sonar un poco rebuscado, así que voy a intentar simplificarlo al máximo.

    ¿Qué es un merge parcial?

    Hacer un “merge parcial” consiste en, dada una rama o un changeset (commit, en términos Hg/Git) que se denominará “origen del merge” (src), hacer “merge” (o integrar) en una rama destino sólo parte de los elementos modificados en el origen del merge. Con una imagen seguro que se entiende mejor:
    El “ninja coder” ha modificado unos cuantos ficheros en una rama, ¿qué pasaría si sólo quiere integrar render.c y readme.txt pero ser capaz de integrar el resto más tarde?

    Nota: Las "flechas" entre changeset y changeset indican "parentesco". Es decir, el cset 0 es padre del cset 1. Las flechas indican parentesco y no secuencia, al estilo de lo que Scott Chacon dibuja en Getting Git (slide 165). Por cierto, es también como nuestro branch explorer de 4.0 dibuja las cosas.

    Objetivo

    Mi objetivo con este post es: que me enviéis vuestra opinión sobre la importancia, o no, de los "merges parciales" en vuestro equipo. Podéis dejar comentarios en este post o bien contribuir a este thread de stackoverflow: http://stackoverflow.com/questions/7323662/dvcs-partial-merge-git-hg-merge-tracking

    ¿Por qué esto es importante?

    Para algunos de vosotros quizá la explicación de arriba os suena ya a hablar de un caso rebuscado. ¡No sabéis cuánto me alegro! Me alegro porque quiere decir que no necesitáis merges parciales, lo que me simplifica mucho la vida. Los merges parciales son importantes porque todos los DVCS (Distributed Version Control System) como Git o Mercurial (Hg) carecen de merge parcial. ¿Es esa una enorme carencia? Es lo que me gustaría que me contaseis.

    Para los usuarios de Subversion que se están riendo…

    … con una risa contagiosa y malvada diciendo “ya os lo decía yo, los DVCS esos son una patata, mejor quedarse con el viejo SVN!!”. Vale, ¡estáis listos! Esto de los merges parciales afecta a sistemas como Git o Hg (que no lo tienen) frente a sistemas como Clearcase o nuestro Plastic <=3… vosotros, queridos usuarios de SVN, no tenéis este problema… ¡¡estáis todavía peor!!

    En detalle

    Vamos a ver qué significa eso de los merges parciales, con imágenes:
    Primero el “ninja coder” hace un merge de dos de los cuatro ficheros que modificó. Luego:
  • Un sistema sin “merge parcial” con trazabilidad a nivel de changeset, crea un “merge link” entre changesets que se han mezclado, pero no tiene modo de saber si todo el contenido (todos los ficheros) fue mezclado o no. Asume siempre que el contenido completo fue mezclado.
  • Un sistema con “merge parcial” (como lo era Plastic SCM hasta 4.0) identifica la historia de merge ítem por ítem mientras que en los DVCS modernos la “trazabilidad de merge” va a nivel de changeset. Implica que hay muchos cálculos (uno por fichero) en lugar de uno sólo para todos.

    ¿Cómo es de importante?

    ¿Integras primero partes de una rama y luego el resto? Si es así, o cambias de método de trabajo o el sistema de merge “parcial” no servirá demasiado.

    Ventajas y desventajas

    No soportar “merges parciales” hace que el mecanismo de merge de ramas sea mucho más rápido. La desventaja es que no es sencillo (se puede hacer dividiendo changesets) mezclar sólo parte de una rama.

    Opiniones

    En la beta de 4.0 (igual que en todos los DVCS incluyendo Git y Hg) el merge tracking es a nivel de cset, lo que implica que no hay soporte para merges parciales.

    Enviadnos opiniones para saber cómo de importante es soportar merge parcial y actuar en consecuencia!

    Como decía: podéis dejar comentarios en este post o bien contribuir a este thread de stackoverflow: http://stackoverflow.com/questions/7323662/dvcs-partial-merge-git-hg-merge-tracking

  • viernes, septiembre 09, 2011

    Test hacker – Plastic SCM

    Estamos buscando a un auténtico "test hacker" que nos ayude a mover Plastic SCM al siguiente nivel.

    ¿Qué buscamos?

    Ingenieros con muchos conocimientos de programación y capaces de:
  • Verificar cada una de las nuevas características y bugfixes de Plastic: exploratory testing y definición de nuevos juegos automáticos de tests (e incluso colaborar con el resto del equipo en su implementación), detección de problemas de usabilidad, reducción de regresiones.
  • Continuar desarrollando el entorno de testing automático: ejecución más rápida de los juegos de pruebas automáticas, paralelización, desarrollo de tests de carga en cluster, migración a Amazon EC2… y todo lo que nos puedas aportar y que estamos deseosos de aprender!
  • No buscamos: experiencia en “ejecutar guiones de tests” sin conocimientos actualizados de programación. No pasamos “guiones de tests a mano”, eso lo tenemos automatizado, necesitamos complementar los tests automáticos y continuar mejorándolos, aumentándolos y haciendo más rápida su ejecución.

    ¿Qué te ofrecemos?

  • Competir contra software de nivel mundial como Perforce, Git, Mercurial, Subversion, ClearCase, Team Foundation Server, AccuRev… Trabajar en control de versiones es pasar a primer nivel, luchar contra los mejores del mundo en el sector, cada día.
  • Problemas de software complicados, muy complicados.
  • Desarrollar en áreas muy diferentes: desde server a cliente GUI, web a capa de red, base de datos a gráficos 3D. Lo de “hacer siempre lo mismo” simplemente no ocurre.
  • Flexibilidad y libertad: controlar, de verdad, cómo y cuándo trabajas.
  • Incorporarte en un gran momento cuando todavía se puede ser parte del núcleo.
  • Remuneración económica muy competitiva.

    ¿Te interesa?

    Si te interesa envíanos tu currículum a: cv@codicesoftware.com y cuéntanos por qué eres el profesional que nos hace falta.

    Mucha más información…

    … por si tienes ganas de conocer más. En cada proyecto competimos con productos como Perforce (el sistema de control de versiones que usa Google... sí, no usa Git, ni SVN!!, y por cientos de miles de desarrolladores de videojuegos), ClearCase (de IBM), AccuRev, Git (el sistema DVCS iniciado por Linus Torvalds), Subversion (SVN)... La mayoría de nuestros clientes y de las descargas de nuestro software son de Estados Unidos, Inglaterra, Australia, Alemania... Códice arrancó en 2005 y está formada por jóvenes ingenieros (cada vez menos jóvenes ;) que creemos firmemente en crear software que compita a nivel mundial. Y no sólo lo creemos, lo logramos día a día. Algunos datos que te pueden interesar:
  • Fuimos la primera pyme en lograr CMMi 2
  • Estamos iniciando nuestro Sprint 113 de Scrum
  • Automatizamos las pruebas de software con tests unitarios, de smoke (línea de comandos automatizada, somos los creadores de PNUnit, la extensión de NUnit para tests paralelos que puedes encontrar en NUnit 2.5) y Gui (TestComplete), que en total suman más de 30 horas de ejecución, que paralelizamos con VMWare y logramos dejar en "sólo" 4-5 horas. El siguiente paso, y ahí podrías colaborar, es usar EC2 de Amazon.
  • Desarrollamos el único DVCS comercial que existe (y tenemos que darnos prisa porque la competencia se mueve)
  • Nos encargamos de la release en Solaris del proyecto Mono, y hemos hecho muchas contribuciones (colaboramos en el desarrollo del nuevo Garbage Collector que se probó mediante tests de carga de nuestro servidor “plasticd”, plastic daemon)
  • Usamos Java, C y mucho, mucho C#, de hecho, no encontrarás otra empresa que use C# en Windows, Linux, MacOS X, Solaris, FreeBSD... (y OpenBSD pero de forma no oficial ;) )
  • Códice está respaldada financieramente por un fondo de capital riesgo. En medio de una de las mayores crisis económicas de los últimos tiempos nuestra tecnología convenció a un fondo tecnológico puntero, algo que creemos que da confianza.
  • Ofrecemos una remuneración muy competitiva, casi seguro que superior a la mayoría de ofertas que hayas visto.
  • Podrás mejorar tu inglés a diario (de hecho, cuanto más nivel tengas, mejor)
  • Participarás en el diseño de software para desarrolladores, para gente como tú, lo que supone uno de los retos más apasionantes para un ingeniero ya que conocerás a fondo el entorno y podrás aportar soluciones (somos usuarios de nuestro propio software!)
  • Plastic lo usan empresas como HP, VVisions (te suena el "Guitar Hero"?), DHL... y también pequeños equipos de desarrollo en todo el mundo. Uno de nuestros primeros clientes fuera de España fue una unidad del ejército de Estados Unidos, a finales de 2007.
  • Hemos participado en eventos como SDWest y Game Developer's Conference (San Francisco), posteamos y escribimos en sitios como DrDobbs (DDJ), fuimos finalistas de los Jolt Awards hace un par de años... ¿Qué nos gusta ver en las entrevistas?
  • Que dominas los temas de los que hablas: si hablas de Java o .NET… ¿nos podrías explicar lo qué es el Garbage Collector? No es tan difícil…
  • Que leas libros de software.¿Te suena el Code Complete?, Implementation Patterns, Clean Code…
  • Que controles lo que has aprendido: ¿semáforos?, ¿threads?
  • Que te encante desarrollar software Si estás interesado escríbenos a cv@codicesoftware.com
  • lunes, diciembre 13, 2010

    Bienvenido a la Jungla!!

    Nota: creo que es recomendable escuchar esta música mientras leéis el post.

    Y ahora... Welcome to the GitJungle!!

    Acabamos de lanzar GitJungle, un pequeño explorador de repositorios de Git que utiliza nuestra tecnología de visualización de ramas de Plastic SCM (BranchExplorer, BrEx) y básicamente permite ver los repositorios de Git desde un ángulo diferente... :P

    Cómo descargarlo


    Muy fácil, hay que ir a nuestra nueva página de labs, leer un poco más sobre GitJungle y después descargar los binarios (recordad que para Mac y Linux necesitaréis tener Mono instalado).

    Cómo usarlo


    Bueno, supongo que no tengo que explicarle a nadie interesado en GitJungle cómo clonar un repositorio de Git pero para que la entrada quede lo más completa posible:

    $ git clone https://github.com/jquery/jquery.git
    $ cd jquery.git
    $ gitjungle .

    Y entonces tendremos los siguientes gráficos!!



    Action not words!


    Un vídeo de GitJungle en acción aquí:



    Peligro - zona de experimentos!


    Acabamos de lanzar la beta de GitJungle!. Es un experimento, creemos que tiene muy buena pinta y todo eso, pero no deja de ser una beta, así que no está libre de posibles problemas. Si encuentras alguno, ya sabes, ¡dínoslo!

    Lo bueno es que hemos usado el mismo núcleo de código del Branch Explorer de Plastic, lo que nos permite mostrar la historia de forma horizontal en lugar de vertical como hacen GitK y otras herramientas de Git. Así que bienvenidas sean las sugerencias, los aplausos o las críticas más mordaces!

    ¿Por qué nos ha dado por sacar una herramienta para Git?


    Como todos sabéis lo que hacemos es desarrollar y vender Plastic SCM, el DVCS comercial más potente jamás creado, el que tiene mejores visualizaciones, soporta diferentes "backends" de base de datos, seguridad integrada con soporte de ACLs, el mejor sistema de branching y merging.... vale, vale, paro ya con el rollo de marketing! ;)

    Bueno, al tema, que sí, que nos centramos en Plastic, sin embargo desarrollar GitJungle nos ha llevado muy poco tiempo así que... ¿por qué no compartirlo?

    Pero, respondiendo a la pregunta: estamos trabajando a tope en la próxima versión de Plastic SCM y nuestro objetivo es que sea más interoperable que nunca y que tenga sincronización bidireccional con Git!

    También, Plastic SCM es un DVCS para empresas mientras que Git (aunque puede usarse en empresas) está muy enfocado a proyectos Open Source así que, ¿por qué no colaborar? La verdad es que Git está enseñando los conceptos de branching y merging a todo el mundo y educando a los desarrolladores en "desarrollo distribuido". Todo eso es muy bueno para Plastic porque así los usuarios aprecian mucho mejor qué es lo que ofrecemos. (Nota: NO, Plastic NO está basado en Git, hemos tenido que trabajar duro para desarrollar nuestro propio sistema, capa de base de datos, algoritmos de merge, seguridad y... bueno, y todas las cosas divertidas!! :P)

    lunes, noviembre 29, 2010

    Linus habla sobre ramas...

    Hace unos meses Linus Torvalds escribía sobre algunos problemas que tenían en el desarrollo del Kernel con Git debido al uso de ciertos patrones de merge.

    Como aprender de Linus es siempre interesante :P me gustaría entrar en detalle en los puntos que menciona y ver cómo aplicarlo para mejorar en desarrollos del día a día (no hace falta ser un kernel-hacker para sacar partido de esas técnicas). De hecho encaja con el patrón que nosotros recomendamos con Plastic aunque lógicamente él lo aplica a Git y sería también válido con cualquier otro SCM con buen soporte de ramas.

    Las palabras de Linus


    Esto es lo que escribió Linus, sólo he sacado un fragmento así que para tener la visión completa lo mejor es leer el link original.

    The real problem is that maintainers often pick random - and not at all stable - points for their development to begin with. They just pick some random "this is where Linus -git tree is today", and do their development on top of that. THAT is the problem - they are unaware that there's some nasty bug in that version.


    Y ahora intentaré traducir lo mejor posible:

    El verdadero problema es que los “maintainers” a menudo cogen puntos aleatorios – y para nada estables – como partida de sus desarrollos. Simplemente cogen un “aquí es donde está el árbol de Git de Linus hoy” y hacen sus cambios sobre eso. Y ESE es el problema – no son conscientes de que hay un fallo muy feo en esa versión.


    Disparando a un objetivo móvil


    ¿De qué está hablando Torvalds? Realmente de un problema muy bien conocido cuando se trabaja en “trunk o mainline” (vamos, sin ramas) como describía aquí hace ya algún tiempo en la sección titulada “don’t shoot a moving target!” (no dispares a un objetivo móvil).

    El problema afecta duramente a todos los seguidores de la doctrina “mainline/trunk” (ya sabéis, SVN, CVS, VSS…) ya que se están actualizando constantemente a “lo más nuevo” quizá por miedo a hacer merges. Algunos intentarán solucionarlo con integración continua (CI) pero simplemente retrasarán el problema. Lo “malo” es que también afectará a quienes usen “ramas de característica” (feature branches) a menos que sigan todas las reglas (lo que nosotros solemos definir en el patrón de “rama por tarea”).

    El problema con el que se encuentran en el desarrollo del kernel se ve en esta imagen:




    El equipo del kernel usa ramas y todo pero ¿qué pasa si usan “master” como rama de integración (muy común, y correcto) y crean ramas desde “commits” que no están etiquetados (tagged)? (Como muestra el dibujo).

    El problema es que al usarse la rama principal como punto de integración habrá “commits” intermedios (changesets) que no serán estables (especialmente si se usan los “fast-forward” merges de Git, que no me gustan un pelo, pero que supongo que no serán el problema de Torvalds ya que seguro que sabe usar Git muy bien, ¿no???). Entonces los programadores empiezan desde un punto inestable y… comienza la fiesta.

    La clave son las líneas base



    Nosotros hemos tenido exactamente el mismo problema con equipos usando Plastic pero que no entendieron bien al principio la importancia de tener líneas base (baselines, releases estables o como queráis llamarlas). Una vez que el código es estable: ¡etiquetadlo! Y cread las ramas de tarea SÓLO desde puntos estables!

    Esa es la regla básica: cread líneas base con frecuencia (mínimo una a la semana en equipos de menos de 10 personas y más si el equipo crece) que por supuesto deben estar totalmente probadas (juego de test automático y cualquier tipo de prueba accesoria o manual que hagáis, de hecho esta es la parte larga de hacer integraciones, los merges, hoy por hoy, tienen que ser muy rápidos) y CREAD LAS RAMAS SÓLO DESDE BASELINES ESTABLES como muestra la siguiente figura:



    De esta forma si algo falla en tu rama de tarea (o feature branch) sabes que… ¡es por tu culpa!, porque todos los tests estaban bien en la línea base (no sólo el juego rápido que puedes pasar en CI, también los que tardan horas).

    Una regla muy, muy sencilla y con enorme ahorro en tiempo y dolores de cabeza!

    domingo, noviembre 28, 2010

    Anunciando Plastic SCM Community Edition

    Ha pasado casi 1 mes desde que hicimos el anuncio oficial de Plastic SCM Community Edition en nuestro blog en inglés.

    Aunque somos una empresa española nuestra audiencia y nuestros usuarios son la mayoría de fuera y de ahí que siempre publiquemos primero en inglés.

    Pero me parece que no viene mal incluir, aunque sea con un poco de retraso, la noticia del lanzamiento aquí.

    El objetivo de Plastic SCM Community Edition es llegar a un número elevado de equipos de desarrollo pequeños y medianos (de ahí lo de hasta 15 usuarios de la licencia gratuita). Plastic es un sistema SCM de última generación (distribuido, con muy buen soporte de ramas, etc, etc) y nuestro objetivo con esta iniciativa es llegar a muchos equipos pequeños (que son mayoría en todo el mundo) dentro de empresas. ¿Por qué esto de "dentro de empresas"? Pues porque para proyectos open source, a pesar de que Plastic es ilimitado y gratis para ellos, ya hay alternativas excelentes como Git y Mercurial que han nacido en el entorno OSS y que están pensados para ese tipo de proyectos. Sin embargo Plastic ha sido diseñado y desarrollado para empresas. ¿Cuál es la diferencia? Pues (generalizando) que características como la seguridad basada en ACLs, integraciones nativas con los IDEs, almacenar los datos en bases de datos relacionales estándar (a elegir: Firebird, MySQL, SQL Server, Oracle e incluso SQLite) y por supuesto nuestra cuidada interfaz gráfica han sido una prioridad para nosotros y algo que sabemos que los desarrolladores valoran cuando buscan un sistema para su trabajo. La propia gestión de ramas (inmutables y persistentes en Plastic contra mutables y un potencialmente volátiles en Git, por ejemplo) está más orientada al uso en empresas.

    Normalmente las empresas buscan herramientas que sean fáciles de poner en marcha, que tengan soporte comercial de primer nivel, que no les den muchos quebraderos de cabeza... y eso es lo que ofrecemos con Plastic para todo tipo de empresas y con CE para las más pequeñas.

    Además consideramos que la situación económica actual fuerza a muchos equipos a no gastar dinero en software, de ahí también la iniciativa: facilitar y universalizar las mejores prácticas de SCM.

    Plastic evoluciona muy rápido y podéis estar al día de todo lo que hacemos a través de twitter (@plasticscm).

    Espero que nos ayudéis a extender el mensaje!