Mostrando las entradas con la etiqueta DIY. Mostrar todas las entradas
Mostrando las entradas con la etiqueta DIY. Mostrar todas las entradas

16/07/2022

Guorkshop Go 1. Organización del código. Estructura de proyectos, módulos y paquetes

Si va a escribir un programa muy simple, en un único archivo, y no espera reusar el código, entonces no se preocupe de la organización de su proyecto y escriba todo su código en un único archivo fuente. Pero si esta trabajando en resolver un problema del mundo real, entonces hay una gran posibilidad de que necesite diseñar su proyecto de forma de poder reusar la mayor cantidad de código posible. Si este último es su caso, entonces preocupese.

Workshop. Fotografía por Daniel Mee a través de Flickr. Licencia CreativeCommons

Este es el primero de los prometidos guorkshops. Puede encontrar el guorkshop 0 aquí. Puede encontrar los otros guorkshops aca.

Si bien nadie le obliga a seguir o usar una forma de estructurar su proyecto, y ciertamente, si su proyecto es simple, o una prueba de conceptos, la estructura que presentaremos en este workshop puede ser innecesaria y un único archivo main.go donde escribir su código basta y sobra. Solo tenga presente que a medida que su código crece es importante que esté bien estructurado, de lo contrario corre el riesgo de terminar con un desorden de proporciones, con dependencias ocultas, estado global y otros malos olores.

Go nos provee con dos formas principales de organizar el código, módulos y paquetes.

Módulos

Los módulos de Go contienen uno o mas paquetes almacenados en una estructura de directorio y nos permiten entre otras cosas controlar las versiones de los paquetes que contiene, y con esto compartir o usar las funcionalidades de sus componentes.

Los módulos de Go tienen en su directorio raíz dos archivos especiales; go.mod y go.sum, donde el archivo go.mod define la ruta del modulo, indica la versión de Go con la que el módulo trabaja, y declara los paquetes de los que depende.

El archivo go.sum es generado automáticamente por Go cuando empezamos a agregar dependencias Contiene el checksum de las dependencias del módulo para determinar que estas no hayan sido modificadas y nosotros no deberiamos modificarlo manualmente.

Con ciertos reparos, podríamos decir que cada vez que vaya a empezar un nuevo proyecto de Go debería crear un módulo.

Para crear un módulo de Go solo tenemos que crear un directorio que será la raíz del proyecto, y usar go mod init nombre_del_modulo.

$ mkdir mi_modulo
$ cd mi_modulo
$ go mod init mi_modulo

Se considera buena practica que el nombre del módulo contenga su ruta de importación para que pueda compartirse usando las herramientas de Go. Esta ruta de importación es la ruta que Go usa para importar desde otros los paquetes contenidos en el módulo.

La especificación de Go indica sobre la ruta de importación:

La ruta de importación es el nombre canónico de un módulo, declarado con la directiva de módulo en el archivo go.mod. La ruta de un módulo es el prefijo para importar los paquetes que contiene.

Se ha vuelto práctica de la comunidad de desarrolladores el usar la url del repositorio que contiene el módulo, incluyendo el username del autor si se tratara de un repositorio como los de github, con la forma host/usuario/repositorio. Por ejemplo github.com/profe-ajedrez/my-awesome-module corresponde al módulo my-awesome-module del usuario profe-ajedrez, alojado en github.com. Otra convención muy usada es la forma dominio organizacion/nombre del modulo, por ejemplo calcutarasterware.com/a-pandaric-module.

Ejemplo:

Crearemos un módulo llamado mi_modulo y lo esperamos alojar en github en el repositorio del mismo nombre. Usaré mi usuario de github para este ejercicio.

$ mkdir mi_modulo
$ cd mi_modulo
$ go mod init github.com/profe-ajedrez/mi_modulo

El comando go mod init github.com/profe-ajedrez/mi_modulo crea al módulo en nuestro directorio local con el nombre github.com/profe-ajedrez/mi_modulo, note que aún no hemos creado ningún repositorio en github, generando al archivo go.mod, el cual contiene la ruta de importación del módulo y la versión de Go que usa nuestro proyecto.

# cat go.mod
module github.com/profe-ajedrez/mi_modulo

go 1.18

Dandole estructura a nuestro módulo

