sábado, junio 03, 2023

Mis primeros 6 meses en una startup Cloud Native

Desde el 2 de enero de este año me encuentro trabajando en una startup cloud native y por ahora estoy mas que feliz. Muchos de mis colegas me comentaban lo negativo de trabajar en una startup y la verdad que hasta el momento no he visto nada de negativo. 

En una startup tienes la oportunidad de hacer todo y aprender de todo dado que al estar arrancando puedes hacer cosas que en una empresa grande ya tienen gente o roles definidos para esas tareas. En particular cumplo el rol de arquitecto y por lo general como arquitecto tienes los conocimientos teóricos como para diseñar aplicaciones pero muy pocas veces puedes realmente llevarlos a la práctica.  

En mi caso me gusta mucho experimentar y estar cerca de las soluciones que diseño, con esto me refiero a poder programar y si es necesario formar parte del equipo que la pone en producción. En mi actual puesto tengo la suerte de poder programar bastante usando Go como lenguaje principal y desplegar nuestras soluciones sobre AWS.

Hace 5 meses solo conocía la teoría de AWS para poder discutir de implementaciones en la nube pero ahora al tener la suerte de trabajar para una startup puedo hacer las implementaciones directamente tocando yo mismo los diferentes servicios en la nube.

Lo bueno de esto es que pude aprender a fondo muchos de los servicios que nos propusimos usar en una solución con una arquitectura orientada a eventos que tuvimos que implementar.  A continuación les muestro una imagen de la consola de AWS con los servicios que use recientemente


Como se puede ver en este tiempo tuve la oportunidad de aprender y poner en práctica mucho de lo que solo sabía en la teoría gracias a trabajar en una pequeña startup. Les recomiendo experimentar y si te gusta estar cerca de la parte técnica y no aburrirte en una empresa grande busques alguna startup que sin dudas vas a poder aprender mucho más rápido que en una empresa grande. Te lo digo por experiencia ya que tuve la suerte de trabajar en empresas de todos los tamaños y me di cuenta que en las pequeñas o startup es donde más se aprende.


miércoles, mayo 31, 2023

A tour of Go

 A tour of Go es un pequeño recorrido por las características del lenguaje. La verdad que es muy recomendable si estas iniciando en go o si quieres tener las básicas del mismo. Tengo que admitir que no le di mucha importancia cuando comencé con esto pero me hubiera ahorrado muchos dolores de cabeza si lo hubiera seguido desde mis inicios en Go.



martes, mayo 23, 2023

Echo de menos a GeneXus

 La última semana me ha pasado que extrañe el uso de GeneXus. Extraño la época en que mi tiempo de desarrollo era 100% en GeneXus independientemente del lenguaje para el que estuviera generando. Lo bueno de GeneXus es que puedes generar para varios lenguajes usando la misma base de conocimiento, eso hace que te puedas especializar en la herramientas sin tener que aprender varios lenguajes. 

En la actualidad el 90% de mi desarrollo lo hago utilizando Go, un 5% Java y el restante en Python. Al tener varios microservicios me pasa que en ocasiones tengo que tocar o manejar tres lenguajes cuando antes todo lo resolvía con GeneXus. Entiendo que hay cosas que se pueden lograr con Go que con GeneXus no eran posibles pero siempre le encontrábamos la vuelta. 

Espero en algún momento volver a trabajar con GeneXus ya que cada día que pasa lo hecho de menos.




viernes, marzo 31, 2023

Git Large File Storage

 El día de hoy  por primera vez desde que uso git tuve un problema al querer subir archivos grandes a github. Contexto: tengo un modelo entrenado con extensión pkl el cual pesa algo así como 280 MB, cuando quise subirlo a mi repositorio me dio el siguiente error:


remote: error: Trace: a30bc8551829cfe15407cd6a30fdf32fa02d500188c7d36f07e868f79f85f1ba
remote: error: See https://gh.io/lfs for more information.
remote: error: File modelacionrename.pkl is 278.13 MB; this exceeds GitHub's file size limit of 100.00 MB
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
To github.com:bullkservices/api-predictions.git
! [remote rejected] develop -> develop (pre-receive hook declined)
error: failed to push some refs to 'github.com:bullkservices/api-predictions.git'

Siguiendo el mensaje de error conocí la existencia de git-lfs, básicamente es un proyecto que nos permite almacenar archivos grandes en nuestros repositorios.

