Paradigmas de programación


2026 semestre 2

Cronograma de actividades

  • (5%) Quiz #1 [Semana 3 Julio 30 | 31]
  • (15%) Evaluación #1 [Semana 5 Agosto 11 | 12]
  • (20%) Taller #1 [Semana 9 Septiembre 8 | 9]
  • (15%) Taller #2 [Semana 12 Septiembre 29 | 30]
  • (20%) Evaluación #2 [Semana 14 Octubre 6 | 7]
  • (25%) Proyecto Final [Semana 17 Octubre 27 | 28]

Taller 1

En parejas o equipos de tres personas

Se les entrega un juego de Godot en C# que ya funciona, pero está mal organizado.

El taller no es hacer el juego. Es reorganizarlo aplicando correctamente los conceptos de POO, y extenderlo sin romper lo que ya anda.

⬇ Descargar el proyecto base

El juego base

Un vendedor de madera (Pawn) recorre el mapa. Hoy:

  • Se mueve, se anima y tiene contador de madera y monedas
  • El Lancer le compra: descuenta 1 madera, suma 1 moneda
  • El Goblin está en el mapa y se anima, pero no tiene implementada la interacción de robo
  • La tecla Z existe, dice "Z para resumir" y solo imprime un texto

El objetivo

Diagrama de clases objetivo del juego SellerGame

⬇ Descargar el diagrama (Draw.io) es el mínimo. Lo que haga falta para limpiar el código va por encima.

Parte 1 — Limpiar la base

Hoy Lancer.cs, Goblin.cs y Monk.cs tienen el mismo bloque de código copiado tres veces: el campo _animator, el _Ready() y un _Process() vacío.

  • Extraer la clase base NPC con lo común
  • Lancer, Goblin y Monk deben derivar de NPC
  • Que no quede ni una línea duplicada entre los tres

Parte 2 — Las interfaces

Este es el corazón del taller. Hoy el vendedor pregunta por el tipo concreto:


// ANTES  (Seller.cs)
if (_npc is Lancer lancer)
    lancer.Buy(this);

// DESPUES
if (_npc is IBuyer buyer) buyer.Buy(this);
if (_npc is IThief thief) thief.Steal(this);
          

Crear IBuyer (Price, Buy) e IThief (Steal), y que el Seller deje de conocer clases concretas.

Parte 3 — El Monk

El proyecto ya trae el sprite, la escena monk.tscn y un Monk.cs vacío.

  • Convertirlo en un segundo comprador: Monk : NPC, IBuyer
  • Debe pagar un precio distinto al del Lancer
  • Agregarlo a world.tscn, porque todavía no está en el mapa

Prueba de fuego: si el refactor está bien hecho, el Seller no se toca para que esto funcione.

Parte 4 — El Goblin roba

  • Implementar Goblin : NPC, IThief con su método Steal
  • Al intentar venderle, el vendedor pierde producto
  • El robo se refleja en el HUD

Regla concreta: si el vendedor no tiene madera, el Goblin no puede robar y no se descuenta nada.

Parte 5 — Las transacciones

  • Crear Transaction con NPC y TotalCounts como mínimo, y sus dos especializaciones: Sale y Theft
  • El Seller compone la lista: las crea, las posee y mueren con él
  • Cada venta y cada robo quedan registrados

Una transacción por NPC: venderle dos veces al mismo Lancer no crea dos instancias — incrementa el TotalCounts de la que ya existe.

Parte 5 — El historial

La tecla Z debe imprimir el historial de transacciones: qué NPC, qué tipo de transacción y cuánto acumula cada uno.

Ustedes deciden el formato y qué más guarda cada transacción. Justifíquenlo en la sustentación.

Reglas del refactor

  • El juego debe seguir funcionando igual que antes, más lo nuevo
  • Si rompieron el juego, el refactor falló — por más lindo que quedó el diagrama

Debe seguir andando: moverse, animarse, el contador de madera, el contador de monedas, el indicador de "X para vender" y la venta al Lancer.

Prohibido

La regla debe salir del diseño, no de un condicional:

  • if (npc is Lancer) o cualquier chequeo de tipo concreto
  • Comparar Name, strings o tags para decidir si vende o le roban
  • Banderas tipo esComprador o esLadron
  • Repetir el bloque _animator + _Ready() en cada NPC

Calidad del código

Esto se evalúa aparte:

  • _Process() no lleva lógica de negocio: orquesta y delega a métodos con nombre
  • Cero números mágicos: velocidad, madera inicial, precios y cantidad robada son constantes o [Export]
  • Una clase por archivo, nombres significativos
  • Encapsulamiento real: nadie modifica los contadores desde afuera a la fuerza

El diagrama final

El diagrama que entregan no es el que les di.

  • Debe reflejar el refactor completo, no solo el mínimo
  • Toda clase, atributo, método y relación que exista en el código debe estar en el diagrama
  • Y al revés: nada en el diagrama que no exista en el código

Espejo exacto. Si crearon una clase extra para limpiar algo, va al diagrama.

Entregables

  • El proyecto de Godot con el refactor completo
  • El diagrama de clases final en Draw.io, espejo exacto del código
  • Demostración en clase: vender al Lancer, vender al Monk a otro precio, que el Goblin robe, y Z mostrando el historial
  • Sustentación individual

Criterios de evaluación

  • (20%) Jerarquía NPC y eliminación de la duplicación
  • (25%) Interfaces IBuyer / IThief y eliminación del chequeo de tipo concreto
  • (10%) Monk como segundo comprador con precio propio
  • (10%) Goblin.Steal funcionando
  • (15%) Transacciones (Sale / Theft) e historial con Z
  • (10%) Calidad del código
  • (10%) Diagrama final completo y espejo del código