La comunidad de desarrolladores de Go ha probado con distintas aproximaciones a la hora de organizar el código de los proyectos, y si bien existen varias formas de lograr esta organización, creemos que la mas extendida es la siguiente, que si bien no es un estándar oficial definido por el equipo de desarrolladores de Go, es un conjunto de patrones históricos en el ecosistema del lenguaje.

directorio raíz del proyecto o módulo/
  cmd/
  internal/
  pkg/

  go.mod
  go.sum

  • El subdirectorio cmd/ contiene los paquetes main que son los puntos de entrada de la aplicación, pudiendo haber varios de ellos, cada uno en su propio subdirectorio cuyo nombre es el mismo que el del binario que generaran.
  • El subdirectorio internal/ contiene el código privado del módulo, es decir, los paquetes que se encuentren en este directorio no se podrán importar desde otros módulos, pero si pueden ser usados en el módulo actual.
  • El subdirectorio pkg/ contiene los paquetes que si serán importables desde otros módulos.

Paquetes

Los paquetes contienen archivos fuente y otros paquetes, y se usan para organizar código Go mejorando su legibilidad y reusabilidad, encapsulando el código de los archivos fuente que se encuentran en un mismo directorio.

Los paquetes corresponen a directorios que contienen archivos fuente y otros paquetes, y se usan para organizar código Go logrando, si se usan bien, mejorar su legibilidad y reusabilidad. Esto lo hacen encapsulando el código de los archivos fuente que se encuentran en un mismo directorio. Por lo tanto, todos loas archivos fuentes que se encuentren ene l mismo directorio deben pertenecer al miosmo paquete, en caso contrario ni siquiera podremos compilar nuestro código.

Remarcamos encapsulando debido a que en Go el paquete es la unidad de encapsulación en oposición a la clase que ofrecen otros lenguajes.

En Go, encontramos dos tipos de paquetes:

1 El paquete main que se usa para generar el ejecutable. Es responsable de contener a la función main que indica el punto de entrada a la aplicación.

// main.go
package main

import (
	"fmt"
)


func main() {
	fmt.Println("Hola Go")
}

2 El paquete orientado a reusar código, o paquete de librería que contiene código que será reusado.

// recepcion/recepcion.go
package recepcion

import (
	"fmt"
)


func Recibir() {
	fmt.Println("Recibiendo")
}

Podemos ver que los archivos fuente de Go empiezan con una línea indicando el paquete al que pertenece. Todo código Go debe pertenecer a uno, siendo nombrado generalmente con el mismo nombre que el del directorio que lo aloja.

El código dentro de un paquete puede referir a cualquier elemento (variables, constantes, funciones y otros tipos de dato) definido dentro de el, mientras que código de otros paquetes solo puede referir a los elementos que hayan sido exportados. Esta referencia siempre incluye el nombre el paquete como un prefijo; puertas.Abrir() refiere a función exportada Abrir del paquete puertas.

Effective Go recomienda que los nombres de paquete sean cortos, concisos y evocativos, y presenta la convención de que los nombres de paquetes sean palabras únicas en minúscula, sin subrayados o mixedCap.

Otra convención es que el paquete tenga el mismo nombre que su directorio fuente.


Gracias por aguantar hasta este punto. ¡Ahora ensuciemonos las manos!

Workshop Hora 1

Para realizar este workshop debe tener Go instalado, usar la terminal de su sistema y estar ubicado en algún directorio de trabajo.

1 En su terminal cree una nuevo directorio para el módulo con el nombre workshop_1
2 Acceda a la nueva carpeta
3 Cree un módulo de nombre workshop_1
4 Dentro del módulo cree la estructura de directorios presentada arriba
5 Abra el directorio con una instancia de su editor de texto favorito
6 Dentro del directorio internal cree el directorio xmath
7 En internal/xmath/ cree el archivo fuente xmathsourcefile.go
8 En el archivo internal/xmath/xmathsourcefile.go agregue el siguiente fragmento de código
package xmath

func SubstractInt(a int, b int) int {
  return a - b
}

9 En el directorio pkg cree el directorio xmathclient
10 En el directorio pkg/xmathclient/ cree el archivo xmathclientsourcefile.go
11 En el archivo pkg/xmathclient/xmathclientsourcefile.go agregue el siguiente fragmento de código
package xmathclient