Seguí los pasos de la documentación pero mi error seguía sucediendo, investigando un poco me di cuenta que hay que seguir los pasos en orden. 

En mi caso lo que hice fue lo siguiente:

a) Descargar nuevamente mi repositorio

b) Ejecute el comando: git lfs install

c) Habilite el seguimiento de archivos grandes con extensión pkl: git lfs track "*.pkl"

d) En el paso anterior se creo automáticamente el archivo .gitattributes por lo que hice el git add . y commit

e) Agregue el archivo del modelo prediccion.pkl al repo, luego hice push con los cambios

Luego de hacer los pasos en orden pude subir mi archivo grande al repositorio.




miércoles, marzo 22, 2023

Error "cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATH" al hacer Build Image

Tengo una aplicación desarrollado en Go que usa una BD SQLite y al intentar crear mi imagen me da el siguiente error:

#10 0.467 cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATH

El dockerfile que estoy utilizando es el siguiente:

FROM golang:1.19-alpine

# Set destination for COPY
WORKDIR /app


# syntax=docker/dockerfile:1
FROM golang:1.19-alpine


RUN apk add curl


WORKDIR /go/src/app
COPY . .

RUN go get -d -v ./...
RUN go install -v ./...

RUN go build -o gestion
COPY start.sh .

ENTRYPOINT ["/bin/sh"]
HEALTHCHECK CMD curl --fail http://localhost:8080/healthcheck || exit 1
CMD ["start.sh"]

Luego de analizar y buscar en google me di cuenta que falta instalar build-base por lo que mi dockerfile queda de la siguiente manera:

FROM golang:1.19-alpine

# Set destination for COPY
WORKDIR /app


# syntax=docker/dockerfile:1
FROM golang:1.19-alpine


RUN apk add curl
RUN apk add build-base

WORKDIR /go/src/app
COPY . .

RUN go get -d -v ./...
RUN go install -v ./...

RUN go build -o gestion
COPY start.sh .

ENTRYPOINT ["/bin/sh"]
HEALTHCHECK CMD curl --fail http://localhost:8080/healthcheck || exit 1
CMD ["start.sh"]

Luego de indicar que instale build-base la imagen se crea de forma correcta.


lunes, marzo 20, 2023

GitHub Copilot (Go)

 Desde hace unas semanas en la StartUp que me encuentro trabajando surgió la idea de utilizar GitHub Copilot. La verdad que al principio no podía darme cuenta de como poder sacarle provecho a esta herramienta de AI.

Con el correr del tiempo me di cuenta que la herramienta analiza tu forma de programar y según el contexto de tu código le puedes sacar mas o menos provecho.  Lo bueno que esta herramienta te completo o sugiere el código que debes poner según el contexto de tu código.

En mi caso le pude sacar mucho provecho creando las pruebas unitarias ya que me proponía los test unitarios que me faltaban hacer o me los completaba.

Ejemplo:

Debía escribir prueba unitarias para encriptar y para desencriptar por lo que solo con el nombre que le puse a la func ya comenzó a proponerme código.  


func TestRsaEncrypt(t *testing.T) {
//GenerateKeyPair(2048)
pub, _, err := CreateKeys(2048)
if err != nil {
t.Error(err)
}
// encrypt
encrypted, err := RsaEncrypt([]byte("hello world"), []byte(pub.String()))
if err != nil {
t.Error(err)
}
assert.NotNil(t, encrypted)
}

Copilot detecto que quería realizar un test para hacer una encriptación RSA por lo que solo con nombrar la func el completo el código. En realidad solo escribí la primer línea y el resto me lo propuso. Hasta ahí me había sorprendido ya que me propuso el código de forma correcta pero mi sorpresa fue al hacer el unit test para el Decrypt.

func TestRsaDecrypt(t *testing.T) {
//GenerateKeyPair(2048)
pub, pri, err := CreateKeys(2048)
if err != nil {
t.Error(err)
}
// encrypt
encrypted, err := RsaEncrypt([]byte("hello world"), []byte(pub.String()))
if err != nil {
t.Error(err)
}
// decrypt
decrypted, err := RsaDecrypt(encrypted, []byte(pri.String()))
if err != nil {
t.Error(err)
}
assert.Equal(t, "hello world", string(decrypted))
}

