1 PROGETTARE SOLUZIONI

1 PROGETTARE SOLUZIONI

Introduzione al concetto di programmazione

Che cosa piace in uno smartphone? Sicuramente il design del dispositivo (hardware), ma soprattutto il software che lo rende interattivo.

Il software è qualcosa di impalpabile, che si potrebbe paragonare al nostro pensiero: esiste, ma senza un supporto hardware che lo contenga (il cervello) non può essere utilizzato.


Per questo motivo l’informatica, pur occupandosi di software, deve sempre tenere in considerazione l’hardware. I programmatori devono occuparsi della logica del software, ma anche dell’input e dell’output.

Il computer è una macchina in grado di eseguire calcoli molto velocemente, ma è compito del programmatore attribuire un significato ai numeri. Per esempio uno smartphone è in grado di generare numeri casuali, ma è compito del programmatore immaginare che essi rappresentino dei dadi lanciati su un tavolo o l’avanzamento di due cavalli durante una corsa.

Oltre a essere creativo, il programmatore deve avere capacità di astrazione per risolvere classi di problemi e non un singolo problema. Per esempio deve programmare una calcolatrice e non un software che sia in grado di sommare solo due numeri (sempre gli stessi).

Programmare semplici app

Oggi esistono dei software didattici (per esempio Scratch, App Inventor) creati per sviluppare il pensiero computazionale, cioè quel processo mentale che consente di individuare un modello astratto di un problema dato, trovarne una soluzione ed esprimerla come una sequenza di istruzioni che possano essere eseguite automaticamente da una macchina.


Le interfacce di questi software sono grafiche, colorate e generalmente gradevoli. I comandi sono intuitivi e si attivano con il mouse. Trascinando i diversi elementi è possibile fingere di essere esperti sviluppatori di app giocando con la programmazione.

La limitazione di non essere ▶ general purpose, tuttavia, rende questi software inadatti a risolvere gran parte dei problemi che, nel mondo reale, vengono gestiti da software generici realizzati utilizzando i linguaggi di programmazione. Inoltre, la semplicità di utilizzo introdotta da questi ambienti nasconde molteplici aspetti che riguardano lo sviluppo dei programmi e la loro interazione con le varie componenti interne del computer.


Per imparare a programmare in modo professionale è necessario entrare nel dettaglio di alcune problematiche di base che riguardano l’hardware (CPU, memoria, periferiche ecc.), che sono intrinsecamente svincolate dall’aspetto estetico delle interfacce o dall’interazione con il mouse, rinunciando, almeno inizialmente, alla gradevolezza di grafica e animazioni.

Per comprendere i concetti fondamentali che riguardano il mondo della programmazione è opportuno adottare alcune accortezze, utilizzando:

  • un personal computer (non uno smartphone o un tablet);
  • un’interfaccia testuale: che elimina i problemi legati alla visualizzazione grafica;
  • una tastiera per l’input: che elimina le problematiche legate alla gestione del clic del mouse;
  • uno schermo per l’output: che elimina le problematiche legate alla gestione di un touch screen;
  • un linguaggio di programmazione adeguato: che metta in evidenza gli aspetti fondamentali legati alla programmazione.

 >> pagina 387 

Dal problema al programma

Quando si impara a programmare per la prima volta è bene “semplificarsi” la vita immaginando che la situazione possa essere rappresentata più o meno come vedi nel seguente disegno, che evidenzia le diverse fasi necessarie per trasformare un problema in un programma.

Problema

Durante questa fase il programmatore incontra l’utente, gli pone delle domande e cerca di comprendere il risultato che si vuole ottenere.

Quando il programmatore ritiene di aver raccolto sufficienti informazioni, passa alla fase di analisi.


esempio

Un utente chiede a un programmatore:
“Vorrei che il computer mi dicesse la somma di due numeri qualunque essi siano.”

 >> pagina 388 

Analisi

Durante questa fase il programmatore pensa a come risolvere il problema, analizzando attentamente quello che gli è stato detto dall’utente. Poiché il modo di ragionare e di approcciare i problemi è estremamente personale, ogni programmatore può affrontare il processo di analisi in modo diverso, in un ordine che non è prefissato né necessariamente sequenziale.

