✅ La abstracción nos permite usar algo sin preocuparnos por cómo funciona. Esto hace el código más limpio, flexible y facilita cambios sin afectar su uso.
Además, ayuda a mantener la consistencia de los datos. En esta lección veremos tres conceptos clave:
- Invariantes: reglas que aseguran datos coherentes.
- Normalización: mantener los datos en un formato estándar.
- Ocultamiento de datos: evitar modificaciones inesperadas.
Invariantes
Cuando trabajamos con números racionales (fracciones), esperamos que la abstracción funcione de manera predecible.
Por ejemplo, si tenemos funciones para crear y acceder a números racionales:
num = make_rational(3, 4)
numer = get_numer(num)
denom = get_denom(num)
print(numer == 3) # Esperamos True
print(denom == 4) # Esperamos True
Aquí asumimos que si creamos un número racional con 3/4, entonces la función get_numer nos devolverá 3, y get_denom nos devolverá 4.
Si la implementación internamente alterara estos valores sin que lo sepamos, el comportamiento sería inesperado.
Invariantes al comparar números racionales
Una fracción como 1/2 es igual a 2/4, aunque tengan numerador y denominador diferentes. Pero si los comparamos directamente sin normalizarlos, obtenemos un resultado incorrecto:
num1 = make_rational(2, 4)
num2 = make_rational(8, 16)
print(num1 == num2) # Falso, pero deberían ser iguales
Esto sucede porque internamente num1 y num2 tienen numeradores y denominadores distintos, aunque representan la misma fracción. Para corregir esto, usamos normalización.
Normalización
En el caso de las fracciones, podemos dividir el numerador y denominador por su máximo común divisor (MCD) para asegurar que guardamos siempre la versión más simple.
⏬ Ejemplo de normalización:
num = make_rational(10, 20)
print(get_numer(num)) # 1
print(get_denom(num)) # 2
Internamente, 10/20 se convierte en 1/2, evitando problemas al comparar fracciones.
Dónde hacer la normalización
Podemos normalizar en dos puntos:
| Método | Ventajas y desventajas |
|---|---|
En la creación de la fracción (make_rational) |
Se normaliza solo una vez, lo que es más eficiente, evitando recalcular en cada acceso. |
Al acceder a los datos (get_numer y get_denom) |
Cada acceso normaliza los datos, lo cual puede ser costoso si se llama muchas veces. |
Para evitar recálculos innecesarios, podemos usar memoización, que almacena los valores ya calculados.
Ocultar Datos
Hasta ahora, hemos asumido que los datos solo se pueden modificar mediante nuestras funciones.
🤔 Pero, ¿qué pasa si alguien accede directamente y modifica los valores?
num = make_rational(10, 20)
num["numer"] = 40 # Modificación directa
print(get_numer(num)) # Ahora devuelve 40 en lugar de 1
print(get_denom(num)) # 20 en lugar de 2
Aquí se rompe la abstracción porque alguien cambió directamente el numerador sin aplicar normalización.
Para evitar esto, podemos aplicar ocultamiento de datos:
🫣 En algunos lenguajes, hay formas de marcar atributos como "privados" (por ejemplo, __atributo en Python).
🫣 También podemos evitar exponer estructuras de datos directas y solo ofrecer acceso controlado mediante funciones.
🫣 Técnicas como closures permiten encapsular datos sin exponerlos directamente.
En la práctica, la mayoría de los programadores respetan la abstracción sin intentar romperla. Incluso en lenguajes sin protecciones estrictas, es común simplemente seguir las reglas establecidas por el código.
Resumen
- La invariante es una regla que garantiza que los datos sean consistentes.
- La normalización convierte los datos a una forma estándar para evitar inconsistencias.
- Si no se normalizan las fracciones, es posible que tengan diferentes representaciones pero no sean iguales en una comparación.
- Para evitar modificaciones directas e inesperadas, podemos ocultar datos utilizando abstracciones y técnicas como closures o atributos privados.
Materiales adicionales
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.