En Definición del proyecto quedó cerrado el qué: un documento de una página con el problema, el alcance en cajones MoSCoW, los requisitos numerados y sus criterios de aceptación. Ahora toca el cómo, y sigue sin tocar teclear código. Diseñar es tomar por adelantado las decisiones caras: qué entidades existen y si son clases o diccionarios, en qué formato se guardan los datos, cómo se reparte el programa en módulos, qué ve el usuario en pantalla y qué algoritmos hacen falta. Cada una de esas decisiones, tomada sobre papel, cuesta diez minutos; tomada a mitad de la implementación cuesta una tarde de reescritura. Al final de la lección tendrás también el plan de trabajo: la lista de tareas pequeñas, estimadas y ordenadas, que convierte «hacer un proyecto» en «hacer la tarea siguiente».

Contenido

  1. Qué es diseñar y cuánto diseño es suficiente
  2. Modelo de datos: entidades y atributos
  3. ¿Diccionario, clase o lista?
  4. El diagrama de clases del proyecto
  5. Persistencia: elegir el formato del fichero
  6. Arquitectura en capas
  7. Diseño de la interfaz
  8. Algoritmos no triviales en pseudocódigo
  9. Planificación temporal por sesiones
  10. Preparar el repositorio y el entorno
  11. Errores comunes y consejos
  12. Ejercicios
  13. Conclusión

  1. Qué es diseñar y cuánto diseño es suficiente

Diseñar es decidir la forma del programa antes de construirlo: sus piezas, sus responsabilidades y cómo se hablan entre ellas. La pregunta razonable es cuánto. La respuesta, para un proyecto de este tamaño, es: lo justo para poder empezar a programar sin dudas en la primera hora, y no más.

Un diseño suficiente para tu proyecto final cabe en tres o cuatro folios y contiene seis cosas:

Pieza del diseño Pregunta que responde Formato
Modelo de datos ¿Qué cosas existen y qué guardo de cada una? Tabla de entidades y atributos
Estructura elegida ¿Clase, diccionario o lista para cada entidad? Decisión justificada en una línea
Persistencia ¿Dónde y cómo se guardan? Formato de fichero con un ejemplo real
Arquitectura ¿Qué módulos hay y de qué depende cada uno? Diagrama de dependencias
Interfaz ¿Qué ve y elige el usuario? Mapa del menú y esbozo de pantallas
Algoritmos ¿Qué partes no son obvias? Pseudocódigo con prueba de escritorio

Lo que no es diseño a este nivel: escribir todas las funciones de antemano, decidir el nombre de cada variable o hacer diagramas de veinte cajas. Eso se llama parálisis por análisis y consume el tiempo del proyecto. Si dudas entre dos opciones y ninguna es claramente peor, elige la más simple y sigue: en el módulo 8 aprendiste a refactorizar, y refactorizar existe precisamente porque ningún diseño inicial es perfecto.

  1. Modelo de datos: entidades y atributos

Una entidad es un sustantivo importante de tu dominio: algo de lo que guardas varios ejemplares y de los que quieres saber cosas. La forma más rápida de encontrarlas es subrayar los sustantivos de los requisitos de 09-01. En MisGastos, los RF hablan de gasto, ingreso, importe, categoría, fecha, concepto y mes.

De esa lista hay que separar el grano de la paja con dos preguntas:

  • ¿Guardo muchos ejemplares de esto? «Gasto» sí; «mes» no, es solo un criterio de filtrado.
  • ¿Tiene atributos propios más allá de su nombre? «Categoría» en MisGastos solo tiene nombre, así que no necesita ser una entidad: basta con una cadena dentro del movimiento.

Ese segundo descarte es el que más simplifica un primer proyecto. Aplicado a MisGastos queda una sola entidad real:

Entidad Atributo Tipo Obligatorio Reglas
Movimiento id int Automático, único, correlativo
fecha date No futura; vacío = hoy
concepto str 1 a 60 caracteres, sin espacios sobrantes
importe float Distinto de 0; negativo = gasto, positivo = ingreso
categoria str En minúsculas; una de las categorías conocidas