import (
	"fmt"
	"workshop_1/internal/xmath"   // ¡Esto es importante! Note como se importa el paquete xmath
)

func Client() {
	fmt.Println(xmath.SubstractInt(10, 5))
}

Observe como se importa al paquete xmath. ¿Recuerda cuando comentamos sobre la ruta de importación del módulo? Pues se trataba de esto, la ruta de importación del módulo es la raíz de donde parte la ruta para encontrar los paquetes que importamos. Note que la ruta de importación del paquete xmath, incluye al directorio internal

12 En el directorio raíz del módulo, cree el archivo main.go y agreguele el siguiente código
package main

import "workshop_1/pkg/xmathclient" // Note como desde main importamos al paquete xmathclient

func main() {
	xmathclient.Client()
}

¿Vio como desde main.go importamos al paquete xmathclient? ¡Exacto! a través de la ruta de importación del módulo pasando por el directorio pkg que lo aloja.

13 En el directorio raíz del módulo, en la terminal ejecute el programa con go run main.go. Debería obtener la salida 5
  • ¿Que hemos hecho?

Hemos creado un módulo Go llamado mi_modulo, en el hemos creado la estructura de directorios propuesta para proyectos Go. En el directorio internal, creamos el directorio/paquete xmath, y en el directorio pkg creamos el directorio/paquete xmathclient. Finalmente creamos el archivo main.go en la raíz del directorio y lo ejecutamos para ver la salida del programa.

Muy bien, ahora rompamos algunos huevos y agreguemos un pequeño error que resolveremos posteriormente.

14 Modifique el archivo internal/xmath/xmathsourcefile.go para que se vea como el siguiente código
package xmath

func SubstractInt(a int, b int) int {
  return a - b
}

func addInt(a int, b int) int {
  return a + b
}

15 Modifique el archivo pkg/xmathclient/xmathclientsourcefile.go de la siguiente manera
package xmathclient

import (
	"fmt"
	"workshop_1/internal/xmath"
)

func Client() {
	fmt.Println(xmath.SubstractInt(10, 5))
	fmt.Println(xmath.addInt(10, 5))
}


16 Ejecute al programa en la terminal, en el directorio raíz del módulo con go run main.go. Debería ver el mensaje undefined: xmath.addInt

Esto ocurre debido a que el nombre de la función addInt del paquete xmath empieza con una letra minúscula, lo que le indica al compilador que es una función privada del paquete, esto es, solo puede accederse a ella desde dentro del paquete donde fue declarada. Código alojado en otros paquetes no podrá acceder a ella.

15 Repare el error para obtener en consola la salida Cambiando la inicial de la función addInt por una letra mayúscula, en su declaración y en su llamada.

Una vez corregido el problema, al ejecutar el programa debería obtener la siguiente salida:

5
15

En este punto ya debería tener un módulo de Go funcionando correctamente y haber entendido la forma de importar y usar paquetes.

Debe recordar
  • Los módulos almacenan paquetes y nos permiten versionar nuestro código
  • Paquetes encapsulan nuestro código Go y definen ámbito
  • El paquete main indica cual archivo será convertido en ejecutable
  • import permite usar funcionalidad de un paquete en otros paquetes
  • Para exportar un identificador debemos iniciar su nombre con una letra mayúscula

Los Guorkshops de Go del Programador Pobre

Pues la cosa detrás de estos guorkshops es que sean un grupo de artículos donde podamos ensuciarnos las manos trabajando en algunos conceptos e ideas que tengo dando vueltas hace rato en la cabeza sobre el lenguaje Go. Si tuviera que poner un objetivo concreto, sería el repasar las caracteristicas principales de Go aprendiendo buenas prácticas, haciendo cosas y usando un leguaje coloquial que permita presentar contenidos sin tanto término rimbombante. En pocas pálabras, Go al hueso (aunque suene gracioso!).

Workshop. Fotografía por Daniel Mee a través de Flickr. Licencia CreativeCommons

Los llamo guorkshops, con la palabra en Inglés mal escrita intentando darle un toque artesanal y DIY, y también para no tomarme demasiado en serio y permanecer siempre en el lado más humilde, pues estos guorkshop per se tienen que ser opinionados, en el sentido de que a través de la experiencia personal y de la comunidad presenta prácticas que se consideran correctas las cuales pueden ir cambiando con el correr del tiempo.

