La lliçó anterior va fixar l'abast general del projecte final de BiblioTech i la seva arquitectura triada. Abans de tocar una sola línia de codi, aquesta lliçó converteix aquest abast en quelcom molt més concret: una llista precisa de requisits funcionals i no funcionals, i un pla de treball en iteracions petites que eviti la temptació d'intentar construir-ho tot de cop. Planificar abans de programar no és burocràcia innecessària: és el que permet, a la Lliçó 3, saber exactament què construir primer i per què, en comptes d'avançar a cegues ensamblant peces en un ordre arbitrari.

Contingut

  1. Requisits funcionals: casos d'ús concrets
  2. Requisits no funcionals
  3. Planificació en fases: quatre iteracions
  4. Estimació bàsica de tasques per iteració
  5. Elecció definitiva de tecnologies

  1. Requisits funcionals: casos d'ús concrets

Un requisit funcional descriu quelcom que el sistema ha de fer: una acció concreta que un usuari (o un client de l'API) pot sol·licitar i esperar-ne un resultat. Per a BiblioTech, la llista de requisits funcionals del projecte final és la següent:

# Cas d'ús Entrada Resultat esperat
RF1 Donar d'alta un llibre o revista Títol, autor, ISBN (o altres dades de Llibre/Revista, Mòdul 3) El material s'afegeix a Cataleg
RF2 Donar de baixa un material del catàleg Identificador del material El material deixa d'aparèixer al catàleg
RF3 Cercar materials per títol o autor Text de cerca Llista de materials que coincideixen (LINQ, Mòdul 4)
RF4 Donar d'alta un soci Nom del soci El soci s'afegeix a Socis, amb un Id únic
RF5 Registrar un préstec ISBN del material, Id del soci Es crea un Prestec; el material queda marcat com a no disponible
RF6 Registrar una devolució Identificador del préstec S'assigna DataDevolucio; es calcula la sanció si hi ha retard (Mòdul 8, IPoliticaSancio)
RF7 Consultar metadades externes d'un llibre ISBN Dades addicionals del servei extern (Mòdul 5), o absència clara si no estan disponibles

Cadascun d'aquests set requisits correspon, de forma gairebé directa, a un mètode ja existent a Biblioteca o a una combinació petita d'ells —la mateixa taula és, en si mateixa, un mapa de quina part del codi ja construït cobreix cada requisit.

  1. Requisits no funcionals

Un requisit no funcional no descriu una acció, sinó una qualitat que el sistema ha de tenir mentre fa el que fa. Són més difícils de verificar amb un simple cas d'ús, però igual d'importants:

  • Rendiment raonable: les operacions de consulta (RF3, llistar el catàleg) han de respondre en un temps acceptable fins i tot amb un catàleg de mida moderada (centenars o pocs milers de materials); no es persegueix aquí cap objectiu de rendiment extrem, només evitar operacions evidentment ineficients (per exemple, carregar tot el catàleg en memòria a cada petició si una consulta a la base de dades ja n'hi hauria prou).
  • Seguretat bàsica: l'API no ha d'exposar dades sensibles de forma innecessària (per exemple, cadenes de connexió o detalls interns de la base de dades en els missatges d'error que retorna al client); les cadenes de connexió de producció han de viure fora del codi font (Lliçó 5, configuració per entorn), mai escrites directament a Program.cs.
  • Mantenibilitat: gràcies a l'arquitectura del Mòdul 8 (IRepositoriBiblioteca + injecció de dependències + proves unitàries), canviar el mecanisme de persistència, afegir un nou endpoint, o corregir un error ha de poder fer-se sense reescriure parts del sistema no relacionades amb el canvi.
  • Fiabilitat davant de fallades externes: la consulta de metadades externes (RF7) depèn d'un servei de tercers que pot fallar o no respondre; ja es va veure al Mòdul 5 que aquest cas es captura amb try/catch sobre HttpRequestException, retornant null en comptes de propagar la fallada a qui va demanar les metadades.

A diferència dels requisits funcionals, aquests no es "marquen com a completats" amb una única prova puntual: es verifiquen de forma contínua al llarg de tot el projecte, i es revisen explícitament al checklist de qualitat de la Lliçó 4.

  1. Planificació en fases: quatre iteracions

Intentar construir les set funcionalitats de l'apartat 1 alhora, sense cap ordre, és la recepta més directa per quedar-se encallat a mig camí sense res que funcioni de cap a cap. En comptes d'això, el projecte s'organitza en quatre iteracions petites, cadascuna lliurant quelcom que funciona per si mateix abans de passar a la següent:

flowchart LR
    I1["Iteracio 1<br/>Domini + Persistencia<br/>(ja construits, Moduls 3-5-8)"] --> I2["Iteracio 2<br/>API<br/>(Llico 3)"]
    I2 --> I3["Iteracio 3<br/>Client / UI<br/>(Llico 3)"]
    I3 --> I4["Iteracio 4<br/>Poliment<br/>(Llicons 4-5)"]
Iteració Què lliura Quins requisits cobreix
1. Domini + Persistència Confirmar que Biblioteca, el model de domini i IRepositoriBiblioteca amb la seva implementació triada (apartat 5) compilen i funcionen de forma aïllada, sense API encara Base de RF1-RF7 (ja construïda en mòduls anteriors, només es verifica que segueix en ordre)
2. API Endpoints HTTP d'ASP.NET Core Minimal API sobre el domini, amb DI ja registrada RF1-RF7 exposats per HTTP
3. Client / UI Un client senzill (Blazor, o una consola amb HttpClient) que consumeixi l'API de la Iteració 2 Verificació d'extrem a extrem de RF1-RF7 des de fora del procés de l'API
4. Poliment Proves d'integració, logging, checklist de qualitat, desplegament Requisits no funcionals de l'apartat 2

Aquesta divisió en iteracions no és arbitrària: cadascuna depèn exclusivament de l'anterior, i cadascuna és, per si mateixa, quelcom verificable —una API que respon correctament a curl, encara que no tingui client encara, ja és un resultat tangible de la Iteració 2, no una feina a mitges sense cap valor propi.

  1. Estimació bàsica de tasques per iteració

Una estimació no necessita ser precisa al minut per ser útil; n'hi ha prou de donar una idea relativa d'esforç que ajudi a prioritzar i a detectar per endavant en quina iteració és més probable encallar-se:

Iteració Tasques principals Esforç relatiu
1. Domini + Persistència Revisar que les quatre implementacions d'IRepositoriBiblioteca (Mòdul 8) segueixen compilant; triar-ne una per a producció Baix (ja construït, només verificació)
2. API Estructura de solució, registre de DI, 5-7 endpoints (un per requisit funcional) Mitjà-alt (és la iteració amb més codi nou)
3. Client / UI Un component o pantalla per cas d'ús principal (catàleg, préstec, devolució) Mitjà
4. Poliment Proves d'integració, logging, checklist, Dockerfile, configuració per entorn Mitjà

La iteració amb més esforç relatiu (l'API) és, precisament, la que més es recolza en la feina ja feta al Mòdul 8: la major part d'aquesta "càrrega" és ensamblatge i registre de serveis, no lògica nova per inventar des de zero.

  1. Elecció definitiva de tecnologies

Amb els requisits ja clars, toca fixar, sense ambigüitat, quina tecnologia concreta es farà servir a cada capa —resumint les decisions ja presentades o comparades en mòduls anteriors:

Capa Tecnologia triada Mòdul on es va explicar
Domini Classes C# ja existents (MaterialBibliotecari, Llibre, Revista, Soci, Prestec) Mòdul 3
Abstracció de persistència IRepositoriBiblioteca Mòdul 8 (Lliçó 3)
Persistència concreta en producció Entity Framework Core sobre SQLite (RepositoriEntityFramework + BibliotecaDbContext) Mòdul 5
Injecció de dependències Contenidor de serveis d'ASP.NET Core (AddScoped/AddSingleton/AddTransient) Mòdul 8 (Lliçó 3)
API ASP.NET Core Minimal APIs Mòdul 7
Client Blazor (o consumidor HttpClient senzill) Mòdul 7, Mòdul 5
Proves xUnit + Moq Mòdul 8 (Lliçó 4)
Metadades externes HttpClient contra un servei extern simulat Mòdul 5

L'elecció d'Entity Framework Core (en comptes de text, JSON o SQLite amb ADO.NET pur) com a persistència de producció respon a un motiu concret: és l'única de les quatre opcions del Mòdul 5 pensada per escalar còmodament a mesura que el model de dades creixi, i s'integra de forma natural amb el contenidor de DI d'ASP.NET Core mitjançant AddDbContext (ja vist a 08-03, apartat 7). Res no impedeix, però, substituir-la per qualsevol de les altres tres en qualsevol moment: aquesta és, precisament, la garantia que ofereix IRepositoriBiblioteca.

Errors Comuns i Consells

  • Confondre requisits funcionals amb tasques d'implementació: "fer servir Entity Framework Core" no és un requisit funcional (no descriu què fa el sistema per a l'usuari), és una decisió tècnica de l'apartat 5; mantenir les dues coses separades evita llistes de requisits confuses.
  • Saltar-se els requisits no funcionals per semblar "menys concrets": són tan reals com els funcionals, només que es verifiquen d'una altra manera (revisió contínua, checklist) en comptes d'amb un cas d'ús puntual.
  • Planificar iteracions que depenen les unes de les altres de forma circular: si la Iteració 3 (Client) necessités canvis a la Iteració 1 (Domini) per funcionar, la planificació té un problema d'ordre; revisa que cada iteració només depengui de les anteriors, mai de les següents.
  • Consell: si una iteració sembla "massa gran" en estimar-la, és bon senyal que es pot dividir en dues iteracions més petites, cadascuna amb el seu propi resultat verificable.

Exercicis

  1. Per a cadascun dels set requisits funcionals (RF1-RF7) de la taula de l'apartat 1, indica en quina iteració de l'apartat 3 es cobreix principalment i quin endpoint HTTP (verb + ruta) esperaries que l'implementi a la Iteració 2.

  2. Un company d'equip proposa afegir, a mig fer la Iteració 2, un requisit nou: "permetre reservar un llibre que no està disponible, perquè quedi apartat quan es retorni". Explica per què, segons els criteris de planificació d'aquesta lliçó, aquest requisit s'hauria d'anotar per a una futura iteració en comptes d'afegir-se immediatament a la Iteració 2 en curs.

Solucions

Requisit Iteració Endpoint aproximat
RF1 (alta de material) 2 POST /libros
RF2 (baixa de material) 2 DELETE /libros/{isbn}
RF3 (cerca) 2 GET /libros?busqueda=...
RF4 (alta de soci) 2 POST /socios
RF5 (préstec) 2 POST /prestamos
RF6 (devolució) 2 POST /prestamos/{id}/devolucion
RF7 (metadades externes) 2 GET /libros/{isbn}/metadatos

Afegir un requisit nou a mig fer una iteració en curs trenca el principi central de la planificació per fases: cada iteració ha de lliurar un abast tancat i verificable abans de passar a la següent. Acceptar el canvi immediatament allargaria la Iteració 2 de forma impredictible i retardaria la resta del pla; el correcte és anotar la idea (per exemple, com a "Iteració 5: reserves", fora de l'abast ja tancat d'aquest projecte final) i continuar amb el que ja estava planificat, igual que es faria amb qualsevol funcionalitat nova proposada durant el desenvolupament, tal com ja s'ha advertit a la lliçó anterior.

Conclusió

Aquesta lliçó ha convertit l'abast general de la Lliçó 1 en quelcom molt més concret: set requisits funcionals traçables a codi ja existent, un conjunt de requisits no funcionals que es vigilen de forma contínua, un pla en quatre iteracions petites amb dependències clares entre elles, una estimació relativa d'esforç, i l'elecció definitiva de tecnologia a cada capa. Amb aquest pla ja tancat, la lliçó següent, Implementació, deixa de planificar i comença a ensamblar: construirà l'estructura de solució amb diversos projectes, registrarà IRepositoriBiblioteca i Biblioteca al contenidor de DI d'ASP.NET Core, i exposarà els endpoints corresponents a cadascun dels set requisits d'aquesta lliçó.

Curs de Programació en C#

Mòdul 1: Introducció al C#

Mòdul 2: Estructures de Control

Mòdul 3: Programació Orientada a Objectes

Mòdul 4: Conceptes Avançats de C#

Mòdul 5: Treballant amb Dades

Mòdul 6: Temes Avançats

Mòdul 7: Construcció d'Aplicacions

Mòdul 8: Bones Pràctiques i Patrons de Disseny

Mòdul 9: Projecte Final

© Copyright 2026. Tots els drets reservats