Al poner el título de la función me propuso todo el código, solo con un error el cual tuve que corregir pero me ahorre de escribir mas de 15 líneas.


En síntesis:

La herramienta es muy potente, solo debemos ayudarla teniendo un buen código ya que toma como contexto el código de nuestro repo para proponer código siguiendo nuestra lógica. Es importante los comentarios y los nombres de las funciones o estructuras. Creo que este tipo de herramientas se están haciendo cada día mas populares y como desarrollador es importante que aprendamos a convivir con este tipo de ayuda dado que nos brinda la posibilidad de aumentar nuestra productividad.



lunes, enero 23, 2023

Mejor canal de youtube para aprender Golang

 Desde hace unos meses comencé a trabajar como Arquitecto de soluciones en una Startup Cloud Native que usa Golang para sus desarrollos. Lo interesante de esta propuesta es que mi experiencia esta basada en Java por lo que tuve que aprender Go rápidamente. Esto me llevo a investigar recursos de aprendizaje y existen miles de lugares para aprender. Por suerte me cruce con un canal de youtube que tiene un curso de golang que tiene en cuenta las buenas prácticas con ejemplos prácticos reales.

El curso se llama:  Golang Crash Course y la verdad que provee todo lo que necesitas para ser un experto en Go.

A pesar que había trabajado el año anterior con Go no tenía la experiencia necesaria hasta que pude encontrar este curso, realmente recomiendo este curso ya que cubre todo lo que necesitamos para crear aplicaciones profesionales en Goland. 


Happy code




sábado, diciembre 17, 2022

Estudiar MongoDB on-line

 Estuve revisando y búscando cursos hasta que me di cuenta que existe MongoDB University



En realidad existe la página https://learn.mongodb.com/ que tiene varios recursos para aprender sobre MongoDB, lo que estuve revisando y ya hice varios cursos es en la sección de "MongoDB University". En este lugar existen varios cursos gratis los cuales brindan un comprobante. También se puede hacer la certificación en línea la cual creo que tiene costo. 

En síntesis les comento que este recurso es super completo y van a poder encontrar mucha información para poder formarse en MongoDB.



jueves, diciembre 15, 2022

MongoDB 6.0

La última versión de MongoDB que había usado fue la 4x o algo por el estilo, ahora estoy en un proyecto que debo usar nuevamente Mongo y veo que la última versión es la 6.0x. En principio estoy investigando los cambios y lo primero que puedo decir es que descontinuarón el mongo shell legacy (mongo) a partir de la versión 5.0X. Tienen qu eestar atentos ya que ahora se debe instalar MongoDB Shell (mongosh) para trabajar en consola. 

Por ahora estoy sin mi equpo Linux por lo que voy a describir la instalación que hice en mi equipo Windows, los pasos para instalar son los siguientes:

a) Descargar versión para windows  de MongoDB Community Server
b) Descargar MongoDB Shell

En el proceso de instalación nos presenta pantallas como las siguientes:


En mi caso seleccione la opción completa:


Esta versión se puede instalar como servicio pero en mi equipo decidí no instalarlo como servicio para levantar el server a demanda.


También deje seleccionada la opción de instalar el MongoDB Compass (Herramienta Gráfica) que viene por defecto para poder probarla (prefiero trabajar en consola).

Una vez que finaliza la instalación tuve que agregar a la variable de ambiente "PATH" la ruta de Mongo para poder levantar el servidor por consola como me gusta.

Para levantar el server tengo que hacer lo siguiente:

C:\Users\uruli>mongod

Con este comando les levanta el server y en la consola van a poder visualizar algo similar a lo que muestra la siguiente imágen:



Para acceder al cliente alcanza con ejecutar en consola el comando: mongosh y presenta una pantalla como la se muestra en la siguiente imágen:




Una cosa que puede pasar es que si manejamos toda la instalación por defecto se debe crear la siguiente carpeta: "C:\data\db" de lo contrario el MongoDB server no levanta. Dado que estoy probando hice la creación de esas carpetas y todo funciona correctamente.













jueves, diciembre 01, 2022

tsc : The term 'tsc' is not recognized as the name of a cmdlet...

 Realizando un curso de typescript veo que me aparece el siguiente error:


La verdad que lo primero que hice fue ejecutar:

>npm install typescript --save

