Estructuras de Control y Modularidad

B2 · Boss Final 2 — Sistema de Gestión de Biblioteca

PF-BOSS2 ⏱ 240 min ⭐ 400 XP avanzado

🧠 Teoría y conceptos

**XP: 500** | **Insignia: *PixelForge Certified Junior Developer*** **Tier: DEV-J2 (Junior Developer)** → **DEV-M1 (Mid Developer Candidate)** **Tiempo estimado: 8 horas** | **Evaluable, con defensa oral obligatoria**

🎯 Brief del "cliente" (PixelForge Library)

*"Necesito un sistema de gestión para una biblioteca escolar. El sistema debe permitir dar de alta libros, dar de baja, buscar por título o autor, prestar libros a usuarios (registrando fecha y usuario), devolver libros, y listar el inventario. El sistema debe manejar al menos 50 libros en memoria (usar arreglos), y todo debe estar organizado en módulos (`.h` y `.cpp`) con funciones específicas para cada responsabilidad. El programa debe compilar sin warnings y estar cubierto con al menos 10 tests `assert`."* — **Ticket #PF-031** | **Cliente ficticio**: Biblioteca PixelForge

Alta de libro

Definición

Pedir: título, autor, ISBN, cantidad en stock (1-10).

Definición

Validar: ISBN único (no debe existir en el catálogo).

Agregar al catálogo.

Mensaje de confirmación.

Baja de libro

Pedir el ISBN del libro a dar de baja.

Si existe, eliminarlo del catálogo (o marcar como inactivo, según decidas).
Si no existe, mostrar error.

Búsqueda

Pedir un término de búsqueda.

Buscar en título Y autor (coincidencia parcial).

Mostrar todos los libros que coincidan: ISBN, título, autor, stock.

Préstamo

Definición

Pedir: ISBN del libro y nombre del usuario.

Definición

Validar: libro existe, stock > 0.

Definición

Registrar: ISBN, nombre de usuario, fecha (puede ser ficticia).

Decrementar el stock.

Mensaje de confirmación.

Devolución

Pedir el ISBN del libro.

Buscar el préstamo activo de ese libro.

Si existe, marcar como devuelto.

Incrementar el stock.

Mensaje de confirmación.

Listar inventario

Mostrar todos los libros del catálogo en formato de tabla.

Salir

Terminar el programa limpiamente.

Estructura del proyecto (multi-archivo)

biblioteca/

├── main.cpp

├── libro.h

├── libro.cpp

├── biblioteca.h

├── biblioteca.cpp

├── menu.h

├── menu.cpp

├── tests.cpp (opcional, para los 10 asserts)

├── README.md

└── .gitignore

Funciones mínimas (al menos 15 funciones)

En `libro.h` / `libro.cpp`:

void inicializarLibro(...) — llena los campos de un libro.

void imprimirLibro(...) — muestra un libro en formato de tabla.

string libroAKey(...) — genera una clave única.

En `biblioteca.h` / `biblioteca.cpp`:

void inicializarBiblioteca(...) — pone el catálogo en estado inicial.

bool agregarLibro(...) — da de alta un libro (valida ISBN único).

bool eliminarLibro(...) — da de baja un libro por ISBN.

int buscarLibros(...) — busca por término en título/autor.

bool prestarLibro(...) — registra un préstamo, decrementa stock.

bool devolverLibro(...) — marca préstamo devuelto, incrementa stock.

int contarLibros(...) — cuenta libros en el catálogo.

int contarLibrosDisponibles(...) — cuenta libros con stock > 0.

int contarPrestamosActivos(...) — cuenta préstamos sin devolver.

En `menu.h` / `menu.cpp`:

int mostrarMenuPrincipal() — muestra el menú, lee opción, valida.

void ejecutarOpcion(...) — dispatch a la función correcta.

(o directamente el do-while en main.cpp)

Variables globales (en el módulo apropiado)

Libro catalogo[MAX_LIBROS] — arreglo de hasta 50 libros.

int numLibros — contador de libros actuales.

Prestamo prestamos[MAX_PRESTAMOS] — arreglo de préstamos.

int numPrestamos — contador de préstamos.

Definición

Constantes: MAX_LIBROS = 50, MAX_PRESTAMOS = 100.

Clean code

Nombres descriptivos (agregarLibro, no agL).

Funciones pequeñas (cada una hace una sola cosa).

Comentarios de intención (no de qué).

Sin magic numbers.

Sin código duplicado.

Testing

Al menos 10 tests con assert en tests.cpp (o en main.cpp con una opción "ejecutar tests").

Definición

Cubrir: alta, baja, búsqueda, préstamo, devolución, casos borde.

Git

5+ commits descriptivos.

Mensajes claros.

README.md profesional.

.gitignore (al menos *.exe, *.o).

libro.h

#ifndef LIBRO_H

#define LIBRO_H

#include <string>

using namespace std;

struct Libro {

string isbn;

string titulo;

string autor;

int stock;

bool activo;

};

struct Prestamo {

string isbn;

string usuario;

string fecha;

bool devuelto;

};