In generale le fasi di analisi sono:

  • “brainstorming”: è il momento in cui il programmatore organizza le idee e immagina le soluzioni.

    Poiché la riflessione del programmatore è un processo personale, è possibile che due ragionamenti completamente diversi fra loro potrebbero essere entrambi corretti. Il programmatore, in questa fase, è libero di creare e seguire il proprio filo logico per trovare una soluzione al problema. Può prendere appunti, disegnare, aiutarsi con alcuni esempi. L’importante è arrivare a comprendere il problema e iniziare a immaginare soluzioni possibili;

  • input: i dati di input sono quelli che entrano nel computer attraverso la tastiera;
  • passaggi logici: sono tutto quello che bisogna fare per ottenere l’output.Normalmente trasformano un input in un output ma, in alcuni problemi, l’input potrebbe anche non esserci (per esempio scrivere il testo “Ciao mondo!” sul monitor);
  • output: i dati di output sono quelli che escono dal computer attraverso il monitor;
  • vincoli: sono tutte le condizioni che devono essere rispettate e che riguardano in particolare l’input, l’output e i passaggi logici.
esempio

Durante la fase di “brainstorming” il programmatore dell’esempio precedente arriva alle seguenti conclusioni:

  • Il computer mi deve dire una somma
  • Una somma si fa con +
  • La somma deve essere fra due numeri
  • I due numeri non li so
  • Il software deve funzionare con qualunque numero
  • Quando proverò il programma, i numeri li sceglierò io

Sulla base di quanto emerso nella fase di “brainstorming” il programmatore arriva a concludere che:

  • La somma è quella da far vedere sullo schermo, alla fine (output)
  • La somma è generica e quindi la calcolo come N + M (passaggi logici)

N e M sono i due numeri da inserire con la tastiera (input)

I vincoli che risultano dall’analisi sono:

  • input: I numeri da inserire devono essere esattamente due, non uno di più, non uno di meno. Come possono essere questi numeri? L’utente mi ha chiesto di considerare solo numeri interi. Quindi vanno bene sia i positivi sia i negativi senza virgola e anche lo zero va bene. E se il programma venisse usato da qualche altro utente che non lo sa? Bisogna fare in modo che il programma informi l’utente generico del fatto che esiste questo vincolo.
  • output: Visto che il risultato è la somma di due numeri interi senza virgola, il risultato S sarà per forza un numero intero senza virgola. Se controllo all’inizio che i due numeri in input rispettino il vincolo di essere numeri interi, allora per l’output non devo controllare niente.
  • passaggi logici: L’addizione è un’operazione che non necessita di controlli particolari. Se fosse una divisione, dovrei controllare che il denominatore dato in input sia diverso da zero, ma per il problema che sto considerando non devo fare controlli.

 >> pagina 389 

Algoritmo

Un algoritmo è una sequenza di istruzioni che descrivono il procedimento che risolve un problema.


Quindi, scrivere un algoritmo significa scrivere tutte le istruzioni che portano alla soluzione del problema.

Un algoritmo può essere scritto a parole (pseudocodice) o, in modo equivalente, usando uno schema (diagramma a blocchi). Una volta scelta la notazione, occorre utilizzarla con precisione, adottando sempre lo stesso formalismo.

esempio

Il programmatore può scrivere sia in pseudocodice sia come diagramma a blocchi.

Un algoritmo deve essere:

  • composto da un numero finito di istruzioni e deve avere un inizio e una fine, raggiunta la quale si interrompe l’esecuzione delle istruzioni;
  • esaustivo: cioè deve indicare la soluzione da seguire per tutti i casi che si possono verificare durante l’esecuzione;
  • deterministico: cioè ogni esecuzione dello stesso algoritmo con i medesimi dati iniziali, deve produrre sempre gli stessi risultati finali.

Le proprietà degli algoritmi, per i diagrammi a blocchi, stabiliscono che:


1. la soluzione proposta non può contenere un numero infinito di blocchi. Deve esistere un unico blocco iniziale (▶ start) e un unico blocco finale (▶ end). Non ci possono essere due o più blocchi in cui termina l’algoritmo; rispettando le regole si deve sempre riuscire a ricondurre tutto il diagramma al blocco finale;