⚠️ Importante


El taller no será evaluado si:


  • El proyecto no compila o no corre
  • El diagrama final no corresponde con el código entregado
  • El integrante no sustenta la entrega

No hay excepciones.

Taller 2

En parejas o equipos de tres personas

Construir desde cero una aplicación de escritorio en .NET C# con Windows Forms que modele una tienda híbrida: vende productos físicos y productos digitales.

El tema lo eligen ustedes — videojuegos, películas, música, libros, lo que les apasione. El dominio es suyo; los requisitos no.

¿Por qué híbrida?

Porque los dos productos se comportan distinto, y ahí está el taller:

  • El físico tiene stock finito y cuesta enviarlo
  • El digital no se agota y no se envía: se descarga
  • Los dos se cobran, se listan y se venden por la misma caja financiera

Si la venta tiene que preguntar de qué tipo es cada producto para cobrarlo, el diseño falló.

El sistema, en tres CRUDs

  1. Productos — el catálogo: físicos y digitales
  2. Clientes — a quién le vendemos
  3. Ventas — qué le vendimos, cuándo y a qué precio

Constrúyanlos en ese orden. Cada uno se apoya en el anterior, y la venta es la que pone a prueba todo lo demás.

CRUD 1 — Productos

Lo primero es decidir qué datos guarda cada uno:

  • Común: código, nombre, descripción, precio, categoría y peso — en el físico es cuánto pesa, en el digital es cuánto ocupa la descarga
  • Físico: stock disponible y costo de envío
  • Digital: formato y URL de descarga

La regla: lo común sube a la clase base. Lo propio se queda abajo. Si un atributo no aplica a los dos, no va en la base.

CRUD 1 — Los dos formularios

Crear un producto físico no es lo mismo que crear uno digital, y el formulario lo tiene que mostrar.

  • Un formulario para producto físico — con stock y costo de envío
  • Otro para producto digital — con su formato y su URL de descarga
  • Un único catálogo que los lista a los dos en la misma grilla

Más el resto de operaciones CRUD

La pregunta incómoda


¿Qué pasa si eliminan un producto que ya fue vendido?


Guarden la respuesta. La necesitan en el CRUD 3.

CRUD 2 — Clientes

El más simple de los tres. Aprovéchenlo para dejar el patrón limpio.

  • Datos mínimos: documento, nombre, correo, teléfono
  • El documento no se repite: valídenlo al crear y al actualizar

Otra decisión suya: ¿se puede eliminar un cliente que ya compró? Si dicen que no, expliquen por qué. Si dicen que sí, expliquen qué pasa con sus ventas.

CRUD 3 — Ventas

Acá se junta todo. Una venta es:

  • Un número y una fecha
  • Un cliente
  • Un conjunto de detalles — lo que se llevó y cuánto
  • Un total que la venta calcula, no la pantalla

El formulario: elegir cliente, ir agregando productos con cantidad, ver el total en vivo y guardar.

El patrón SaleDetail

La venta no guarda productos. Guarda SaleDetail, y cada detalle copia lo que se vendió:

  • Descripción del producto tal como estaba ese día
  • Precio unitario del momento de la venta
  • Cantidad y subtotal

¿Y por qué tanto lío?

Porque si la venta apunta directo al producto, pasa esto:

  • Mañana suben el precio — y la venta de ayer cambia sola
  • Pasado eliminan el producto — y la venta queda rota
  • Le cambian el nombre — y el histórico miente

Una venta es un registro histórico. Una vez registrada, nada de afuera la puede modificar. Eso es desacoplar.

Las reglas de la venta

  • Al vender un producto físico se descuenta el stock; si no alcanza, el detalle no se agrega
  • El digital nunca se queda sin stock
  • El total sale de sumar los detalles, cada uno con su precio y su envío
  • Una venta sin detalles no se guarda

Persistencia con CsvHelper

Los tres CRUDs guardan en archivos .csv con CsvHelper.

  • Un archivo por entidad: productos, clientes, ventas y los detalles de venta
  • Al abrir la aplicación se carga todo; al crear, actualizar o eliminar se guarda
  • Nada de leer ni escribir el CSV a mano: eso lo hace CsvHelper

La prueba: cerrar la aplicación, volver a abrirla y que esté todo, tal como lo dejaron.

Y acá viene lo bueno

Un CSV es plano. Su modelo no lo es.

  • ¿Cómo guardan productos físicos y digitales y los vuelven a leer sabiendo cuál es cuál?
  • ¿Cómo reconstruyen una venta con sus detalles si el CSV solo guarda filas sueltas?

No hay una única respuesta correcta. Hay respuestas justificadas. La suya la explican en la sustentación.

Entregables


  1. Comprimido del código — el proyecto completo, con los archivos .csv incluidos
  2. Diagrama de clases UML en archivo Draw.io

Criterios de evaluación

  • (25%) CRUD de productos: separación común / físico / digital y los dos formularios
  • (15%) CRUD de clientes: validaciones y su relación con las ventas
  • (35%) CRUD de ventas: SaleDetail, reglas de stock y cálculo del total
  • (25%) Persistencia con CsvHelper: guardar y recuperar sin perder datos

⚠️ La sustentación


La sustentación es individual y no tiene porcentaje. No suma: habilita.

El integrante que no sustente correctamente su entrega no tiene el taller evaluado — aunque el equipo haya entregado todo completo y funcionando.


No hay excepciones.