La metodología que uso es incremental y repetitiva a propósito, pues habiendo sido varios años profesor de ajedréz, es la que me ha dado mejores resultados, entregando ídeas y habilidades de forma acumulativa. Cosas que podrían parecer errores en un workshop, son usadas para ejemplificar una ídea específica de este y son corregidas en los siguientes junto con un comentario explicativo del error o mala práctica que ejemplifica.

Sin perjuicio de lo anterior, aunque a veces no lo parezca, soy un ser humano. Me reservo el derecho a equivocarme.

Cabe señalar que cada vez me vuelvo un mas firme creyente del Manifiesto, y creo que lo notará en los guorkshops.

Requisitos previos

Go instalado

Dirijase a https://go.dev/doc/install e instale la última versión estable del lenguaje correspondiente a su sistema operativo siguiendo las instrucciones que el sitio le ofrece.
Si usa Linux, recomiendo instalar Go manualmente y no usar al manejador de paquetes de su distribución o utilidades como Snap, para garantizar el uso de la última versión estable del lenguaje.

Tour de Go

Go es un lenguaje muy sencillo de aprender, pero como todo lo que vale la pena, es díficil lograr maestría con el. El primer paso para su dominio debería siempre ser el Tour de Go que enseña de manera interactiva los aspectos básicos del lenguaje.

En estos workshops, asumimos que ya ha completado el tour de Go. Si aún no lo ha hecho completelo y luego regrese.

Uso de terminal

En estos workshops asumimos que tiene un manejo básico de la terminal y los comando de su sistema operativo. Basta con que sepa abrír una línea de comandos, navegar a través de directorios, listar archivos y crear subdirectorios.

Herramientas

IDES

La wiki oficial de Go tiene una pagina dedicada a presentar y configurar ides para hacer más eficiente el desarrollo con este lenguaje. Ud puede usar el de su preferencia, pero los ejemplos de este workshop serán escritos en Visual Studio Code usando el plugin oficial

Toolset

Go viene con una serie de herramientas para ayudar a los desarrolladores a ser productivos. Estas pueden llamarse desde la línea de comandos o integrarse con su ide favorito (Esto lo hace el plugin oficial de Visual Studio Code. por ejemplo) Aún así, no está de más conocerlas y saberlas usar desde la terminal.

Puede obtener en su terminal esta lista de herramientas con:

$ go tool

El toolset de Go es muy completo y tiene muchas otras herramientas. Puede verlas en su pagina de documentación oficial


Enlaces directos a los guorkshops

13/03/2022

Lavaplatos DIY


Este 2022 hice realidad un viejo sueño y me vine a vivir al campo. Escapar de la ciudad era una idea que acariciabamos hace mucho tiempo con mi bruja y finalmente pudimos hacerla realidad, pero eso será material para otra historia

Si bien la casa aún está en construcción, los restos de materiales de la obra se van acumulando con el paso de los días. Mucho del volumen de estos restos usados corresponden a trozos de madera de diferentes dimensiones, y llevo algún tiempo pensando en que hacer con ellos. Por la zona, es común usar los palos sobrantes como leña, pero yo tenía algunos otros usos en mente.

Como este resbalín que le hice a mi hija con sobras 



El segundo proyecto fue un mueble base de lavaplatos. Esto debido a que están muy caros y opino que la melamina no es durable ni tampoco un material muy noble. Yo quería algo con un toque tradicional, pero que fuera práctico y usable, y por sobre todo que pudiera hacer reutilizando materiales sobrantes.

Materiales

  • 8 tablas de 90cm de largo que al estar juntas una junto a otra sumen 48 cm de ancho para los dos laterales del mueble. Tuve que cepillar el borde de una de ellas en cada lateral para alcanzar esta medida. Si puede, intente usar tablas de 1x5 pulgadas para tener menos trabajo. Tenga en cuenta que si bien las tablas se comercializan en dimensiones indicadas en pulgadas, si compra una tabla cepillada de 5 pulgadas será mas angosta que una table en bruto del mismo tamaño, esto debido a que la medida se calcula a partir de la tabla en bruto y el cepillado remueve material.
  • 4 tablas de 1x3 pulgadas de 48 cm, a los que hay que cortar en cada extremo 1 pulgada. Estas serán usadas como tablas de soporte contra las cuales apernar las tablas que formarán los laterales. Estas se pueden reesplazar por pletinas de fierro de 2mm de grosos de 2cm de ancho x 44 cm de largo
  • 8 tablas de 1x4 pulgadas de 114.5 cm. Estas se convertiran en los largueros que unen los laterales y en el piso del mueble
  • 16 pernos coches pavonados con golilla y tuerca Estos serán usados para armar los letrales contra las tablas de soporte
  • 50 tornillos soberbios de 3/16 x 2 pulgadas