El error seguía por lo que búscando en google encontre que la forma de "fixear" esto era haciendo lo siguiente:

> npm install typescript@latest -g

Luego de hacer esto pude ejecutar tsc test.ts y se genero mi archivo test.js sin problemas.


viernes, noviembre 25, 2022

ng.ps1 cannot be loaded because running scripts is disabled on this system

 Seguramente si te topas con este mensaje de error al querer generar un componente en Angular se debe a que estas usando Windows :-)

En mi caso tengo el siguiente error:

> ng g c components/Saludo

ng : File C:\Users\uruli\AppData\Roaming\npm\ng.ps1 cannot be loaded because running scripts is disabled on 

this system. For more information, see about_Execution_Policies at 

https:/go.microsoft.com/fwlink/?LinkID=135170.

At line:1 char:1

+ ng g c components/Saludo

+ ~~

    + CategoryInfo          : SecurityError: (:) [], PSSecurityException

    + FullyQualifiedErrorId : UnauthorizedAccess

Esto se debe a que Windows por defecto tiene directivas para no permitir que scripts mal intencionados se ejecuten en tu equipo. Para poder ver estas directivas puedes hacer lo siguiente:

> Get-ExecutionPolicy -List que te dara una salida similar a esta:

La solución sencilla es ejecutar power-shell como administrador, de lo contrario si estas usando Windows te recomiendo cambiar la politica para CurrentUser, ejemplo:

$> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Luego de ejecutar este comando si ejecuto Get-ExecutionPolicy -List el resultado debería ser el siguiente:



Al realizar este cambio pude mi componente de forma satisfactoria:
$> ng g c components/Saludo
CREATE src/app/components/saludo/saludo.component.html (21 bytes)
CREATE src/app/components/saludo/saludo.component.spec.ts (599 bytes)
CREATE src/app/components/saludo/saludo.component.ts (202 bytes)
CREATE src/app/components/saludo/saludo.component.css (0 bytes)
UPDATE src/app/app.module.ts (487 bytes)



Fuente: Microsoft




Retomando con Angular

Desde hace un tiempo que no tocaba Angular en mi equipo por lo que me ha tocado actualizar la versión como muestra la siguiente imágen:


Vamos a ver como me va con esta verisón

miércoles, febrero 16, 2022

Upgrade macOS Monterey

 Desde hace tres meses me convertí  en usuario MAC, basicamente cambie de trabajo y me asignaron una MAC para trabajar. La verdad que el equipo vuela y hace poco tuve que ejecutar una actualización del SO llamada Monterey. 


En principio no tuve mayores problemas hasta que tuve que usar la terminal y me tope con el siguiente error a la hora de ejecutar diferentes comandos:

-bash: /usr/local/bin/fury: /Library/Developer/CommandLineTools/usr/bin/python3: bad interpreter: No such file or directory


La solución a este problema fue ejecutar el siguiente comando:


$ xcode-select --install



miércoles, agosto 26, 2020

Recuperar contraseña postgres 12 en Linux Mint

En mi equipo tengo instalado Linux Mint 20 y para un proyecto instale PostgreSQL, no lo use por un tiempo y ahora que quiero usarlo me pide contraseña para el usuario postgres. La verdad que no recuerdo haber puesto una contraseña y no encuentro cual es la contraseña por defecto. No soy un guru en este tema por lo que me puse a investigar como restablecer la contraseña, lo dejo aquí por si otro es igual de despistado que yo.

Esto lo hice de la siguiente manera:

Lo primero es editar el archivo pg_hba.conf y agregarle la siguiente línea:

host    all      postgres    127.0.0.1/32     trust


 


Luego de editar el archivo hay que reiniciar el servicio:

service postgresql restart

Luego de reiniciar el servicio pude entrar a cambiar la contraseña del postgres:

psql -h localhost -U postgres

ALTER USER postgres with password 'NuevaPassword';
\q

Después de cambiar el password edite el archivo pg_hba.conf, reinicie el servicio de postgresql nuevamente y pude verificar que efectivamente había podido cambiar la contraseña.




 

 

miércoles, julio 29, 2020

HAPI FHIR for Dummies (20200601)

Cuando estamos arrancando con HAPI FHIR una cosa que me ayudo mucho es que existe un servidor público de test. Para acceder al servidor público tengo que acceder a la siguiente url: http://hapi.fhir.org/


