A Definició del projecte va quedar tancat el què: un document d'una pàgina amb el problema, l'abast en calaixos MoSCoW, els requisits numerats i els seus criteris d'acceptació. Ara toca el com, i encara no toca teclejar codi. Dissenyar és prendre per avançat les decisions cares: quines entitats existeixen i si són classes o diccionaris, en quin format es desen les dades, com es reparteix el programa en mòduls, què veu l'usuari a la pantalla i quins algorismes calen. Cadascuna d'aquestes decisions, presa sobre paper, costa deu minuts; presa a mitja implementació costa una tarda de reescriptura. Al final de la lliçó tindràs també el pla de treball: la llista de tasques petites, estimades i ordenades, que converteix «fer un projecte» en «fer la tasca següent».
Contingut
- Què és dissenyar i quant disseny n'hi ha prou
- Model de dades: entitats i atributs
- Diccionari, classe o llista?
- El diagrama de classes del projecte
- Persistència: triar el format del fitxer
- Arquitectura en capes
- Disseny de la interfície
- Algorismes no trivials en pseudocodi
- Planificació temporal per sessions
- Preparar el repositori i l'entorn
- Errors comuns i consells
- Exercicis
- Conclusió
- Què és dissenyar i quant disseny n'hi ha prou
Dissenyar és decidir la forma del programa abans de construir-lo: les seves peces, les seves responsabilitats i com es parlen entre elles. La pregunta raonable és quant. La resposta, per a un projecte d'aquesta mida, és: el just per poder començar a programar sense dubtes la primera hora, i prou.
Un disseny suficient per al teu projecte final cap en tres o quatre fulls i conté sis coses:
| Peça del disseny | Pregunta que respon | Format |
|---|---|---|
| Model de dades | Quines coses existeixen i què en deso, de cadascuna? | Taula d'entitats i atributs |
| Estructura triada | Classe, diccionari o llista per a cada entitat? | Decisió justificada en una línia |
| Persistència | On i com es desen? | Format de fitxer amb un exemple real |
| Arquitectura | Quins mòduls hi ha i de què depèn cadascun? | Diagrama de dependències |
| Interfície | Què veu i tria l'usuari? | Mapa del menú i esbós de pantalles |
| Algorismes | Quines parts no són òbvies? | Pseudocodi amb prova d'escriptori |
El que no és disseny a aquest nivell: escriure totes les funcions per endavant, decidir el nom de cada variable o fer diagrames de vint caixes. Això s'anomena paràlisi per anàlisi i consumeix el temps del projecte. Si dubtes entre dues opcions i cap no és clarament pitjor, tria la més simple i continua: al mòdul 8 vas aprendre a refactoritzar, i refactoritzar existeix precisament perquè cap disseny inicial no és perfecte.
- Model de dades: entitats i atributs
Una entitat és un substantiu important del teu domini: alguna cosa de la qual deses diversos exemplars i de la qual vols saber coses. La manera més ràpida de trobar-les és subratllar els substantius dels requisits de 09-01. A LesMevesDespeses, els RF parlen de despesa, ingrés, import, categoria, data, concepte i mes.
D'aquesta llista cal separar el gra de la palla amb dues preguntes:
- En deso molts exemplars, d'això? «Despesa» sí; «mes» no, és només un criteri de filtratge.
- Té atributs propis més enllà del seu nom? «Categoria» a LesMevesDespeses només té nom, així que no cal que sigui una entitat: n'hi ha prou amb una cadena dins del moviment.
Aquest segon descart és el que més simplifica un primer projecte. Aplicat a LesMevesDespeses queda una sola entitat real:
| Entitat | Atribut | Tipus | Obligatori | Regles |
|---|---|---|---|---|
| Moviment | id |
int |
Sí | Automàtic, únic, correlatiu |
data |
date |
Sí | No futura; buit = avui | |
concepte |
str |
Sí | 1 a 60 caràcters, sense espais sobrants | |
quantitat |
float |
Sí | Diferent de 0; negatiu = despesa, positiu = ingrés | |
categoria |
str |
Sí | En minúscules; una de les categories conegudes |
Fixa't en la decisió de l'última fila de la quantitat: en lloc d'un camp tipus amb els valors "despesa" o "ingres", el signe de l'import codifica el tipus. És una decisió de disseny amb conseqüències bones —el saldo del mes és una simple suma— i una conseqüència dolenta: cal recordar-la i documentar-la, perquè no és evident. Aquest tipus de decisió és exactament el que et preguntaran a Presentació del projecte, així que anota-la ara amb el seu perquè.
A més de les entitats, defineix les constants del domini: a LesMevesDespeses, les categories permeses.
És una tupla i no una llista perquè no canvia durant l'execució (05-04), i és en un únic lloc perquè afegir una categoria sigui editar una línia, no buscar per tot el codi.
- Diccionari, classe o llista?
Amb les entitats identificades cal triar la seva representació en Python, aplicant la taula de decisió de Tuples i estructures imbricades i el que vas aprendre a De les dades als objectes:
| Fes servir... | Quan... | A LesMevesDespeses |
|---|---|---|
| Llista | Només hi ha una seqüència de valors del mateix tipus, sense nom propi | Els imports d'un mes per sumar-los |
| Tupla | Un grup petit i fix de valors que no canvia | CATEGORIES; el parell (categoria, total) d'un informe |
| Diccionari | Camps amb nom, estructura que canvia o dades que vénen de JSON | El resultat d'agrupar per categoria: {"menjar": -212.4, ...} |
| Classe | Les dades tenen comportament: es validen, es formaten, es comparen | Moviment |
La regla que resol gairebé tots els dubtes és aquesta: si a més de desar dades escriuràs funcions que operen sempre sobre aquestes dades, és una classe. A LesMevesDespeses, un moviment es valida en crear-se (import diferent de zero, categoria coneguda, data no futura), es mostra formatat en una línia de taula i es compara per data per ordenar. Tres comportaments: classe, sens dubte.
I hi ha una segona classe que no és una entitat del domini però sí una peça del disseny, exactament com Agenda a TascaFàcil: la col·lecció amb lògica. Llibre és una entitat; Biblioteca és la classe que sap cercar, filtrar i resumir. A LesMevesDespeses es diu Quadern.
- El diagrama de classes del projecte
classDiagram
class Moviment {
+int id
+date data
+str concepte
+float quantitat
+str categoria
+es_despesa() bool
+to_dict() dict
+from_dict(d) Moviment
+__str__() str
}
class Quadern {
-list moviments
-int seguent_id
+afegir(mov) Moviment
+eliminar(id) bool
+cercar(id) Moviment
+del_mes(aaaa_mm) list
+total_per_categoria(aaaa_mm) dict
+saldo(aaaa_mm) float
+__len__() int
+__iter__()
}
class MovimentInvalid {
<<exception>>
}
Quadern "1" o-- "*" Moviment : conte
Moviment ..> MovimentInvalid : llanca
El diagrama diu tres coses d'un cop d'ull. Primera, que Quadern conté moviments: és composició (07-03), la mateixa relació que Agenda tenia amb Tasca. Segona, que la validació viu a Moviment i llança la seva pròpia excepció MovimentInvalid, igual que TascaInvalida a TascaFàcil: les dades es protegeixen a si mateixes i cap altra capa no pot crear un moviment invàlid. I tercera, una cosa que es veu pel que no hi apareix: ni Moviment ni Quadern no saben res de fitxers ni de print. Aquesta absència és l'arquitectura de l'apartat 6 dibuixada per omissió.
Dibuixa el teu diagrama amb dues o tres classes com a màxim. Si te'n surten sis, gairebé segur que unes quantes són atributs disfressats de classe.
- Persistència: triar el format del fitxer
Reprenent Desar dades en fitxers, tens tres opcions realistes:
| Format | Va bé quan | Va malament quan | Cost |
|---|---|---|---|
| Text pla | Les dades són línies soltes sense estructura (notes, log) | Hi ha camps per separar; arriben comes o salts de línia | Mínim, però et toca inventar el format |
| CSV | Registres plans i uniformes que algú obrirà al full de càlcul | Hi ha llistes dins d'un camp o estructures imbricades | Baix; csv de la biblioteca estàndard |
| JSON | Hi ha imbricació, camps opcionals o tipus variats | El fitxer s'ha d'obrir a Excel sense conversió | Baix; json de la biblioteca estàndard |
Per a LesMevesDespeses: JSON com a format principal, CSV com a exportació. El perquè és el que has de saber defensar: JSON conserva els tipus (un float torna com a float, no com la cadena "12.5"), admet créixer amb camps opcionals sense trencar els fitxers antics i json.load valida l'estructura per tu. CSV entra només on té avantatge real —RF-7, obrir el mes en un full de càlcul—, i com a sortida d'un sol sentit: s'exporta, no s'importa, cosa que estalvia tota la feina de reconstruir tipus des de text.
I ara l'important: escriu el format concret amb un exemple real abans de programar res. Aquest és despeses.json:
{
"versio": 1,
"seguent_id": 4,
"moviments": [
{"id": 1, "data": "2026-08-01", "concepte": "Compra setmanal", "quantitat": -62.35, "categoria": "menjar"},
{"id": 2, "data": "2026-08-01", "concepte": "Abonament transport", "quantitat": -32.0, "categoria": "transport"},
{"id": 3, "data": "2026-08-03", "concepte": "Nomina agost", "quantitat": 1450.0, "categoria": "ingressos"}
]
}Tres detalls deliberats, i tots tres tenen justificació:
versioal principi. Avui no serveix de res; el dia que canviïs el format, el teu codi podrà llegir els fitxers vells en lloc de trencar-se. Costa una línia.seguent_iddesat, no recalculat. Si el calculessis com «el màxim id més un», en esborrar l'últim moviment reutilitzaries el seu id, i un id reutilitzat és una font de confusió.- Dates com a cadena
AAAA-MM-DD. JSON no té tipus data. Aquest format és l'estàndard ISO 8601, es converteix ambdate.fromisoformat()i, a més, ordena alfabèticament igual que cronològicament, cosa que simplifica filtres i ordenacions.
- Arquitectura en capes
Un programa se separa en capes per la raó que ja coneixes de Descompondre un programa en funcions i Mòduls, paquets i importacions: cada peça té una única raó per canviar. Si el càlcul del total per categoria estigués barrejat amb els print, no el podries provar sense simular la pantalla, ni canviar la presentació sense arriscar-te a tocar el càlcul.
Les quatre capes i el seu fitxer:
| Capa | Fitxer | Responsabilitat | Què té prohibit |
|---|---|---|---|
| Model | model.py |
Entitats i les seves regles de validació | print, input, fitxers |
| Lògica | quadern.py |
Col·lecció i operacions: afegir, cercar, filtrar, agregar totals | print, input, fitxers |
| Magatzem | magatzem.py |
Llegir i escriure JSON i exportar CSV | print, input |
| Interfície | interficie.py |
Menú, input, print, format de pantalla |
Càlculs del domini |
flowchart TD
M["__main__.py<br/>arrencada"] --> I["interficie.py<br/>menu i pantalles"]
I --> C["quadern.py<br/>logica de colleccio"]
I --> A["magatzem.py<br/>JSON i CSV"]
A --> C
C --> MO["model.py<br/>Moviment i validacio"]
A --> MO
Les fletxes van sempre cap avall: la interfície coneix la lògica, la lògica coneix el model, i el model no coneix ningú. Cap fletxa no puja. Aquesta regla, que sembla trivial, és la que permet escriure proves del model i de la lògica sense tocar la pantalla, i és la mateixa estructura que ja has vist funcionant a TascaFàcil (model.py, agenda.py, magatzem.py, interficie.py, __main__.py).
Afegeix __init__.py perquè el directori sigui un paquet i __main__.py per poder executar python -m lesmevesdespeses, exactament com es va fer a 07-04.
- Disseny de la interfície
Un menú mal dissenyat es nota a la demostració. Dibuixa el mapa abans de programar-lo:
flowchart TD
Menu["MENU PRINCIPAL"] --> O1["1 Registrar despesa"]
Menu --> O2["2 Registrar ingres"]
Menu --> O3["3 Moviments del mes"]
Menu --> O4["4 Resum per categoria"]
Menu --> O5["5 Esborrar moviment"]
Menu --> O6["6 Exportar mes a CSV"]
Menu --> O0["0 Sortir"]
O1 --> Menu
O2 --> Menu
O3 --> Menu
O4 --> Menu
O5 --> Conf["Confirmar s/n"] --> Menu
O6 --> Menu
O0 --> Fin["Desar i acabar"]
Tres regles de disseny que es llegeixen en aquest mapa: tot camí torna al menú (no deixis mai l'usuari en un lloc sense sortida), una sola pantalla de profunditat (res de submenús en un primer projecte) i les accions destructives demanen confirmació. L'opció 0 per sortir és convenció: el 0 és sempre al mateix lloc encara que la llista creixi.
Després esbossa cada pantalla en text, tal com la vols veure. No és cosmètica: en escriure l'esbós descobreixes quines dades necessites calcular.
=========================================
RESUM DE 2026-08 (4)
=========================================
menjar -212,40 EUR 38,1 %
transport -132,00 EUR 23,7 %
llar -98,50 EUR 17,7 %
oci -57,20 EUR 10,3 %
altres -57,00 EUR 10,2 %
-----------------------------------------
Despeses -557,10 EUR
Ingressos +1450,00 EUR
SALDO +892,90 EUR
=========================================Aquest esbós acaba de generar tres requisits de càlcul que no eren explícits: cal el percentatge sobre el total de despeses, cal ordenar de major a menor despesa i cal separar despeses d'ingressos al peu. Dibuixar la pantalla és la manera més barata de trobar feina oculta.
- Algorismes no trivials en pseudocodi
La major part del teu projecte és codi evident. Però sempre hi ha dos o tres punts on no ho és, i aquests —només aquests— s'escriuen abans en pseudocodi, amb la tècnica de Del problema a l'algorisme. A LesMevesDespeses són dos.
Algorisme 1: total per categoria d'un mes.
FUNCIO total_per_categoria(moviments, mes):
totals <- diccionari buit
PER A CADA m EN moviments:
SI m.data comenca per mes LLAVORS
totals[m.categoria] <- totals.obtenir(m.categoria, 0) + m.quantitat
RETORNA totals ordenat per valor ascendentDues decisions concretes aquí. La comparació per prefix de cadena ("2026-08-03" comença per "2026-08") funciona perquè el format ISO ho permet, la decisió de l'apartat 5 pagant dividends. I obtenir(clau, 0) és el patró d'acumulació en diccionari de Diccionaris i conjunts, que evita el if clau not in totals. L'ordre ascendent per valor posa primer els imports més negatius, és a dir, les despeses més grans, que és el que demana l'esbós de l'apartat 7.
Prova d'escriptori amb quatre moviments i mes = "2026-08":
| Pas | Moviment | Coincideix? | totals després |
|---|---|---|---|
| 1 | 2026-07-30, -20,00, menjar | No | {} |
| 2 | 2026-08-01, -62,35, menjar | Sí | {menjar: -62,35} |
| 3 | 2026-08-01, -32,00, transport | Sí | {menjar: -62,35, transport: -32,00} |
| 4 | 2026-08-04, -15,00, menjar | Sí | {menjar: -77,35, transport: -32,00} |
Resultat ordenat: [("menjar", -77,35), ("transport", -32,00)]. Correcte: la despesa de juliol queda fora i les dues compres de menjar s'acumulen a la mateixa clau. Aquesta taula, feta en tres minuts sobre paper, és la que evita descobrir a la demostració que el filtre de mes agafava també l'any equivocat.
Algorisme 2: assignar el següent identificador.
FUNCIO afegir(quadern, moviment):
moviment.id <- quadern.seguent_id
quadern.seguent_id <- quadern.seguent_id + 1
afegir moviment a la llista
RETORNA movimentSembla massa simple per escriure'l, i precisament per això convé: escrit així es veu que el comptador s'ha de persistir amb les dades (apartat 5) i que hi ha un cas límit, la primera arrencada sense fitxer, on seguent_id val 1.
- Planificació temporal per sessions
Un projecte de 15 a 25 hores no es planifica «per setmanes»: es parteix en tasques d'una a tres hores, cadascuna amb un resultat visible. Si una tasca no cap en tres hores, parteix-la; si no la saps estimar, és que encara no l'entens i cal dissenyar-la una mica més.
| # | Tasca | Est. | Depèn de | Resultat visible |
|---|---|---|---|---|
| T1 | Repositori, entorn, esquelet que arrenca i surt | 1 h | — | python -m lesmevesdespeses mostra el menú i surt |
| T2 | Classe Moviment amb validació i MovimentInvalid |
2 h | T1 | Es crea un moviment des de l'intèrpret |
| T3 | tests/test_model.py |
1 h | T2 | pytest en verd |
| T4 | Classe Quadern: afegir, cercar, eliminar, __len__ |
2 h | T2 | Alta i baixa des de l'intèrpret |
| T5 | magatzem.py: desar i carregar JSON |
2 h | T2 | El fitxer es crea i es rellegeix |
| T6 | tests/test_magatzem.py amb tmp_path |
1 h | T5 | Cicle desar/carregar provat |
| T7 | Interfície: menú, registrar despesa (RF-1) de cap a cap | 3 h | T4, T5 | Primera funcionalitat completa |
| T8 | Llistar moviments del mes (RF-3) | 2 h | T7 | Pantalla de llistat |
| T9 | total_per_categoria i saldo + proves (RF-4) |
3 h | T4, T3 | Pantalla de resum |
| T10 | Registrar ingrés (RF-2) i esborrar (RF-5) | 2 h | T7 | Menú complet dels Must |
| T11 | Exportar CSV (RF-7) | 2 h | T8 | Fitxer obert al full de càlcul |
| T12 | Robustesa: try/except, logging, revisió d'entrades |
2 h | T10 | Cap entrada no trenca el programa |
| T13 | README, docstrings, black i ruff, etiqueta v1.0 |
2 h | T12 | Repositori presentable |
Total estimat: 25 hores. I ara la regla que gairebé ningú no aplica la primera vegada: multiplica la teva estimació per 1,5. No perquè siguis lent, sinó perquè totes les estimacions de principiant ometen el temps de buscar errors. Si el resultat no cap en el temps de què disposes, no acceleris: treu un Should.
flowchart LR
H1["Fita 1<br/>Arrenca i surt<br/>T1"] --> H2["Fita 2<br/>Model provat<br/>T2 T3"]
H2 --> H3["Fita 3<br/>Desa i carrega<br/>T4 T5 T6"]
H3 --> H4["Fita 4<br/>Primer RF complet<br/>T7"]
H4 --> H5["Fita 5<br/>Tots els Must<br/>T8 T9 T10"]
H5 --> H6["Fita 6<br/>v1.0 presentable<br/>T11 T12 T13"]
El principi que ordena tot això: l'esquelet que arrenca ha d'existir el primer dia. Un python -m lesmevesdespeses que mostri el menú i surti, encara que les opcions no facin res, resol de cop l'entorn, l'estructura del paquet i l'execució, que són justament els problemes que bloquegen qui comença. A partir d'aquí el programa no torna a estar trencat mai: cada tasca el deixa executable.
- Preparar el repositori i l'entorn
Abans de la primera línia de codi, deixa el terreny a punt. És la tasca T1 i són quinze minuts, reprenent Entorns de desenvolupament i Control de versions:
mkdir lesmevesdespeses-projecte && cd lesmevesdespeses-projecte
python -m venv .venv
source .venv/bin/activate # a Windows: .venv\Scripts\activate
pip install pytest black ruff
pip freeze > requirements-dev.txt
git init
mkdir lesmevesdespeses tests
touch lesmevesdespeses/__init__.py lesmevesdespeses/__main__.py lesmevesdespeses/model.py
touch lesmevesdespeses/quadern.py lesmevesdespeses/magatzem.py lesmevesdespeses/interficie.pyEl .gitignore, amb el que no ha d'entrar mai al repositori:
Repara en despeses.json: les dades personals no es versionen. Al repositori hi va dades_exemple.json amb moviments inventats, i el fitxer real de treball queda fora. És el mateix criteri pel qual tascafacil.log estava exclòs a TascaFàcil.
I el primer commit, que ja deixa constància del disseny:
Errors Comuns i Consells
- Dissenyar de més. Diagrames de quinze classes, jerarquies d'herència per si de cas, una capa d'abstracció sobre el fitxer «per si algun dia és una base de dades». Aquest dia no arribarà en aquest projecte. Dissenya per al que hi ha al calaix Must.
- Convertir en classe tot el que es mou. Si una entitat només té nom i cap comportament —com
categoriaa LesMevesDespeses—, és una cadena. Una classe d'un sol atribut gairebé sempre sobra. - Triar el format de dades per costum. CSV sembla més simple fins que necessites desar una llista dins d'un camp o recuperar un número que va tornar com a cadena. Tria amb la taula de l'apartat 5, no per inèrcia.
- Saltar-se l'esbós de pantalles. És el pas que més feina oculta descobreix: a LesMevesDespeses van aparèixer tres càlculs que cap requisit no esmentava.
- Planificar en tasques grans. «Fer la interfície» no és una tasca, és un mes de sensació de no avançar. Una tasca és «registrar una despesa de cap a cap»: tres hores i un resultat que es veu.
- Consell: escriu el perquè de cada decisió. Una línia per decisió al
DEFINICIO.md(«JSON perquè conserva tipus i admet camps nous»). A 09-04 hauràs de defensar-les i no te'n recordaràs. - Consell: si dubtes entre dos dissenys, tria el que sigui més fàcil de desfer. És gairebé sempre el més simple, i ja saps refactoritzar (08-05).
Exercicis
Continuen el projecte que vas definir a 09-01. Desa els resultats en un DISSENY.md al costat del DEFINICIO.md.
Exercici 1: Model de dades i diagrama de classes
Subratlla els substantius dels teus requisits i munta la taula d'entitats amb els seus atributs, tipus, obligatorietat i regles de validació. Justifica en una línia per entitat si serà classe, diccionari o llista. Dibuixa el diagrama de classes en mermaid, incloent-hi la classe col·lecció i l'excepció pròpia. Màxim tres classes.
Exercici 2: Persistència, capes i interfície
Tria el format de fitxer amb la taula de l'apartat 5 i escriu un exemple real del teu fitxer de dades amb tres registres. Reparteix el codi en els mòduls de les quatre capes i dibuixa el diagrama de dependències. Dibuixa el mapa del menú i esbossa en text les dues pantalles més importants del teu programa.
Exercici 3: Algorismes i pla de treball
Identifica els dos o tres algorismes no trivials del teu projecte, escriu-los en pseudocodi i fes una prova d'escriptori d'almenys un amb quatre o cinc dades d'entrada. Després munta la taula de tasques d'una a tres hores amb estimació i dependències, multiplica el total per 1,5 i comprova si cap en el teu temps disponible. Si no hi cap, indica quin Should elimines.
Solucions
Solució 1. Els apartats 2, 3 i 4 són la solució per a LesMevesDespeses: una única entitat Moviment (classe, perquè valida, formata i es compara), la categoria reduïda a cadena, i Quadern com a col·lecció amb lògica. El descart de Categoria com a classe és el punt interessant: només tenia nom. Si el teu projecte necessités pressupost per categoria, la decisió s'invertiria, perquè aleshores sí que tindria atributs i comportament propis. Rúbrica: tens tres classes o menys? Cada classe té almenys dos comportaments que justifiquin ser-ho? Cada atribut té tipus i regla de validació? Hi ha una excepció pròpia per a les dades invàlides?
Solució 2. Apartats 5, 6 i 7. Els criteris que has de poder defensar: JSON perquè hi ha tipus numèrics i el format pot créixer; CSV només com a exportació d'un sentit; les capes separades per poder provar la lògica sense pantalla; el menú d'una sola profunditat amb confirmació en l'esborrat. Rúbrica: l'exemple de fitxer és JSON o CSV vàlid de debò, amb tres registres reals? Totes les fletxes del diagrama de dependències van cap avall, sense cicles? El teu esbós de pantalla t'ha descobert algun càlcul que no havies previst? Si no n'ha descobert cap, mira-te'l una altra vegada: gairebé sempre n'hi ha un.
Solució 3. Apartats 8 i 9. Observa que les tretze tasques de LesMevesDespeses segueixen l'ordre model → proves → lògica → magatzem → interfície → extres, amb T1 (l'esquelet que arrenca) en primer lloc i T7 marcant la fita de la primera funcionalitat completa. Aquest és l'ordre de construcció que desenvolupa Implementació i proves. Rúbrica: cap tasca no passa de tres hores? Cada tasca té un resultat visible i verificable? Hi ha una tasca T1 d'una hora que deixa el programa arrencant? Has aplicat el factor 1,5? El teu pseudocodi és independent de Python, és a dir, el podries traduir a un altre llenguatge?
Conclusió
Dissenyar és prendre per avançat les decisions cares, i per a un projecte d'aquesta mida cap en tres o quatre fulls. El model de dades surt de subratllar els substantius dels requisits i descartar els que no tenen ni exemplars múltiples ni atributs propis; cada entitat es representa com a llista, tupla, diccionari o classe segons la taula de 05-04 i 07-01, amb la regla que allò que a més de dades té comportament és una classe. A les entitats s'hi suma la classe col·lecció —Agenda a TascaFàcil, Quadern a LesMevesDespeses— que concentra la lògica de cercar, filtrar i resumir, i una excepció pròpia per a les dades invàlides.
La persistència es tria amb criteri: text pla per a línies sense estructura, CSV per a registres plans que veurà un full de càlcul, JSON quan hi ha tipus, imbricació o camps que creixeran; i s'escriu el format concret amb un exemple real abans de programar, amb detalls que després estalvien hores —número de versió, comptador d'identificadors persistit i dates en ISO AAAA-MM-DD, que ordenen alfabèticament igual que en el temps—. L'arquitectura en capes reparteix el codi en model, lògica, magatzem i interfície, amb les dependències sempre cap avall i el model sense conèixer ningú, que és el que permet provar sense pantalla. La interfície es dissenya amb un mapa de menú d'una sola profunditat on tot camí torna a l'inici i les accions destructives confirmen, més un esbós en text de cada pantalla que gairebé sempre descobreix càlculs ocults. Els dos o tres algorismes no trivials s'escriuen en pseudocodi i es validen amb una prova d'escriptori abans de traduir-los. I el pla de treball parteix tot en tasques d'una a tres hores amb resultat visible, ordenades per dependència, estimades i multiplicades per 1,5, amb l'esquelet que arrenca com a primeríssima tasca i el repositori i l'entorn preparats abans d'escriure una línia.
Amb el què i el com tancats, ja no queda res que impedeixi començar. A Implementació i proves construirem de debò: l'estratègia incremental que manté el programa sempre executable, l'ordre de construcció capa per capa amb les proves escrites alhora que el codi, què fer quan alguna cosa falla i no saps per què, i la checklist que decideix quan la implementació està acabada.
Fonaments de la Programació
Mòdul 1: Introducció a la Programació
- Què és la programació?
- Història de la programació
- Llenguatges de programació
- Entorns de desenvolupament
- Del problema a l'algorisme
Mòdul 2: Conceptes Bàsics
- Variables i tipus de dades
- Operadors i expressions
- Entrada i sortida de dades
- Conversió de tipus i validació de dades
Mòdul 3: Estructures de Control
Mòdul 4: Funcions i Procediments
- Definició i ús de funcions
- Paràmetres i retorn de valors
- Àmbit de variables
- Descompondre un programa en funcions
- Funcions com a valors: lambda i ordre superior
Mòdul 5: Estructures de Dades
- Llistes i arrays
- Cadenes de caràcters
- Diccionaris i conjunts
- Tuples i estructures imbricades
- Desar dades en fitxers: text, CSV i JSON
Mòdul 6: Algorismes Bàsics
Mòdul 7: Objectes i Organització del Codi
- De les dades als objectes: classes i instàncies
- Atributs, mètodes i constructor
- Col·leccions d'objectes
- Mòduls, paquets i importacions
Mòdul 8: Bones Pràctiques i Eines
- Documentació i comentaris
- Depuració i gestió d'errors
- Control de versions
- Proves automatitzades
- Estil, llegibilitat i refactorització
