Richiamo all’architettura dell’app Flutter
Obiettivo
Strutturare correttamente il progetto per facilitare manutenzione, riuso, testing e scalabilità.
Perché serve un’architettura?
- Codice più leggibile
- Facile separare UI e logica
- Collaborazione tra team
- Scalabilità e test automatizzati
Struttura a cartelle base
Cartella | Contenuto |
---|---|
lib/screens/ | Le schermate (UI) |
lib/models/ | Strutture dati (classi, DTO, entity) |
lib/services/ | Chiamate API, DB, Firebase |
lib/widgets/ | Componenti riutilizzabili |
lib/providers/ | Logica di stato se si usa Provider |
In alternativa:
lib/feature/nome/
per struttura modulare (feature-based)
Separation of concerns
Ogni parte del codice ha un singolo scopo:
Livello | Responsabilità |
---|---|
UI (screens) | Visualizza e riceve input |
Logic | Gestisce eventi, stato, validazione |
Data layer | Interroga API, DB, storage |
Clean Architecture base
Strato | Descrizione |
---|---|
Presentation | UI + ViewModel |
Domain | Entità, UseCases, logica pura |
Data | Repository, sorgente dati (API, DB, Firebase) |
Vantaggi:
- Codice testabile
- Decoupling
- Manutenibilità nel lungo periodo
Esempio pratica: app Note
Cartella | Cosa contiene |
---|---|
screens/note_list.dart | UI della lista note |
models/note.dart | Modello Note |
services/note_api.dart | Funzione per caricare/salvare |
providers/note_provider.dart | Logica con ChangeNotifier |
Consigli
Usa extension
o helper
per pulire la UI
- Extension: aggiungi funzionalità a tipi esistenti per scrivere codice più leggibile.
extension Spacing on num {
SizedBox get h => SizedBox(height: toDouble());
SizedBox get w => SizedBox(width: toDouble());
}
Column(
children: [
Text('Titolo'),
16.h, // invece di SizedBox(height: 16)
Text('Descrizione'),
],
)
- Helper: funzioni riutilizzabili per widget personalizzati.
//File: nome_helper.dart
Widget customButton(String label, VoidCallback onPressed) {
return ElevatedButton(
onPressed: onPressed,
child: Text(label.toUpperCase()),
);
}
//File:screen
customButton("Login", () => print("Premuto"));
Non mischiare setState
, Provider
, Bloc
, ecc.
Usare troppi approcci per la gestione dello stato nello stesso progetto crea confusione, rende il debug più difficile e complica l’onboarding di altri sviluppatori.
Scegli un paradigma coerente per tutto il progetto, ed eventualmente usa setState
solo per widget locali molto semplici.
- Nomina coerente (es.
NoteService
,NoteScreen
,NoteModel
) - Ogni file dovrebbe contenere una sola responsabilità