Fíjate en la decisión de la última fila del importe: en lugar de un campo tipo con los valores "gasto" o "ingreso", el signo del importe codifica el tipo. Es una decisión de diseño con consecuencias buenas —el saldo del mes es una simple suma— y una consecuencia mala: hay que recordarla y documentarla, porque no es evidente. Ese tipo de decisión es exactamente lo que te preguntarán en Presentación del proyecto, así que anótala ahora con su porqué.

Además de las entidades, define las constantes del dominio: en MisGastos, las categorías permitidas.

CATEGORIAS = ("comida", "transporte", "ocio", "hogar", "salud", "ingresos", "otros")

Es una tupla y no una lista porque no cambia durante la ejecución (05-04), y está en un único sitio para que añadir una categoría sea editar una línea, no buscar por todo el código.

  1. ¿Diccionario, clase o lista?

Con las entidades identificadas hay que elegir su representación en Python, aplicando la tabla de decisión de Tuplas y estructuras anidadas y lo aprendido en De los datos a los objetos:

Usa... Cuando... En MisGastos
Lista Solo hay una secuencia de valores del mismo tipo, sin nombre propio Los importes de un mes para sumarlos
Tupla Un grupo pequeño y fijo de valores que no cambia CATEGORIAS; el par (categoria, total) de un informe
Diccionario Campos con nombre, estructura que cambia o datos que vienen de JSON El resultado de agrupar por categoría: {"comida": -212.4, ...}
Clase Los datos tienen comportamiento: se validan, se formatean, se comparan Movimiento

La regla que resuelve casi todas las dudas es esta: si además de guardar datos vas a escribir funciones que operan siempre sobre esos datos, es una clase. En MisGastos, un movimiento se valida al crearse (importe distinto de cero, categoría conocida, fecha no futura), se muestra formateado en una línea de tabla y se compara por fecha para ordenar. Tres comportamientos: clase, sin duda.

Y hay una segunda clase que no es una entidad del dominio pero sí una pieza del diseño, exactamente como Agenda en TareaFácil: la colección con lógica. Libro es una entidad; Biblioteca es la clase que sabe buscar, filtrar y resumir. En MisGastos se llama Cuaderno.

  1. El diagrama de clases del proyecto

classDiagram
    class Movimiento {
        +int id
        +date fecha
        +str concepto
        +float importe
        +str categoria
        +es_gasto() bool
        +to_dict() dict
        +from_dict(d) Movimiento
        +__str__() str
    }
    class Cuaderno {
        -list movimientos
        -int siguiente_id
        +agregar(mov) Movimiento
        +eliminar(id) bool
        +buscar(id) Movimiento
        +del_mes(aaaa_mm) list
        +total_por_categoria(aaaa_mm) dict
        +saldo(aaaa_mm) float
        +__len__() int
        +__iter__()
    }
    class MovimientoInvalido {
        <<exception>>
    }
    Cuaderno "1" o-- "*" Movimiento : contiene
    Movimiento ..> MovimientoInvalido : lanza

El diagrama dice tres cosas de un vistazo. Primera, que Cuaderno contiene movimientos: es composición (07-03), la misma relación que Agenda tenía con Tarea. Segunda, que la validación vive en Movimiento y lanza su propia excepción MovimientoInvalido, igual que TareaInvalida en TareaFácil: los datos se protegen a sí mismos y ninguna otra capa puede crear un movimiento inválido. Y tercera, algo que se ve por lo que no aparece: ni Movimiento ni Cuaderno saben nada de ficheros ni de print. Esa ausencia es la arquitectura del apartado 6 dibujada por omisión.

Dibuja tu diagrama con dos o tres clases como máximo. Si te salen seis, casi seguro que varias son atributos disfrazados de clase.

  1. Persistencia: elegir el formato del fichero

Retomando Guardar datos en archivos, tienes tres opciones realistas:

Formato Va bien cuando Va mal cuando Coste
Texto plano Los datos son líneas sueltas sin estructura (notas, log) Hay campos que separar; llegan comas o saltos de línea Mínimo, pero te toca inventar el formato
CSV Registros planos y uniformes que alguien abrirá en la hoja de cálculo Hay listas dentro de un campo o estructuras anidadas Bajo; csv de la biblioteca estándar
JSON Hay anidamiento, campos opcionales o tipos variados El fichero debe abrirse en Excel sin conversión Bajo; json de la biblioteca estándar

Para MisGastos: JSON como formato principal, CSV como exportación. El porqué es el que debes saber defender: JSON conserva los tipos (un float vuelve como float, no como la cadena "12.5"), admite crecer con campos opcionales sin romper los ficheros antiguos y json.load valida la estructura por ti. CSV entra solo donde tiene ventaja real —RF-7, abrir el mes en una hoja de cálculo—, y como salida de un solo sentido: se exporta, no se importa, lo que ahorra todo el trabajo de reconstruir tipos desde texto.

Y ahora lo importante: escribe el formato concreto con un ejemplo real antes de programar nada. Este es gastos.json:

{
  "version": 1,
  "siguiente_id": 4,
  "movimientos": [
    {"id": 1, "fecha": "2026-08-01", "concepto": "Compra semanal", "importe": -62.35, "categoria": "comida"},
    {"id": 2, "fecha": "2026-08-01", "concepto": "Abono transporte", "importe": -32.0, "categoria": "transporte"},
    {"id": 3, "fecha": "2026-08-03", "concepto": "Nomina agosto", "importe": 1450.0, "categoria": "ingresos"}
  ]
}

Tres detalles deliberados, y los tres tienen justificación:

  • version al principio. Hoy no sirve para nada; el día que cambies el formato, tu código podrá leer los ficheros viejos en lugar de romperse. Cuesta una línea.
  • siguiente_id guardado, no recalculado. Si lo calculases como «el máximo id más uno», al borrar el último movimiento reutilizarías su id, y un id reutilizado es una fuente de confusión.
  • Fechas como cadena AAAA-MM-DD. JSON no tiene tipo fecha. Ese formato es el estándar ISO 8601, se convierte con date.fromisoformat() y, además, ordena alfabéticamente igual que cronológicamente, lo que simplifica filtros y ordenaciones.

  1. Arquitectura en capas

Un programa se separa en capas por la razón que ya conoces de Descomponer un programa en funciones y Módulos, paquetes e importaciones: cada pieza tiene una única razón para cambiar. Si el cálculo del total por categoría estuviera mezclado con los print, no podrías probarlo sin simular la pantalla, ni cambiar la presentación sin arriesgarte a tocar el cálculo.

Las cuatro capas y su fichero:

Capa Fichero Responsabilidad Qué tiene prohibido
Modelo modelo.py Entidades y sus reglas de validación print, input, ficheros
Lógica cuaderno.py Colección y operaciones: agregar, buscar, filtrar, agregar totales print, input, ficheros
Almacén almacen.py Leer y escribir JSON y exportar CSV print, input
Interfaz interfaz.py Menú, input, print, formato de pantalla Cálculos del dominio
flowchart TD
    M["__main__.py<br/>arranque"] --> I["interfaz.py<br/>menu y pantallas"]
    I --> C["cuaderno.py<br/>logica de coleccion"]
    I --> A["almacen.py<br/>JSON y CSV"]
    A --> C
    C --> MO["modelo.py<br/>Movimiento y validacion"]
    A --> MO

Las flechas van siempre hacia abajo: la interfaz conoce la lógica, la lógica conoce el modelo, y el modelo no conoce a nadie. Ninguna flecha sube. Esa regla, que parece trivial, es la que permite escribir pruebas del modelo y de la lógica sin tocar la pantalla, y es la misma estructura que ya has visto funcionando en TareaFácil (modelo.py, agenda.py, almacen.py, interfaz.py, __main__.py).

Añade __init__.py para que el directorio sea un paquete y __main__.py para poder ejecutar python -m misgastos, exactamente como se hizo en 07-04.

  1. Diseño de la interfaz