Herramientas

  • Taladro eléctrico inalámbríco
  • Cepillo eléctrico (Podría usarse un cepillo manual, pero es un trabajo que te encargo)
  • Lijadora eléctrica. Idealmente de banda, una orbital funcionaría muy bien también. Yo me vi obligado a usar un accesorio para taladro que es un poco díficil de usar, pero igual me dió buenos resultados
  • Martillo
  • Serrucho
  • Atornilladores de punta phillips para apretar los soberbios, y de paleta para empujar y soltar las tablas
  • Llave inglesa para apretar las tuercas de los pernos coche. También sirve una llave punta corona del tamaño adecuado, o hasta un alicate

Busqué las medidas estandares de este tipo de muebles y decidí hacer uno de 120x90x50 (largo, alto, fondo) cuya construcción comento a continuación.



De la pila de maderas sobrantes, elegí las que estabán en mejor estado 

 


Cepille y pulí concienzudamente las maderas elegidas. Esta fue la parte más pesada de esta aventura



Hice los laterales del mueble cortando 4 maderos de 90 cm de largo y uniendolos con otro madero cruzado, apernandolos con pernos coche con golilla y tuerca de 1/4 pulgada de calibre y 2.5 pulgadas de largo. Estos dan un toque rustico y a la vez firmeza y soporte a la estructura.



De esa manera forme los laterales con dimensiones de 90 cm de alto por 48 cm de ancho.




Posteriormente, corté una pulgada de madera a cada lado del madero de soporte, para encajar en ellos un madero de 114.5cm a guisa de larguero, con el fin de dar forma y soporte al mueble. Notese que esta maniobra la hice a serrucho limpio





Había construido antes una sencilla banquita de madera en bruto para poder trabajar comodamente. En ella fui uniendo los largueros a los laterales usando tornillos soberbios, que son los usados en mueblería.



La ventaja de los tornillos soberbios es que apretan mas que los tornillos de madera, por eso son muy usados en mueblería, sobre todo en el armado de muebles de tableros aglomerado y terciados.


Ademas es posible ocultar sus cabezas usando tapas plasticas



Finalmente, corté, cepillé y presenté las tablas que formarían el piso del lavaplatos. Con esto el mueble está casi listo


Terminé dandole una nueva pulida con la lijadora al mueble y presentando la cubierta de acero inoxidable para asegurarme de que las medidas estuvieran correctas




Como pueden ver, todo quedó muy bien. Aún me falta construir las puertas, pero como estas tienen una complejidad mayor, las haré otro día. También me falta aplicar aceite de linaza y barniz, lo cual haré una vez tenga construidas las puertas.

A modo de comentario y conclusión, si tiene interés en realizar un proyecto diy, como este o parecido, le recomiendo que pase algún tiempo diseñandolo en papel, que calcule lo más ajustadamente posible las medidas y piense con anticipación en los materiales y técnicas que usará. En mi caso, originalmente tenía pensado unir las maderas usando una pletina de fierro de 2mm, pero no encontré ningún lugar donde me las vendieran con el largo que necesitaba (44cm) pues normalmente las comercializan en tiras de 6 metros, y lamentablemente por el momento no cuento con un esmeril angular para cortarlas (y cortarlas con sierra de mano es muchisisimo trabajo)

Si necesita hacer uniones invisibles puede hacer las uniones con tarugos de madera y cola fria, o buscar sistema de sujeción especializados como los agarres que se insertan en las paredes del mueble y apretan el tornillo a ser girados

Como última recomendación, hagase un favor y use una sierra eléctrica con un disco de precisión, de al menos 60 dientes. Yo me ví obligado a usar serrucho manual por haber prestado mi sierra eléctrica.