12 enero 2016

Functional Python Programming

Siempre quise saber de qué iba eso de la programación funcional, pero no me apetecía aprender un nuevo lenguaje para comprenderlo, al menos no por ahora. Por eso, cuando encontré un libro que trataba el tema desde el punto de vista de Python (Functional Python Programming de Steven Lott), no dudé en leérmelo.

Tras su lectura me di cuenta de que he estado usando un montón de principios de programación funcional sin ni siquiera saberlo: utilizar funciones cortas, no alterar estados externos desde el interior de las funciones, usar iteradores donde fuera posible, etc. Eso no significa que no aprendiese nada, por ejemplo me gustó bastante la parte que describía las posibilidades de la librería itertools, la cual no había utilizado hasta el momento.

También es cierto que incluye algunos consejos que no voy a seguir, como el de encadenar funciones. Al libro le gusta mucho el encadenamiento de funcione (pasar la llamada a una función como parámetro a otra), pero al hacerlo se crean líneas de código extremadamente largas y difíciles de leer que me parecen poco "pythonicas". Además, al libro le gusta mucho la recursión y ese es un concepto con el que no me siento cómodo y tampoco es que entendiese muy bien los ejemplos que aparecían en el libro sobre tail-optimization.

Con todo el libro es extenso, sistemático e incluye un montón de ejemplos por lo que creo que merece la pena leerlo aunque sea para quedarse con conceptos sueltos útiles para mejorar globalmente nuestro estilo de programación.

26 diciembre 2015

Manteniendo sicronizado un fork de Github con respecto al repositorio original

Estupendo, has solicitado tu primer pull request y te lo han aceptado junto con algunos otros pull requests de otros  desarrolladores, o puede ser que todavía estes trabajando en tu propia versión pero la original esté recibiendo actualizaciones que te convenga tener en tu fork. En ambos casos lo que te interesará es importar todos los commits recibidos por el fork original en el tuyo.

Borrar tu fork y reclonar el original no es una solución porque podrías tener código inacabado que perderías si borrases tu repositorio. Trabajar de esa manera es ineficiente y tendente a errores.


Hay otra manera mucho mejor que esa pero para ser sincero no es evidente si se mira el interfaz web de Github. El truco es importar los commits del repositorio original en la copia local de nuestro fork y acto seguido hacer un merge de los cambios en local para luego subirlo todo a Github con un push.

A primera vista podría parecer excesivamente complicado pero tiene sentido si consideramos nuestro repositorio de Github como el lugar donde debemos dejar nuestros cambios definitivos mientras que dejamos nuestra copia local como el lugar donde cacharrear.


Como dije antes, para hacerlo así no he encontrado ninguna manera evidente a través del interfaz web de Github. Incluso Pycharm carece de una de la de las funcionalidades que necesitamos para hacer todo el proceso a través del GUI, por lo cual tendremos que recurrir a la consola en algún paso. Por suerte todo el asunto se resuelve con sólo unos pocos comandos.

El primer paso supone añadir el repositorio original de Github como una fuente remota de nuestro repositorio local. Voy a mostrar cómo hacerlo usando mi fork de vdist. Este paso es precisamente el que no podemos hacer visualmente a través del GUI de Pycharm. Para ver qué fuentes tenemos en nuestro repositorio de Git tendremos que teclear el siguiente comando:

dante@Camelot:~/vdist$ git remote -v origin https://github.com/dante-signal31/vdist.git (fetch) origin https://github.com/dante-signal31/vdist.git (push)


Como se puede ver, llamo origin a mi fork en Github. Ahora vamos a añadir el repositorio original a mis fuentes de git. Digamos que queremos llamar upstream al repositorio original:

dante@Camelot:~/vdist$ git remote add upstream https://github.com/objectified/vdist.git dante@Camelot:~/vdist$ git remote -v origin https://github.com/dante-signal31/vdist.git (fetch) origin https://github.com/dante-signal31/vdist.git (push) upstream https://github.com/objectified/vdist.git (fetch) upstream https://github.com/objectified/vdist.git (push)

Se puede ver que el repositorio original se encuentra ahora entre las fuentes de mi repositorio local de git.

Para descargar cualquier cambio en el repositorio original sin aplicarlo en el repositorio local debemos usar el comando git fetch:

dante@Camelot:~/vdist$ git fetch upstream remote: Counting objects: 1, done. remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 1 De https://github.com/objectified/vdist * [new branch] master -> upstream/master

Se puede hacer este último paso desde el GUI de Pycharm usando la entrada de menu: "VCS-> Git-> Fetch".

Los cambios descargados se guardan por defecto en la rama upstream/master. Una vez revisados los cambios, y si se está de acuerdo con ellos, se pueden aplicar a la rama master local haciendo:

dante@Camelot:~/vdist$ git checkout master Switched to branch 'master' dante@Camelot:~/vdist$ git merge upstream/master


Con lo anterior la rama master local y la del repositorio original quedarán sincronizados.  Ahora, lo que quedaría por hacer es actualizar nuestro repositorio de Github con un push:

dante@Camelot:~/vdist$ git push origin master


La buena noticia es que sólo hay que añadir una vez el repositorio original a nuestras fuentes de git, tras lo cual se puede usar git como hasta el momento, incluso a través del interfaz de Pycharm, ya que este último detecta las nuevas ramas remotas en cuanto hacemos un fetch desde su menú.