Un menú mal diseñado se nota en la demo. Dibuja el mapa antes de programarlo:

flowchart TD
    Menu["MENU PRINCIPAL"] --> O1["1 Registrar gasto"]
    Menu --> O2["2 Registrar ingreso"]
    Menu --> O3["3 Movimientos del mes"]
    Menu --> O4["4 Resumen por categoria"]
    Menu --> O5["5 Borrar movimiento"]
    Menu --> O6["6 Exportar mes a CSV"]
    Menu --> O0["0 Salir"]
    O1 --> Menu
    O2 --> Menu
    O3 --> Menu
    O4 --> Menu
    O5 --> Conf["Confirmar s/n"] --> Menu
    O6 --> Menu
    O0 --> Fin["Guardar y terminar"]

Tres reglas de diseño que se leen en ese mapa: todo camino vuelve al menú (nunca dejes al usuario en un sitio sin salida), una sola pantalla de profundidad (nada de submenús en un primer proyecto) y las acciones destructivas piden confirmación. La opción 0 para salir es convención: el 0 está siempre en el mismo sitio aunque la lista crezca.

Después esboza cada pantalla en texto, tal cual quieres verla. No es cosmética: al escribir el esbozo descubres qué datos necesitas calcular.

=========================================
  RESUMEN DE 2026-08                 (4)
=========================================
  comida          -212,40 EUR   38,1 %
  transporte      -132,00 EUR   23,7 %
  hogar            -98,50 EUR   17,7 %
  ocio             -57,20 EUR   10,3 %
  otros            -57,00 EUR   10,2 %
-----------------------------------------
  Gastos          -557,10 EUR
  Ingresos       +1450,00 EUR
  SALDO           +892,90 EUR
=========================================

Ese esbozo acaba de generar tres requisitos de cálculo que no estaban explícitos: hace falta el porcentaje sobre el total de gastos, hace falta ordenar de mayor a menor gasto y hace falta separar gastos de ingresos en el pie. Dibujar la pantalla es la forma más barata de encontrar trabajo oculto.

  1. Algoritmos no triviales en pseudocódigo

La mayor parte de tu proyecto es código evidente. Pero siempre hay dos o tres puntos donde no lo es, y esos —solo esos— se escriben antes en pseudocódigo, con la técnica de Del problema al algoritmo. En MisGastos son dos.

Algoritmo 1: total por categoría de un mes.

FUNCION total_por_categoria(movimientos, mes):
    totales <- diccionario vacio
    PARA CADA m EN movimientos:
        SI m.fecha empieza por mes ENTONCES
            totales[m.categoria] <- totales.obtener(m.categoria, 0) + m.importe
    DEVOLVER totales ordenado por valor ascendente

Dos decisiones concretas ahí. La comparación por prefijo de cadena ("2026-08-03" empieza por "2026-08") funciona porque el formato ISO lo permite, la decisión del apartado 5 pagando dividendos. Y obtener(clave, 0) es el patrón de acumulación en diccionario de Diccionarios y conjuntos, que evita el if clave not in totales. El orden ascendente por valor pone primero los importes más negativos, es decir, los mayores gastos, que es lo que pide el esbozo del apartado 7.

Prueba de escritorio con cuatro movimientos y mes = "2026-08":

Paso Movimiento ¿Coincide? totales después
1 2026-07-30, -20,00, comida No {}
2 2026-08-01, -62,35, comida {comida: -62,35}
3 2026-08-01, -32,00, transporte {comida: -62,35, transporte: -32,00}
4 2026-08-04, -15,00, comida {comida: -77,35, transporte: -32,00}

Resultado ordenado: [("comida", -77,35), ("transporte", -32,00)]. Correcto: el gasto de julio queda fuera y las dos compras de comida se acumulan en la misma clave. Esta tabla, hecha en tres minutos sobre papel, es la que evita descubrir en la demo que el filtro de mes tomaba también el año equivocado.

Algoritmo 2: asignar el siguiente identificador.