void inicializarLibro(Libro& libro, const string& isbn, const string& titulo,

const string& autor, int stock);

void imprimirLibro(const Libro& libro);

#endif

libro.cpp

#include "libro.h"

#include <iostream>

#include <iomanip>

void inicializarLibro(Libro& libro, const string& isbn, const string& titulo,

const string& autor, int stock) {

libro.isbn = isbn;

libro.titulo = titulo;

libro.autor = autor;

libro.stock = stock;

libro.activo = true;

}

void imprimirLibro(const Libro& libro) {

if (!libro.activo) return;

cout << "| " << left << setw(15) << libro.isbn

<< "| " << setw(30) << libro.titulo

<< "| " << setw(20) << libro.autor

<< "| " << setw(5) << libro.stock << " |" << endl;

}

biblioteca.h

#ifndef BIBLIOTECA_H

#define BIBLIOTECA_H

#include "libro.h"

const int MAX_LIBROS = 50;

const int MAX_PRESTAMOS = 100;

void inicializarBiblioteca(Libro catalogo[], int& numLibros,

Prestamo prestamos[], int& numPrestamos);

bool agregarLibro(Libro catalogo[], int& numLibros, const Libro& libro);

bool eliminarLibro(Libro catalogo[], int numLibros, const string& isbn);

int buscarLibros(const Libro catalogo[], int numLibros, const string& termino,

Libro resultados[]);

bool prestarLibro(Libro catalogo[], int numLibros, Prestamo prestamos[],

int& numPrestamos, const string& isbn, const string& usuario,

const string& fecha);

bool devolverLibro(Libro catalogo[], int numLibros, Prestamo prestamos[],

int numPrestamos, const string& isbn);

int contarLibros(const Libro catalogo[], int numLibros);

int contarLibrosDisponibles(const Libro catalogo[], int numLibros);

#endif

biblioteca.cpp (esqueleto — implementa tú las funciones)

#include "biblioteca.h"

#include <cstring>

void inicializarBiblioteca(Libro catalogo[], int& numLibros,

Prestamo prestamos[], int& numPrestamos) {

numLibros = 0;

numPrestamos = 0;

// Opcional: cargar libros de ejemplo

if (MAX_LIBROS >= 3) {

inicializarLibro(catalogo[0], "978-0131103627", "The C Programming Language",

"Kernighan & Ritchie", 3);

inicializarLibro(catalogo[1], "978-0321563842", "Effective C++",

"Scott Meyers", 2);

inicializarLibro(catalogo[2], "978-0201633610", "Design Patterns",

"Gang of Four", 1);

numLibros = 3;

}

}

bool agregarLibro(Libro catalogo[], int& numLibros, const Libro& libro) {

if (numLibros >= MAX_LIBROS) return false;

// Validar ISBN único

for (int i = 0; i < numLibros; i++) {
if (catalogo[i].activo && catalogo[i].isbn == libro.isbn) {

return false; // ISBN duplicado

}

}

catalogo[numLibros] = libro;

numLibros++;

return true;

}

// ... (implementa las demás funciones)

main.cpp (esqueleto)

#include <iostream>

#include "libro.h"

#include "biblioteca.h"

using namespace std;

int main() {

Libro catalogo[MAX_LIBROS];

Prestamo prestamos[MAX_PRESTAMOS];

int numLibros, numPrestamos;

int opcion;

inicializarBiblioteca(catalogo, numLibros, prestamos, numPrestamos);

do {

cout << "\n=== BIBLIOTECA PIXELFORGE ===" << endl;

cout << "1. Dar de alta libro" << endl;

cout << "2. Dar de baja libro" << endl;

cout << "3. Buscar libro" << endl;

cout << "4. Prestar libro" << endl;

cout << "5. Devolver libro" << endl;

cout << "6. Listar inventario" << endl;

cout << "7. Salir" << endl;

cout << "Opción: ";

cin >> opcion;

// Aquí dispatch con switch

// ...

} while (opcion != 7);

return 0;

}

Estructura

0:00 - 1:00 — Presentación del proyecto "Nombre, proyecto, problema que resuelve. La biblioteca necesitaba un sistema para gestionar libros, préstamos y devoluciones."

1:00 - 2:30 — Diseño modular "Decidí separar en 3 módulos:

libro.h/cpp para el tipo de dato.

biblioteca.h/cpp para la lógica.

main.cpp para la interfaz.

Esto facilita el testing y el mantenimiento."

2:30 - 4:00 — Demo en vivo "Voy a demostrar: alta de un libro, búsqueda, préstamo, devolución, listado."

4:00 - 5:00 — Testing "Tengo 10 tests con assert que validan las funciones críticas. Voy a ejecutarlos."

5:00 - 6:00 — Decisiones de diseño "¿Por qué usé arreglos en vez de memoria dinámica? (más simple para un junior). ¿Por qué puse ISBN como string en vez de int? (los ISBN tienen guiones)."

6:00 - 7:00 — Mejoras futuras "Con más tiempo, agregaría: persistencia en archivo, base de datos, sistema de multas, interfaz gráfica."

⚠️ Errores típicos

Definición