2. il diagramma a blocchi deve essere costruito (prima) in modo da funzionare “qualunque cosa succeda” durante la sua esecuzione (dopo). Questo significa che il diagramma deve funzionare per qualunque input: la soluzione deve essere astratta e generica e non riferita a determinati valori. Inoltre il diagramma deve prevedere diverse diramazioni per gestire tutti i casi che si potrebbero verificare, inclusi quelli in cui gli input potrebbero essere “sbagliati” e quindi diventi necessario generare un messaggio di errore;


3. a parità di condizioni iniziali, il diagramma a blocchi deve comportarsi sempre nello stesso modo.

esempio

Possiamo paragonare il diagramma a blocchi a un labirinto che ha un unico ingresso e un’unica uscita.

Si entra solo da una parte e si esce solo dall’altra. Non è possibile pensare di poter uscire dal labirinto in un altro punto: qualunque strada si scelga, essa deve prevedere la possibilità di portare anche all’uscita.

Il labirinto viene costruito (prima), prevedendo tutte le strade percorribili. In un secondo tempo (dopo) l’utente deciderà quale strada percorrere durante l’esecuzione del suo tragitto. La strada percorsa sarà solo una, ma tutte le altre strade devono essere previste, tracciate e costruite nel labirinto, anche se potrebbero non essere mai percorse da nessuno.

Se l’utente che attraversa a piedi il labirinto parte ogni volta equipaggiato nello stesso identico modo, se i muri non sono crollati e se la strada scelta è sempre la stessa, l’utente deve uscire dal labirinto sempre nelle stesse identiche condizioni.

 >> pagina 390 

Simulazione

Quando il programmatore pensa di aver trovato una soluzione che risolve correttamente il problema, deve testare l’algoritmo, cioè provare a inserire dei dati (casuali, ma rappresentativi, talvolta anche sbagliati di proposito) e vedere se l’algoritmo funziona in tutte le situazioni che si possono presentare.

Questa operazione, almeno inizialmente, viene fatta con carta e matita. Per testare un algoritmo occorrono:

  • diagramma a blocchi;
  • variabili;
  • input;
  • output.
esempio

Il programmatore potrebbe scrivere su un quaderno la simulazione dell’esecuzione dell’algoritmo.

 >> pagina 391 

Codifica

Il programmatore riscrive l’algoritmo usando un linguaggio di programmazione (per esempio il linguaggio C) per renderlo comprensibile al computer.

Quando un algoritmo viene tradotto in un linguaggio di programmazione, diventa un programma (o codice) sorgente.

In questa fase è necessario un ambiente di sviluppo, cioè un software che metta a disposizione del programmatore tutti gli strumenti che gli servono, tra i quali, l’editor testuale all’interno del quale poter scrivere il programma sorgente.

esempio

Il programmatore riscrive l’algoritmo usando un linguaggio di programmazione.

Lo sapevi che

In informatica, i termini programma e codice sono sinonimi.

Programma

Il programma che l’utente installa e utilizza si chiama programma eseguibile e si ottiene dal codice sorgente.

Dal programma sorgente al programma eseguibile

La trasformazione di un programma sorgente (scritto dal programmatore) in un programma eseguibile (usato dall’utente) richiede diversi passaggi.


L’ambiente di sviluppo usato dal programmatore durante la fase di codifica mette a disposizione e consente di utilizzare diversi strumenti che realizzano questo processo:

  • editor: è un software per scrivere testi e può essere di due tipi:
    • editor di testo puro, come Notepad++ (▶ unità 10): consente di scrivere testo puro, cioè senza formattazione;
    • programma di videoscrittura, come Word e Writer (▶ unità 6): consente di scrivere testo, anche formattato, inserire immagini ecc.

    I programmatori usano gli editor di testo puro per scrivere il programma sorgente, che è un algoritmo scritto in linguaggio di programmazione;

  • compilatore: è un software che traduce il programma sorgente in un programma oggetto scritto in linguaggio macchina (binario), comprensibile all’elaboratore. Il codice oggetto non è il codice eseguibile;
  • librerie: sono un insieme di funzioni (blocco di istruzioni) o dati (entità usate per organizzare un insieme di dati all’interno della memoria del computer) definite in precedenza e collegabili a un programma oggetto.

    In altre parole, le librerie contengono dei codici sorgenti scritti in precedenza, che risolvono alcuni problemi che si ripropongono più volte (per esempio calcolare la radice quadrata) oppure contengono i codici sorgenti che descrivono dei “contenitori particolari” da usare per i dati;

  • linker: è un software che collega il programma oggetto alle librerie (e anche a eventuali altri programmi a cui faccia riferimento il programma di partenza) e genera un programma eseguibile, scritto in linguaggio macchina.

 >> pagina 392 