FUNCION agregar(cuaderno, movimiento):
    movimiento.id <- cuaderno.siguiente_id
    cuaderno.siguiente_id <- cuaderno.siguiente_id + 1
    anadir movimiento a la lista
    DEVOLVER movimiento

Parece demasiado simple para escribirlo, y precisamente por eso conviene: escrito así se ve que el contador debe persistirse con los datos (apartado 5) y que hay un caso límite, el primer arranque sin fichero, donde siguiente_id vale 1.

  1. Planificación temporal por sesiones

Un proyecto de 15 a 25 horas no se planifica «por semanas»: se parte en tareas de una a tres horas, cada una con un resultado visible. Si una tarea no cabe en tres horas, pártela; si no sabes estimarla, es que no la entiendes todavía y hay que diseñarla un poco más.

# Tarea Est. Depende de Resultado visible
T1 Repositorio, entorno, esqueleto que arranca y sale 1 h python -m misgastos muestra el menú y sale
T2 Clase Movimiento con validación y MovimientoInvalido 2 h T1 Se crea un movimiento desde el intérprete
T3 tests/test_modelo.py 1 h T2 pytest en verde
T4 Clase Cuaderno: agregar, buscar, eliminar, __len__ 2 h T2 Alta y baja desde el intérprete
T5 almacen.py: guardar y cargar JSON 2 h T2 El fichero se crea y se relee
T6 tests/test_almacen.py con tmp_path 1 h T5 Ciclo guardar/cargar probado
T7 Interfaz: menú, registrar gasto (RF-1) de punta a punta 3 h T4, T5 Primera funcionalidad completa
T8 Listar movimientos del mes (RF-3) 2 h T7 Pantalla de listado
T9 total_por_categoria y saldo + pruebas (RF-4) 3 h T4, T3 Pantalla de resumen
T10 Registrar ingreso (RF-2) y borrar (RF-5) 2 h T7 Menú completo de los Must
T11 Exportar CSV (RF-7) 2 h T8 Fichero abierto en la hoja de cálculo
T12 Robustez: try/except, logging, revisión de entradas 2 h T10 Ninguna entrada rompe el programa
T13 README, docstrings, black y ruff, etiqueta v1.0 2 h T12 Repositorio presentable

Total estimado: 25 horas. Y ahora la regla que casi nadie aplica la primera vez: multiplica tu estimación por 1,5. No porque seas lento, sino porque todas las estimaciones de principiante omiten el tiempo de buscar errores. Si el resultado no cabe en el tiempo del que dispones, no aceleres: quita un Should.

flowchart LR
    H1["Hito 1<br/>Arranca y sale<br/>T1"] --> H2["Hito 2<br/>Modelo probado<br/>T2 T3"]
    H2 --> H3["Hito 3<br/>Guarda y carga<br/>T4 T5 T6"]
    H3 --> H4["Hito 4<br/>Primer RF completo<br/>T7"]
    H4 --> H5["Hito 5<br/>Todos los Must<br/>T8 T9 T10"]
    H5 --> H6["Hito 6<br/>v1.0 presentable<br/>T11 T12 T13"]

El principio que ordena todo esto: el esqueleto que arranca tiene que existir el primer día. Un python -m misgastos que muestre el menú y salga, aunque las opciones no hagan nada, resuelve de golpe el entorno, la estructura del paquete y la ejecución, que son justamente los problemas que bloquean a quien empieza. A partir de ahí el programa nunca vuelve a estar roto: cada tarea lo deja ejecutable.

  1. Preparar el repositorio y el entorno

Antes de la primera línea de código, deja el terreno listo. Es la tarea T1 y son quince minutos, retomando Entornos de desarrollo y Control de versiones:

mkdir misgastos-proyecto && cd misgastos-proyecto
python -m venv .venv
source .venv/bin/activate        # en Windows: .venv\Scripts\activate
pip install pytest black ruff
pip freeze > requirements-dev.txt

git init
mkdir misgastos tests
touch misgastos/__init__.py misgastos/__main__.py misgastos/modelo.py
touch misgastos/cuaderno.py misgastos/almacen.py misgastos/interfaz.py