Realidad: la rúbrica penaliza el main largo. 5 puntos se van si main no es "limpio" (solo llamadas).

Solución: desde el primer commit, divide en funciones. Si una función pasa de 30 líneas, divídela.

Error 2: "Tengo todo en un solo archivo .cpp"

Definición

Realidad: la rúbrica pide multi-archivo (3+ .cpp y 3+ .h).

Definición

Solución: planifica ANTES de codificar. Escribe los headers primero, luego implementa.

Error 3: "Las funciones son globales (no en struct ni en class)"

Realidad: está bien para C++ básico. Pero si usas struct, las funciones pueden ser métodos (lo verás en el Cap 3 con POO). Para este Boss, funciones libres + struct es aceptable.

Error 4: "Olvidé validar ISBN duplicado en alta"

Realidad: la rúbrica explícitamente pide "ISBN único". Si dos libros tienen el mismo ISBN, el alta debe fallar.
Definición

Solución: antes de agregar, recorre el catálogo buscando el ISBN.

Error 5: "No versioné en Git, lo entrego solo como código"

Definición

Realidad: la rúbrica pide 5+ commits, README, .gitignore. Sin Git, pierdes 15+ puntos.

Definición

Solución: desde el primer día del Boss, git init y commit por cada feature.

✅ Checklist de entrega

Estructura del proyecto:

[ ] Al menos 3 archivos .cpp y 3 archivos .h.

[ ] Cada archivo en la carpeta correcta.

[ ] main.cpp solo tiene el menú y llamadas a funciones.

Funcionalidad:

[ ] Las 6 opciones del menú funcionan.

[ ] Validación de ISBN único.

[ ] Validación de stock en préstamo.

[ ] Validación de entradas (ISBN no vacío, stock positivo, etc.).

Calidad de código:

[ ] 15+ funciones.

[ ] Nombres descriptivos.

[ ] Constantes nombradas.

[ ] Sin magic numbers.

[ ] Sin código duplicado.

[ ] main con menos de 30 líneas de lógica.

Git:

[ ] 5+ commits.

[ ] Mensajes claros.

[ ] README con todas las secciones.

[ ] .gitignore.

Testing:

[ ] 10+ assert.

[ ] Casos normales + bordes + extremos.

Defensa oral:

[ ] Practicada 2 veces.

[ ] Demo en vivo preparada.

[ ] Capturas listas.

🎉 Al cerrar el Boss

Si tu calificación es ≥ 80 puntos:

🎖️ Recibes la insignia: PixelForge Certified Junior Developer

📈 Asciendes a Tier: DEV-M1 (Mid Developer Candidate)

🚀 Desbloqueas: Acceso al Capítulo 3 — Estructuras de Datos, Persistencia y Proyecto Integrador (70h)

📝 Tu GitHub: Un sistema de gestión completo, modular, testeado y documentado. Esto vale oro en una entrevista.

*"Un junior que entrega un sistema modular con tests es un mid-level disfrazado. Bienvenido al mundo profesional."* — De la introducción de este manual.

Fin del Boss Final 2

\newpage

PARTE 3

Estructuras de Datos Básicas

70 horas · 8 temas + Boss 3

\newpage

📝 Quest · Cuestionario — 📝 Quest — Reactivos para autoevaluación

Las siguientes preguntas te sirven para autoevaluarte después de leer el tema. Responde en tu cuaderno o mentalmente, y luego revisa las Respuestas modelo (disponibles en libre acceso, sin iniciar sesión).

Sección A · Opción múltiple

Elige la opción correcta (A, B, C o D). Las respuestas están en la sección Respuestas modelo.

  1. Un sistema de gestión de biblioteca necesita:
    • Solo libros
    • Libros, usuarios, préstamos, devoluciones, multas
    • Solo multas
    • Solo fechas
  2. Para modelar entidades en C++ usas:
    • Variables globales
    • struct o class
    • Arrays solamente
    • Solo funciones
  3. Para persistir datos del sistema entre ejecuciones:
    • Variables
    • Archivos o base de datos
    • Memoria
    • No se puede
  4. ¿Qué operación es esencial en un sistema de biblioteca?
    • Imprimir
    • Registrar préstamo con fecha de devolución
    • Solo lectura
    • Solo escritura
  5. El sistema debe calcular multas por:
    • Cada visita
    • Días de retraso en la devolución
    • Cada libro
    • Cada usuario

Sección B · Preguntas abiertas

Desarrolla tu respuesta en al menos 3 líneas. Compara con la respuesta modelo después de escribir.

  1. Diseña las entidades y operaciones principales de un sistema de gestión de biblioteca. Usa struct en pseudocódigo.
    → Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
  2. ¿Cómo modelarías la multa por retraso en la devolución?
    → Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
  3. ¿Qué archivos usaría para persistir los datos de la biblioteca entre ejecuciones?
    → Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…

🟢 Cuando termines, revisa las Respuestas modelo y compáralas con las tuyas. La mejor forma de aprender es discutir cada respuesta contigo mismo o con un compañero.

← Volver a temas del capítulo 📚 Ver todos los temas 🔑 Inicia sesión para hacer el Test