L’esecuzione di un programma

Il programma eseguibile (cioè usato dall’utente) è quello “eseguito” dal computer. Contiene infatti tutte le istruzioni da svolgere per risolvere un determinato problema, scritte in un linguaggio fatto da 0 e 1, direttamente comprensibile dalla macchina.


La CPU interpreta e rende concrete le istruzioni dell’algoritmo (contenute nel codice eseguibile) seguendo il loro preciso ordine, fino alla fine, ottenendo una risposta al problema da risolvere. Spesso la risposta viene ottenuta sulla base di dati forniti in input dall’utente.

I dati sono noti solo al momento dell’esecuzione del programma. Fino a quel momento, il programmatore non li conosce. Può solo “inventarsene” qualcuno per vedere se il programma funziona.

Introduzione al linguaggio C

Il linguaggio C, nato nel 1972, è uno dei linguaggi di programmazione più conosciuti e utilizzati nel mondo. Proprio per questo motivo è descritto da un’ampia letteratura e mette a disposizione una grande varietà di librerie già pronte che risolvono tantissimi problemi diversi.


Il linguaggio C consente di salvare le informazioni all’interno di variabili o strutture dati più complesse, dà la possibilità di eseguire operazioni di input/output sul monitor o su file e permette di convogliare il flusso del programma utilizzando istruzioni condizionali, istruzioni cicliche e funzioni, organizzando il codice in maniera strutturata. È un linguaggio sintetico che consente di scrivere anche programmi brevi e facili da capire.

Nel mondo reale, con il linguaggio C si possono scrivere programmi di qualunque genere, compresi i videogiochi e le app per dispositivi mobili. Consente di sviluppare le routine per piattaforme come Arduino e viene utilizzato per sviluppare i sistemi operativi (per esempio kernel Linux).

Anche se a un programmatore poco esperto potrebbe sembrare arretrato e meno utile di altri linguaggi più moderni, come per esempio C#, Python o Java, in realtà dal punto di vista didattico il linguaggio C è un ottimo strumento per imparare a programmare e fornisce le basi necessarie per comprendere facilmente anche altri linguaggi di programmazione.

Il seguente codice sorgente è scritto in linguaggio C e, quando viene eseguito, visualizza il testo “Ciao mondo” sul monitor.


#include <stdio.h>

int main()
{
printf("Ciao mondo!");
return 0;
}


Al suo interno sono presenti le istruzioni:

  • #include <stdio.h>: collega la libreria stdio.h al codice sorgente, in modo tale che il compilatore, generando il codice eseguibile, sappia come implementare l’istruzione printf richiamata all’interno del programma;
  • int main(){ }: in prima approssimazione può essere considerata come il “contenitore del programma sorgente” che infatti viene scritto all’interno delle parentesi graffe;
  • printf();: al cui interno può essere inserito, fra virgolette, il testo da visualizzare sul monitor;
  • return 0;: termina il programma e restituisce il controllo al sistema operativo.

Anche se è difficile da credere, conoscere un linguaggio di programmazione non è sufficiente a diventare un programmatore. L’importante non è il linguaggio con cui le idee vengono espresse, ma sono le idee stesse. I linguaggi di programmazione sono tutti simili e impararli, in realtà, è molto semplice. Quello che si rivela complesso è sviluppare il pensiero computazionale, cioè saper progettare un algoritmo che risolva un problema, rappresentarlo con un diagramma a blocchi che, successivamente, possa essere tradotto in qualunque linguaggio di programmazione.


Per esempio, il diagramma a blocchi a lato corrisponde al codice sorgente in linguaggio C appena descritto.


Per scrivere correttamente un diagramma a blocchi occorre conoscere determinate regole.

Lo sapevi che

Arduino è una piattaforma hardware, utilizzabile per scopi sia didattici sia professionali, che consente di realizzare piccoli dispositivi funzionanti per il controllo di led, sensori e attuatori, abbinata a un ambiente di sviluppo software per la programmazione del microcontrollore.

Clic!
Clic!
Tecnologie informatiche per il primo biennio