El .gitignore, con lo que nunca debe entrar en el repositorio:

.venv/
__pycache__/
*.pyc
gastos.json
*.log
.pytest_cache/

Repara en gastos.json: los datos personales no se versionan. En el repositorio va datos_ejemplo.json con movimientos inventados, y el fichero real de trabajo queda fuera. Es el mismo criterio por el que tareafacil.log estaba excluido en TareaFácil.

Y el primer commit, que ya deja constancia del diseño:

git add .
git commit -m "Estructura inicial del proyecto y documento de definicion"

Errores Comunes y Consejos

  • Diseñar de más. Diagramas de quince clases, jerarquías de herencia por si acaso, una capa de abstracción sobre el fichero «por si algún día es una base de datos». Ese día no llegará en este proyecto. Diseña para lo que hay en el cajón Must.
  • Convertir en clase todo lo que se mueve. Si una entidad solo tiene nombre y ningún comportamiento —como categoria en MisGastos—, es una cadena. Una clase de un solo atributo casi siempre sobra.
  • Elegir el formato de datos por costumbre. CSV parece más simple hasta que necesitas guardar una lista dentro de un campo o recuperar un número que volvió como cadena. Elige con la tabla del apartado 5, no por inercia.
  • Saltarse el esbozo de pantallas. Es el paso que más trabajo oculto descubre: en MisGastos aparecieron tres cálculos que ningún requisito mencionaba.
  • Planificar en tareas grandes. «Hacer la interfaz» no es una tarea, es un mes de sensación de no avanzar. Una tarea es «registrar un gasto de punta a punta»: tres horas y un resultado que se ve.
  • Consejo: escribe el porqué de cada decisión. Una línea por decisión en el DEFINICION.md («JSON porque conserva tipos y admite campos nuevos»). En 09-04 tendrás que defenderlas y no te acordarás.
  • Consejo: si dudas entre dos diseños, elige el que sea más fácil de deshacer. Es casi siempre el más simple, y ya sabes refactorizar (08-05).

Ejercicios

Continúan el proyecto que definiste en 09-01. Guarda los resultados en un DISENO.md junto al DEFINICION.md.

Ejercicio 1: Modelo de datos y diagrama de clases

Subraya los sustantivos de tus requisitos y monta la tabla de entidades con sus atributos, tipos, obligatoriedad y reglas de validación. Justifica en una línea por entidad si será clase, diccionario o lista. Dibuja el diagrama de clases en mermaid, incluyendo la clase colección y la excepción propia. Máximo tres clases.

Ejercicio 2: Persistencia, capas e interfaz

Elige el formato de fichero con la tabla del apartado 5 y escribe un ejemplo real de tu fichero de datos con tres registros. Reparte el código en los módulos de las cuatro capas y dibuja el diagrama de dependencias. Dibuja el mapa del menú y esboza en texto las dos pantallas más importantes de tu programa.

Ejercicio 3: Algoritmos y plan de trabajo

Identifica los dos o tres algoritmos no triviales de tu proyecto, escríbelos en pseudocódigo y haz una prueba de escritorio de al menos uno con cuatro o cinco datos de entrada. Después monta la tabla de tareas de una a tres horas con estimación y dependencias, multiplica el total por 1,5 y comprueba si cabe en tu tiempo disponible. Si no cabe, indica qué Should eliminas.

Soluciones

Solución 1. Los apartados 2, 3 y 4 son la solución para MisGastos: una única entidad Movimiento (clase, porque valida, formatea y se compara), la categoría reducida a cadena, y Cuaderno como colección con lógica. El descarte de Categoria como clase es el punto interesante: solo tenía nombre. Si tu proyecto necesitara presupuesto por categoría, la decisión se invertiría, porque entonces sí tendría atributos y comportamiento propios. Rúbrica: ¿tienes tres clases o menos? ¿Cada clase tiene al menos dos comportamientos que justifiquen serlo? ¿Cada atributo tiene tipo y regla de validación? ¿Hay una excepción propia para los datos inválidos?

