Cholo Programando

Cholo Programando Subo contenido relacionado con la programación, con un sabor un poco distinto 🌮

31/07/2022

Diferencia entre Eager Loading y Lazy Loading en ORMs.

Hace unos días en el trabajo me encontré con esta query que tardaba 1:30 minutos en ejecutarse. Como podrán imaginarse este tiempo, para traer una lista de 400 cursos, es una gran mi**da.

Descubrí por la mala que mi ORM por defecto hacía Lazy Loading. Lo que quiere decir que:

Cada Curso tiene un Estado, Nivel, Tipo y varias Tags. Con Lazy Loading lo que ocurre es que el ORM primero trae los Cursos y después, por cada Curso envia una query para traer su respectivo Estado, Nivel, Tipo y Tags. Obviamente, en 400 Cursos esto resulta en 400 * 4 solicitudes.

Esto es porque el Lazy Loading no es para que traigas todas las tablas asociadas (Estado, Nivel, Tipo, Tags) con tu tabla principal (Cursos). Si quieres hacer esto debes usar Eager Loading. Lo que hace es crear una sola query en la que solicita tu tabla principal y todas sus tablas asociadas (en el caso mío, solicita todos los Cursos y sus respectivos Estado, Nivel, Tipo y Tags).

Tras aplicar esta modificación conseguí que la query pase de 1:30 minutos a 5-9 segundos, lo que es una gran mejora. Pero sigue siendo lento para mí. Así que seguiré investigando donde mas se puede optimizar.

Lo que si es seguro, es que voy a agregar Redis (para cachear los resultados, y reducir aun mas los tiempos).

22/06/2022

Typescript: Como sobreponer interfaces y luego constrainearlas

Hace poco me paso que quería crear una función que aceptase un parametro que podía cumplir con una de dos interfaces (bastante similares, pero con unas propiedades que diferían).

Imaginemos la funcion Matar(PARAMETRO)

Queremos que el tipo de PARAMETRO sea lo suficientemente general para admitir el tipo Humano o Vaca.

Pero que nos de la flexibilidad de decidir dentro del metodo, que si en dicho objeto tenemos propiedades de una Vaca, se haga algo (empaquetar la carne, por ejemplo). Y si es un Humano que se haga otra cosa (Tirarlo a un hueco).

Ese tipo lo podriamos llamar SerVivo.

Dadas las siguientes interfaces:

interface Humano {
name: string,
age: number,
country: string
}

interface Vaca {
age: number,
country: string,
specie: string
}

Lo primero que podríamos hacer es:

type SerVivo = Humano & Vaca

En este caso se consideraría que este tipo tiene todas las propiedades de Vaca y Humano (lo que no es correcto).

Un siguiente paso sería conseguir que las propiedades exclusivas de Humano o Vaca, sean marcadas como opcionales (ya que con estas filtrariamos el tipo exacto que tenemos).

Para ello crearemos un tipo auxiliar llamado PartialBy, que nos devolverá un tipo con "x" propiedad marcada como opcional y el resto como requeridas.

type PartialBy = Omit & Partial

Omit -> Toma todas las propiedades menos la que especificas en K
Partial -> Setea todas las propiedades como opcionales

La suma de estos dos da: Todas la propiedades marcadas como requeridas, menos la que pongas en el lugar de "K".

Entonces, nuestro tipo SerVivo quedaría:

type SerVivo = PartialBy & PartialBy

Ahora podríamos desarrollar mas a fondo nuestro metodo Matar:

const Matar = (ser: SerVivo) => {
if(ser.specie){
const carne = cortar(ser)
enviar(carne)
}
if(ser.name){
const cuerpo = ahorcar(ser)
enterrar(cuerpo)
}
}

Un lindo ejemplo para que aprendan como crear un tipo medianamente generico, pero con la posibilidad de tamizarlo a su antojo.

Si al tratar de setearle una rama remota como upstream a tu rama local. Te encuentras con algo como esto:- warning: refn...
02/06/2022

Si al tratar de setearle una rama remota como upstream a tu rama local. Te encuentras con algo como esto:

- warning: refname 'remote/nombre' is ambiguos

Tu problema tiene que ver con los refs que tienes seteados.
Las branches locales estan en la carpeta refs/heads/... cualquier branch que este fuera de 'heads' no es considerado local.

Si, por ejemplo, tuvieses en tus refs:

refs/remotes/origin/master
refs/origin/master (donde este apunta a tu branch local)

Cuando quisieses usar git branch --set-upstream-to=origin/master master

Ahí tendrías un problema. Pues al tener 2 branches que terminan igual. Git no va a saber a cual te refieres como upstream.

Para deshacerte de la ref que apunta a tu branch local (en el caso de que la hubieras creado involuntariamente):

- git update-ref -d refs/origin/master

Bibliografía:

I have a git repository that is tracking several remote branches: $ git branch -a * master remotes/git-svn remotes/origin/master remotes/trunk When I try to setup a default one I get the

Como crear un nuevo GIT repo a partir de un directorio de tu repo actual (manteniendo el historial de commits correspond...
16/05/2022

Como crear un nuevo GIT repo a partir de un directorio de tu repo actual (manteniendo el historial de commits correspondiente a dicho directorio).

Si, tremendo título jaja. Pero ese fue el problema que tuve que resolver hoy y me pareció interesante compartirles como fue el proceso para solucionarlo.

Primeramente tenemos que clonar (git clone) el repositorio del que queremos sacar el directorio (y su historial de commits).

Una vez con esto listo, podriamos usar el comando "git filter-branch" pero... GIT tira muchas advertencias y parece ser que no es recomendable.

Por lo que vamos a optar por git-filter-repo, que es un proyecto accesible desde GitHub que agrega el comando "git filter-repo" para que consigamos nuestro objetivo. (Esto puede servirles para instalarlo https://superuser.com/a/1563783)

Una vez con el comando "git filter-repo" funcionando (para verificar esto podes correr el comando sin argumentos y te debería devolver "Faltan argumentos"):

git filter-repo --subdirectory-filter NOMBRE_DIRECTORIO

Esto va a hacer que, ahora, la root de tu proyecto sea dicha carpeta (NOMBRE_DIRECTORIO). Va a remover todo menos ese directorio, y solo va a dejar los commits que tengan que ver con este.

Lo que procedería ahora es cambiar la remote branch asociada a tu repo local, para mandarle estos cambios.

De este modo mantenes el historial de commits y tenes una solución elegante a tu problema!

Ojalá les sirva, nos vemos en el próximo capitulo!

I'm attempting to use git-filter-repo to remove large binaries from my repository. I have not used python before. I installed the latest python by clicking on the downloaded .exe file as that is a

11/05/2022

Si querés usar Cookies entre Dominios (Cookies de Terceros) acordate de 3 cosas:

- Que tu Back tenga en su politica de CORS (WithOrigins, AllowCredentials) para que permita que el Front le hablé y le envie Cookies.
- Que el Front, en las solicitudes Fetch que necesiten enviar la Cookie, tenga en sus opciones {credentials: 'include'}
- Que la Cookie al ser creada tenga (SameSite: None, Secure: true)

Esto último implica que para que la Cookie pueda ser seteada, el Back tiene que estar corriendo en HTTPS (Secure: true) y que esa Cookie puede ser usada por otro sitio distinto al que la seteo (SameSite: None).

# A tener en cuenta: Si estas corriendo tu Front en Modo Incognito, por defecto Google no va a enviar Cookies de Terceros (O sea, las que aprendimos a setear en este post). Así que preferiblemente, no corras tu Front en Incognito al probar esto.

Estas Cookies pueden ser de Autenticación, de Métricas, etc.

30/04/2022

Como hacer un INSERT Multiple (Con algunos campos fijos y uno variable) con Condicional:

INSERT INTO tablaName (name, age, country)
SELECT anotherTable.Username, 20, 'El Salvador'
FROM anotherTable
WHERE anotherTable.Gender = 'male'
AND anotherTable.FavoriteColor = 'white'

EL INSERT INTO tiene por un lado la tabla objetivo de la insercion (tablaName) y entre parentesis tiene los fields que vamos a llenar en el orden que los vamos a llenar.
EL SELECT por su lado tiene 3 valores a su derecha, uno variable (anotherTable.Username), dos constantes (estos se repetiran en cada insercion: 20, 'El Salvador').
EL FROM especifica de que tabla vamos a sacar los campos variables.
Y el WHERE especifica las condiciones. Acá podríamos usar mas subqueries, llamar otras tablas, etc. pero lo deje simple para que se entienda la idea.

Como pueden ver este INSERT va a agregar tantas rows como usuarios tengan genero 'male' y color favorito 'white'. Nos evitamos escribir manualmente cada consulta, y tenemos una query mucho mas versatil.

Un saludo a todos y nos vemos en el próximo consejo/tip/mini tutorial xd

26/04/2022

Elon Musk dueño de Twitter? Ni uso esa red social, pero me parece loquísimo como un tipo "porque si" decide comprar uno de los medios de comunicaçao mas grandes del mundo.
Se habló de libertad de expresión. Y no deja de sonar magnífico en el papel.
Ahora que al fin sucedió, solo nos queda esperar y ver...
Que le deparará al pajarito celeste? 😱

En el laburo me salto un problema bastante sencillo en solución, pero molesto por la incertidumbre que genera.Y era el h...
24/04/2022

En el laburo me salto un problema bastante sencillo en solución, pero molesto por la incertidumbre que genera.
Y era el hecho de tener que buscar cursos por su Title y que palabras como "induccion" e "inducción" no fueran evaluadas como la misma palabra.
Para este inconveniente hay una solución muy rápida, que implica una modificación en el Collation_Name de la columna Title.
Si queres saber mas a detalle como es la solución, acá te la dejo! 🤪

Buenas tardes gente! En este post quiero solucionarles rápidamente un problema que me encontré hace poco en el trabajo.

Pequeño Dato 🍎 (relacionado con bases de datos)Si tuvieses que almacenar en una DB los amigos de un usuario. Y recién es...
11/04/2022

Pequeño Dato 🍎 (relacionado con bases de datos)

Si tuvieses que almacenar en una DB los amigos de un usuario. Y recién estuvieses empezando. Es muy probable que a tu tabla Usuarios se te ocurra ponerle un campo "Amigos" y que el tipo de valor sea un string.

"[1,23,4,6]"

Mas específicamente un array de ids parseado a string (es lo primero que se te ocurre, el que diga que no, miente!).

Sin embargo eso no es lo mejor que puedes hacer. En realidad es algo terrible. Porque la idea es que "normalices" la información. O sea que evites repetir datos. En este caso el amigo A tendría una referencia al Id del amigo B, y el amigo B al amigo A. Un error al parsear alguno de los 2 campos "Amigos" y tendrías la información errada.

Lo optimo en estos casos es crear una nueva tabla, Amigos (tabla de unión). Y que esta tenga dos campos:

AmigoA / AmigoB

Estos campos deberían ser poblados con los Ids de 2 usuarios que sean amigos.

De este modo. Si quisieras traer a todos los amigos del Usuario con Id "123". Buscarías todas las filas donde AmigoA o AmigoB son "123". Y luego ya con esos ids, filtrarías la tabla Usuarios para traer a todos los amigos de "123".

Esto sería una relación Many-to-Many (mas específicamente self-referencing many-to-many). Ya que Usuarios puede tener varios amigos que son Usuarios. Y lo mismo al revés.

En este caso estamos relacionando Usuarios con Usuarios, por eso es self-referncing. Pero también podríamos relacionar Usuarios y Servicios, donde un Usuario puede tener muchos Servicios, y un Servicio también puede tener muchos Usuarios. En ese caso estaríamos hablando de una relacion many-to-many a secas.

Bueno, era mas que nada para decirles esta vaina. Ojalá tengan un buen día 🤟 nos olemos luego

Si quieren cavar un poco mas hondo: https://fmhelp.filemaker.com/help/18/fmp/es/index.html /FMP_Help/many-to-many-relationships.html

Muchos habrán visto las siglas TDD. Y los que hayan tenido el valor de intentar aplicarlo se habrán chocado contra un mu...
24/01/2022

Muchos habrán visto las siglas TDD. Y los que hayan tenido el valor de intentar aplicarlo se habrán chocado contra un muro. En un inicio parece algo imposible de entender, y difícil de ejecutar 🤔

Pero a día de hoy es una habilidad necesaria para conseguir ser contratado como desarrollador (ya que tu eres responsable de crear Tests para tu código) 😬

Por lo tanto, aquí les dejo una serie de consejos que pueden serviles a la hora de encarar la creación de sus próximos tests!! 😎

Muchos ven las siglas TDD y automáticamente empieza el sudor frío, la furia, y después la pena y el llanto. Se lo pregona siempre como el…

¿Eres actualmente un albañil, verdulero, pintor o trabajas en algún oficio donde no reconocen tu valor? 😢Probablemente d...
18/01/2022

¿Eres actualmente un albañil, verdulero, pintor o trabajas en algún oficio donde no reconocen tu valor? 😢
Probablemente deberías considerar dar un nuevo rumbo a tu vida. Acá te cuento mi experiencia pasando de un oficio cualquiera a programador, ojalá te saque las excusas! 🤟

Sé que muchos de ustedes vienen de rubros nada relacionados con la informática ni la tecnología en general. Es mas, es probable que algunos…

Muchos no acabaron ni el secundario. Y están pensando en como hacer platita sin necesidad de salir a chorear. 🔪Para toda...
11/01/2022

Muchos no acabaron ni el secundario. Y están pensando en como hacer platita sin necesidad de salir a chorear. 🔪

Para toda ese gente con ganas de saber si necesitan o no tener estudios universitarios para poder ser desarrolladores. Acá les dejo la palabra del Cholo Programador para que la disfruten. 🦙

Bueno, la respuesta corta es “no”. Y la respuesta larga es “la verdad, no”.

Dirección

Olivos 2022
Monserrat
1087

Notificaciones

Sé el primero en enterarse y déjanos enviarle un correo electrónico cuando Cholo Programando publique noticias y promociones. Su dirección de correo electrónico no se utilizará para ningún otro fin, y puede darse de baja en cualquier momento.

Compartir