Este servidor de test fue muy útil al comienzo de mi investigación sobre HAPI FHIR.

HAPI FHIR for Dummies (20200701)

Si te encuentras en la etapa de aprender sobre HAPI FHIR aquí va un Tip de los mas básicos.
Cuando te encuentras frente a un servidor HAPI FHIR lo primero que debes hacer para saber que es lo que se encuentra disponible en ese servidor es acceder a su "metadata". Para hacer una prueba puedo acceder al servidor de test de hapi: http://hapi.fhir.org/baseR4/metadata




Ejemplo de la respuesta:


HTTP 200 OK
Response Headers
X-Powered-By: HAPI FHIR 5.1.0-SNAPSHOT REST Server (FHIR Server; FHIR 4.0.1/R4)
Content-Type: application/fhir+xml;charset=utf-8
X-Request-ID: NhDkIGO8AFlOSg6K
Response Body
{
"resourceType": "CapabilityStatement",
"status": "active",
"date": "2020-07-29T15:43:40+00:00",
"publisher": "Not provided",
"kind": "instance",
"software": {
"name": "HAPI FHIR Server",
"version": "5.1.0-SNAPSHOT"
},
"implementation": {
"description": "UHN Test Server (R4 Resources)",
"url": "http://hapi.fhir.org/baseR4"
},
"fhirVersion": "4.0.1",
"format": [ "application/fhir+xml", "application/fhir+json" ],
"rest": [ {
"extension": [ {
"url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-websocket",
"valueUri": "/websocketR4"
} ],
"mode": "server",
"resource": [ {
"extension": [ {
"url": "http://hl7api.sourceforge.net/hapi-fhir/res/extdefs.html#resourceCount",
"valueDecimal": 500
} ],
"type": "Account",
"profile": "http://hl7.org/fhir/StructureDefinition/Account",
"interaction": [ {
"code": "read"
}, {
"code": "vread"
}, {
"code": "update"
}, {
"code": "patch"
}, {
"code": "delete"
}, {
"code": "history-instance"
}, {
"code": "history-type"
}, {
"code": "create"
}, {
"code": "search-type"
} ],
"versioning": "versioned-update",
"conditionalCreate": true,
"conditionalUpdate": true,
"conditionalDelete": "multiple",
"searchInclude": [ "*", "Account:owner", "Account:patient", "Account:subject" ],
"searchParam": [ {
"name": "_language",
"type": "string",
"documentation": "The language of the resource"
}, {
"name": "owner",
"type": "reference",
"documentation": "Entity managing the Account"
}, {
"name": "identifier",
"type": "token",
"documentation": "Account number"
}, {
"name": "period",
"type": "date",
"documentation": "Transaction window"
}, {
"name": "patient",
"type": "reference",
"documentation": "The entity that caused the expenses"
}, {
"name": "subject",
"type": "reference",
"documentation": "The entity that caused the expenses"
}, {
"name": "SearchByMsgDate",
"type": "date",
"documentation": "Search by patient for a MSH.7 agreement, which is stored in Patient Resource"
}, {
"name": "name",
"type": "string",
"documentation": "Human-readable label"
}, {
"name": "_id",
"type": "token",
"documentation": "The ID of the resource"
}, {
"name": "type",
"type": "token",
"documentation": "E.g. patient, expense, depreciation"
}, {
"name": "status",
"type": "token",
"documentation": "active | inactive | entered-in-error | on-hold | unknown"
} ]
}, {
"extension": [ {
"url": "http://hl7api.sourceforge.net/hapi-fhir/res/extdefs.html#resourceCount",
"valueDecimal": 83
} ],
"type": "ActivityDefinition",
"profile": "http://hl7.org/fhir/StructureDefinition/ActivityDefinition",
"interaction": [ {
"code": "read"
}, {
"code": "vread"
}, {
"code": "update"
}, {
"code": "patch"
}, {
"code": "delete"
}, {
"code": "history-instance"
}, {
"code": "history-type"
}, {
"code": "create"
}, {
"code": "search-type"
} ],
"versioning": "versioned-update",
"conditionalCreate": true,
"conditionalUpdate": true,
"conditionalDelete": "multiple",
"searchInclude": [ "*", "ActivityDefinition:composed-of", "ActivityDefinition:depends-on",
"ActivityDefinition:derived-from", "ActivityDefinition:predecessor", "ActivityDefinition:successor" ],
"searchParam": [ {
"name": ....


La lista es muy extensa ya que es el servidor público de hapi pero seguramente el servidor que me encuentro desarrollando tenga una lista menor, por ejemplo mi servidor local tiene la siguiente lista:


http://localhost:7070/hapilocal/fhir/metadata


Al acceder a la "metadata" de mi implementación se muestra lo que tengo disponible hasta el momento.




HTTP 200 OK
Response Headers
X-Powered-By: HAPI FHIR 5.0.2 REST Server (FHIR Server; FHIR 1.0.2/DSTU2)
X-Request-ID: lbcIeZTv5EZMae6L
Response Body
{
"resourceType": "Conformance",
"publisher": "Not provided",
"date": "2020-07-29T12:04:08-03:00",
"kind": "instance",
"software": {
"name": "HAPI FHIR Server",
"version": "5.0.2"
},
"implementation": {
"description": "HAPI FHIR",
"url": "http://localhost:7070/hapilocal/fhir"
},
"fhirVersion": "1.0.2",
"acceptUnknown": "extensions",
"format": [ "application/xml+fhir", "application/json+fhir" ],
"rest": [ {
"mode": "server",
"resource": [ {
"type": "Location",
"profile": {
"reference": "http://hl7.org/fhir/profiles/Location"
},
"interaction": [ {
"code": "read"
}, {
"code": "vread"
}, {
"code": "update"
}, {
"code": "create"
}, {
"code": "search-type"
} ]
}, {
"type": "OperationDefinition",
"profile": {
"reference": "http://hl7.org/fhir/profiles/OperationDefinition"
},
"interaction": [ {
"code": "read"
} ]
}, {
"type": "Organization",
"profile": {
"reference": "http://hl7.org/fhir/profiles/Organization"
},
"interaction": [ {
"code": "read"
} ]
}, {
"type": "Patient",
"profile": {
"reference": "http://hl7.org/fhir/profiles/Patient"
},
"interaction": [ {
"code": "read"
}, {
"code": "vread"
}, {
"code": "update"
}, {
"code": "create"
}, {
"code": "search-type"
} ],
"searchParam": [ {
"name": "family",
"type": "string",
"documentation": "A portion of the family name of the patient"
} ]
}, {
"type": "Practitioner",
"profile": {
"reference": "http://hl7.org/fhir/profiles/Practitioner"
},
"interaction": [ {
"code": "read"
}, {
"code": "vread"
}, {
"code": "update"
}, {
"code": "create"
}, {
"code": "search-type"
} ],
"searchParam": [ {
"name": "family",
"type": "string",
"documentation": "A portion of the family name"
} ]
}, {
"type": "StructureDefinition",
"profile": {
"reference": "http://hl7.org/fhir/profiles/StructureDefinition"
},
"interaction": [ {
"code": "read"
}, {
"code": "search-type"
} ]
} ]
} ]
}
Wrote 2,4 KB (32,6 KB total including HTML) in estimated 16ms

martes, mayo 19, 2020

Actualizar versión de Git en Linux Mint

Estoy en un proyecto que necesito usar Git y me pidieron que usara una versión nueva pero en mi Linux Mint tenía la versión 2.7.4 como muestra la siguiente imagen:


A pesar de que podría haber trabajado con la versión actual seguí el consejo y actualice a la última versión estable de Git. Para hacer esto tuve que agregar un repositorio y actualizar la versión. Para esto tuve que ejecutar el siguiente comando:

cgomez@cgomez-urulinux ~ $ sudo add-apt-repository ppa:git-core/ppa

Luego de agregar el repositorio de git lo que hice fue actualizar git como muestra la siguiente imagen:




Después de actualizar me quedo actualizado Git



domingo, mayo 17, 2020

Hacer un procedimiento sin hacer Unit Test "Es una irresponsabilidad"

El título de este artículo lo tome de la charla que dio Gaston Milano en el GUG Montevideo, la misma se llama: "Gente, Ideas, Herramientas - Gaston Milano sobre App Coronavirus UY".

En la charla Gaston explica el proceso de desarrollo de la aplicación "Coronavirus UY", cuando se refiere al testing que se le hizo a la aplicación hace hincapié en los Unitt Test.  Sin dudas que esto es importante pero en ocasiones hay que lograr que los equipos y las organizaciones se encuentren maduros para sumar al proceso de desarrollo esta buena práctica.

Hace casi un año escribía algunos artículos sobre "Pruebas unitarias en GeneXus", no fue nada técnico pero conté un poco mi proceso para llegar a la necesidad de contar con Unit Test. Tuve un largo camino dado que primero debía lograr migrar a GeneXus 16 para lograr usar GXTest

Tuve que atravesar algunos problemas antes de poder llegar a implementar Unit Test con GeneXus pero luego de migrar la aplicación de GX9 a GX 15 y por último a GX16 pude llegar a comenzar a implementar mis primeros Unit Test.

En nuestra experiencia tuvimos algunos problemas que fuimos resolviendo pero que nos hicieron cambiar de parecer a la hora de hacer pruebas unitarias para cada procedimiento de nuestra KB. Los principales problemas que encontramos fueron los siguientes:

  • La KB creció considerablemente: por defecto se crean tres objetos (Unit Test, SDT y un Data Provider). 
  • Se necesita Licencia para usar GX-Server y para usar con integración continua
  • No es una práctica extendida dentro de los desarrolladores

En realidad el problema mas complejo de resolver es que los unit test no son una práctica extendida dentro de los desarrolladores genexus y esto hace que no se tenga apoyo para poder lograr recursos para usar GX-Test.

El problema del crecimiento de la kb se puede solucionar modificando los unit test en los casos que sea posible (En un próximo artículo voy a explicar como lo hacemos).

El licenciamiento se puede solucionar pero todavía no pude lograr que se vean los beneficios de esto para obtener los recursos necesarios (Estoy en proceso).

En resumen considero que debemos comenzar a utilizar las pruebas unitarias y extender esta práctica entre la comunidad genexus para poder enriquecer la herramienta, logrando que las organizaciones tengan esto como obligatorio.

El principal debe en la utilización de los unit test esta del lado de los desarrolladores que todavía no han integrado esto a su forma de trabajo y esto hace que en equipos grandes sea complejo implementar esta práctica.

En otro artículo voy a explicar como usamos los unit test en una KB grande que esta teniendo liberaciones de versiones a producción de forma mensual.







domingo, abril 12, 2020

Kotlin Bootcamp for Programmers

Dado que estoy por comenzar un proyecto para mobile estoy investigando Kotlin dado la importancia que esta tomando en el desarrollo para Android. Lo primero que hice fue instalar el Android Studio y ahora estoy investigando un poco Kotlin.
La verdad que estoy fascinado por la cantidad de recursos que tenemos disponibles para los desarrolladores, por ejemplo al entrar a la sección de Kotlin se encuentra disponible un curso en UDACITY totalmente gratis llamado "Kotlin Bootcamp for Programmers".
Aprovechando la cuarentena por el COVID-19 lo estoy siguiendo dado que no tenia ni idea de Kotlin.


Espero poder terminarlo para comenzar rápidamente a realizar alguna app, en principio voy a intentar comparar esto con lo que puedo hacer con el Generador Mobile de GeneXus.

Curso GeneXus for mobile

Este lunes comienzo el curso on-line de GeneXus Mobile en GX 16, el cual se esta dando por una iniciativa de GeneXus de poner disponible este curso a la comunidad.
Este curso siempre se encuentra on-line en modalidad auto-estudio pero en esta oportunidad se hizo una publicación en donde los interesados se anotaban para seguir el curso junto al equipo de capacitación de GeneXus.
La verdad que en versiones pasadas había realizado un acercamiento al generador Mobile pero nunca pude avanzar mucho por falta de tiempo, en esta oportunidad voy a sacarle el máximo provecho que pueda.
Lo poco que pude ver hasta el momento veo que se ha mejorado mucho en la ayuda para instalar el ambiente dado que ahora existe "Android Requirements Installer", esto facilita mucho la instalación cosa que antes era todo manual.


Hasta el momento solo configure el ambiente y estoy a la espera de comenzar este curso para poder implementar un proyecto que tengo en mente. Una aclaración es que si se instala la versión trial la parte de Android se instala sola, en mi caso voy a usar la versión que ya tengo por lo que tuve que instalar el ambiente para Android mediante el "Android Requirements Installer".