Solución 2. Apartados 5, 6 y 7. Los criterios que debes poder defender: JSON porque hay tipos numéricos y el formato puede crecer; CSV solo como exportación de un sentido; las capas separadas para poder probar la lógica sin pantalla; el menú de una sola profundidad con confirmación en el borrado. Rúbrica: ¿el ejemplo de fichero es JSON o CSV válido de verdad, con tres registros reales? ¿Todas las flechas del diagrama de dependencias van hacia abajo, sin ciclos? ¿Tu esbozo de pantalla te ha descubierto algún cálculo que no habías previsto? Si no ha descubierto ninguno, míralo otra vez: casi siempre hay uno.

Solución 3. Apartados 8 y 9. Observa que las trece tareas de MisGastos siguen el orden modelo → pruebas → lógica → almacén → interfaz → extras, con T1 (el esqueleto que arranca) en primer lugar y T7 marcando el hito de la primera funcionalidad completa. Ese es el orden de construcción que desarrolla Implementación y pruebas. Rúbrica: ¿ninguna tarea pasa de tres horas? ¿Cada tarea tiene un resultado visible y verificable? ¿Existe una tarea T1 de una hora que deja el programa arrancando? ¿Has aplicado el factor 1,5? ¿Tu pseudocódigo es independiente de Python, es decir, podrías traducirlo a otro lenguaje?

Conclusión

Diseñar es tomar por adelantado las decisiones caras, y para un proyecto de este tamaño cabe en tres o cuatro folios. El modelo de datos sale de subrayar los sustantivos de los requisitos y descartar los que no tienen ni ejemplares múltiples ni atributos propios; cada entidad se representa como lista, tupla, diccionario o clase según la tabla de 05-04 y 07-01, con la regla de que aquello que además de datos tiene comportamiento es una clase. A las entidades se suma la clase colecciónAgenda en TareaFácil, Cuaderno en MisGastos— que concentra la lógica de buscar, filtrar y resumir, y una excepción propia para los datos inválidos.

La persistencia se elige con criterio: texto plano para líneas sin estructura, CSV para registros planos que verá una hoja de cálculo, JSON cuando hay tipos, anidamiento o campos que crecerán; y se escribe el formato concreto con un ejemplo real antes de programar, con detalles que después ahorran horas —número de versión, contador de identificadores persistido y fechas en ISO AAAA-MM-DD, que ordenan alfabéticamente igual que en el tiempo—. La arquitectura en capas reparte el código en modelo, lógica, almacén e interfaz, con las dependencias siempre hacia abajo y el modelo sin conocer a nadie, que es lo que permite probar sin pantalla. La interfaz se diseña con un mapa de menú de una sola profundidad donde todo camino vuelve al inicio y las acciones destructivas confirman, más un esbozo en texto de cada pantalla que casi siempre descubre cálculos ocultos. Los dos o tres algoritmos no triviales se escriben en pseudocódigo y se validan con una prueba de escritorio antes de traducirlos. Y el plan de trabajo parte todo en tareas de una a tres horas con resultado visible, ordenadas por dependencia, estimadas y multiplicadas por 1,5, con el esqueleto que arranca como primerísima tarea y el repositorio y el entorno preparados antes de escribir una línea.

Con el qué y el cómo cerrados, ya no queda nada que impida empezar. En Implementación y pruebas construiremos de verdad: la estrategia incremental que mantiene el programa siempre ejecutable, el orden de construcción capa por capa con las pruebas escritas a la vez que el código, qué hacer cuando algo falla y no sabes por qué, y la checklist que decide cuándo la implementación está terminada.

Fundamentos de la Programación

Módulo 1: Introducción a la Programación

Módulo 2: Conceptos Básicos

Módulo 3: Estructuras de Control

Módulo 4: Funciones y Procedimientos

Módulo 5: Estructuras de Datos

Módulo 6: Algoritmos Básicos

Módulo 7: Objetos y Organización del Código

Módulo 8: Buenas Prácticas y Herramientas

Módulo 9: Proyecto Final y Cierre del Curso

© Copyright 2026. Todos los derechos reservados