---
title: ASIX M3. [UF2]. Aplicació amb menú.
tags: asix, programació, funcions, programació modular
---
# ASIX1 M03: Aplicació amb menú
[vincle a font en MarkDown](https://hackmd.io/@JdaXaviQ/HkacdjUpj)
---
# 0. La app.
La nostra app consistirà en una aplicació de consola que mostrarà un menú cada entrada del menú estarà numerada i premen el nombre que acompanya a la entrada del menú, realitzarem una funcionalitat o una altra.
## Històries d'usuari (funcionalitat de la app).
|Id | Descripció | Importancia | Càrrega de feina|
|---|---|---|---|
|1 | Només començar i justament desprès de realitzar qualsevol funcionalitat que no sigui la de sortir, la aplicació mostrarà un menú on es mostrin les tasques que es poden realitzar. El menú contindrà les següents entrades: '0. Sortir' - '1. Crida' - '2. Saluda' - '3. Insulta' - '4. Acomida't | 100 | 5|
|2 | [0. Sortir] Si l'usuari tria la entrada 0 del menú: finalitzarà la aplicació | 80 | 2 |
|3 | [1. Crida] Si l'usuari tria la entrada 1 del menú: La aplicació escriurà: 'AAAAAAAAH!!!'| 80 | 2 |
|4 | [2. Saluda] Si l'usuari tria la entrada 2 del menú: La aplicació escriurà: 'Hola!'| 80 | 2 |
|5 | [3. Insulta] Si l'usuari tria la entrada 3 del menú: La aplicació escriurà: 'Brètol!'| 80 | 2 |
|6 | [4. Acomiada't] Si l'usuari tria la entrada 4 del menú: La aplicació escriurà: 'A10!'| 80 | 2 |
# 1. La funció main.
```mermaid
flowchart TD
id1([comença]) --> id4{sortir?}
id2[mostra_menu] --> demana_opcio --> procesa_opcio --> id4
id3([acaba])
id4 --> id2
id4 --> id3
```
A partir d'ara ens hem d'acostumar a que cada funció només farà una cosa. Hauríem de poder descriure què fa cada funció sense utilitzar la conjunció 'i'.
Així que en aquesta aplicació, la nostra funció 'main()' gestionarà el fluxe.
Una possible implementació de la nostra app amb la funció main desenvolupada, pot ésser la següent:
```python=
#!/usr/bin/python3
# -*- coding = utf-8 -*-
"""
menu.py:
Aplicació que mostra com implementar
un programa de consola amb menú utilitzant
programació modular.
"""
def mostra_menu():
# TODO
raise NotImplementedError("Encara no implementat")
def llegeix_opcio():
# TODO
raise NotImplementedError("Encara no implementat")
def procesa_opcio(n):
# TODO
raise NotImplementedError("Encara no implementat")
def main():
opcio = None
while opcio != 0:
mostra_menu()
opcio = llegeix_opcio()
procesa_opcio(opcio)
if __name__ =='__main__':
main()
```
Pareu-vos un moment i compareu la implementació de la funció main() amb el diagrama anterior.
1. Fixeu-vos com el bucle main implementa al mateix temps la fletxa que va de la operació 'procesa_opcio' al condicional 'sortir?' i com la condició del while decideix si sortim o no de la aplicació.
2. Pareu atenció a que cada capsa rectangular del diagrama de flux es correspon unívocament amb una funció del programa.
3. Noteu que l'ordre i flux del programa es gestiona dins de la funció main().
# 2. El menú.
El menú en si mateix no ha de ser més que una informació unidireccional cap a l'usuari. Informem de quines funcionalitats ofereix la nostra app i com les hem de demanar.
Consegüentment pot consistir en una sèrie de prints amb la info dessitjada.
```python=
def mostra_menu():
print("-------------")
print("0. Sortir")
print("1. Crida")
print("2. Saluda")
print("3. Insulta")
print("4. Acomiadat")
print("-------------")
```
# 3. Obtenir la opció triada per l'usuari.
Aquesta és la funció més senzilla del nostre programa, tan que només necessitem una línia de codi per a implementar-la.
```python=
def llegeix_opcio():
return int(input("Tria la opció dessitjada: "))
```
# 4. Procesar la opció triada per l'usuari.
Aquí la cosa es complica; la nostra aplicació és molt senzilla, només hem d'escriure uns missatges per pantalla segons l'elecció de l'usuari, però en una aplicació estàndar cada opció pot consistir en una mini aplicació per si mateixa. És per aquesta raó que cada opció es convertirà com a mínim en una nova funció a desenvolupar.
Veiem un exemple d'implementació:
```python=
def sortir():
pass
def cridar():
print("AAAAAAAAH!!!")
def saludar():
print("Hola!")
def insultar():
print("Brètol!")
def acomiadar():
print("A10!")
def procesa_opcio(n):
if n == 0:
sortir()
elif n == 1:
cridar()
elif n == 2:
saludar()
elif n == 3:
insultar()
elif n == 4:
acomiadar()
else:
raise ValueError(f"Opció incorrecta: {n=}")
```
# 5. Protegint el nostre codi dels errors de l'usuari.
Quan l'usuari entra una opció incorrecte es produeixen excepcions que ens cas de no ser degudament tractades, el nostre programa 'petaria' i finalitzaria sense control. Per a evitar aquest efecte no dessitjat hem de capturar les excepcions produides al nostre codi tal i com varem aprendre a la UF1.
Modificarem la nostra funció main() per a capturar les excepcions que es puguin produïr mentre s'executa la nostra app.
```python=
def main():
opcio = None
while opcio != 0:
mostra_menu()
try:
opcio = llegeix_opcio()
procesa_opcio(opcio)
except ValueError as ve:
print(str(ve))
```