Wednesday, 20 October 2010

La trappola del C++ (quarta parte)

Bjarne Stroustrup, l'autore del linguaggio C++
Nei precedenti post ho illustrato le difficoltà che possono emergere dall'uso del C++ e gli eventuali correttivi. Nell'ultimo post avevo accennato alla domanda «ma abbiamo ancora bisogno del C++?». Contrariamente alle previsioni, la mia risposta è «si, ne abbiamo ancora bisogno», ma con le dovute attenzioni.
Lo scopo dei miei post non è mai stato denigrare il linguaggio di Stroustroup, ma sottolineare come alcune posizioni di principio facciano più male che bene.
Pensate a un programma come Gwibber: è un programma di microblogging che aggiorna il vostro stato su Facebook e su Twitter (lo facesse anche su Google Buzz sarebbe perfetto); è veloce e pratico. In che linguaggio è stato scritto? In Python puro, con le interfacce grafiche fatte con le GTK+ per integrarlo nell'ambiente Gnome. Avrebbe avuto senso scriverlo in C++? Non penso. Non ne vedrei l'utilità. Il programma funziona e fa quello che deve fare senza rallentamenti né noie.Avremmo aumentato il numero di righe di codice (sicuramente di un buon 30%) per guadagnare qualche millisecondo che, per quello che deve fare Gwibber, sarebbe stato inutile.

Ma me serve il C++!
Analizziamo, invece, Vuze, noto client BitTorrent. Lo uso spesso, funziona ed è ricco di funzionalità. E' scritto in Java e su un sistema un po' datato non da un'esperienza utente particolarmente gradevole. Varrebbe la pena riscriverlo in C++? Non saprei, ma sulla pagina wikipedia dedicata ai client bittorrent ne trovo almeno tre (uTorrent, Opera e KTorrent); altri sono scritti in Python; uno solo in C#. Evidentemente Vuze non è particolarmente amato dall'utenza.

Mettiamo a confronto due programmi simili, ossia due motori 3D: il Source della Valve e l'Unreal Enginedella Epic Games. Non ci sono storie: entrambi DOVEVANO venir scritti in C++ (persino John Carmack, il programmatore eroico che ha scritto Quake 2 in puro C, per Quake 3 s'è votato al C++) perché un motore grafico 3D ha bisogno di
  1. Massima velocità di esecuzione, perché qualche millisecondo può far la differenza
  2. Alto livello di astrazione, visto l'alto numero di entità coinvolte
  3. Contatto il più vicino possibile con l'hardware della macchina
  4. Rispetto delle deadline nel contesto realtime
Python non è in grado di far questo e Java nemmeno. In questo contesto il C++ è davvero l'unica scelta praticabile. I programmatori dell'Unreal Engine, però, si son dimostrati più furbi di quelli di Valve. Unreal Tournament 2003 è stato fin da subito disponibile per Mac OS X e GNU/Linux, mentre Source no. Come mai? Alla pagina di wikipedia c'è la spiegazione, ma se siete stati attenti negli articoli precedenti avrete già indovinato. A un engine di base fatto in C++ facilmente portabile, i programmatori di Epic hanno agganciato un motore di scripting (UnrealScript) che gestisce tutta la logica di gioco. Per loro è "bastato" (le virgolette sono d'obbligo) riscrivere alcuni blocchi di basso livello (routine grafiche,audio) per trasferire un intero gioco su altre tre piattaforme. Source, invece, ha tutti i plugin scritti in C++ e compilati all'interno del motore. Fare una modifica su un programma del genere (in questo contesto ci aggiriamo facilmente sulle 20.000 e più righe di codice) non è assolutamente un lavoro da poco.

La Valutazione dei Requisiti
Sul famoso racconto «La notte che bruciammo Chrome», William Gibson racconta la storia del miglior colpo fatto da due hacker: questi due vivono in condizioni economiche pietose e vogliono fare "il colpaccio". La svolta avviene quando uno di loro scopre che un misterioso cubo comprato al mercato nero è un sistema di intrusione informatico pensato per i militari. Ma, anzichè esultare, il personaggio dice

«Mi sentivo come il ladruncolo che scende in strada per comprare un coltello e torna a casa con una bomba a neutroni. Tombola. Cosa te ne fai di una bomba a neutroni in una rissa di strada?»

Riuscite ad afferrare l'analogia? Il C++ è la bomba a neutroni. E' vero che col C++ si fa tutto, ma pochi ci mettono davvero la testa quando programmano in quel linguaggio. Provate a pensare ai programmatori C++ che conoscete e chiedetevi:
  • quanti hanno parlato di aver scritto una classe String più efficiente?
  • quanti hanno detto di aver pronta una personale libreria di template?
  • quanti hanno scritto delle classi per la gestione delle strutture dati comuni (vettori, liste)?
  • quanti hanno riempito di cout<< i loro programmi?
Ora, per contro, pensate a quanti
  • hanno scelto un motore di scripting interno?
  • hanno fatto una valutazione dei requisiti?
  • hanno calcolato le deadline del programma?
  • hanno utilizzato lo GNU debugger?
  • hanno utilizzato software come Valgrind?
  • hanno utilizzato le librerie QT?
Qui son stato volutamente provocatorio, ma il senso è chiaro. Molti decidono di programmare in C++ per partito preso, senza considerare se hanno davvero bisogno dell'astrazione, della velocità (e delle difficoltà) proprie di questo linguaggio. Lanciano allegramente g++ senza riflettere seriamente su debug, gestione della memoria, portabilità e su tutti i problemi di cui ho parlato. E' un po' come vedere il ladruncolo che armeggia con la bomba a neutroni dicendo «funziona meglio di un coltello, ne minacci di più e so perfettamente come funziona»

Pensare a un roguelike
Agband (immagine hostata da Wikipedia), uno dei roguelike più famosi
Faccio un altro esempio: provate a progettare (solo progettare) un gioco sullo stile di Angband. Questo tipo di giochi si chiama roguelike e sono degli RPG, generalmente basati sul regolamento di Dungeons and Dragons. L'interfaccia, come vedete, è scarna da far paura: è un'interfaccia a caratteri che usa i caratteri come tiles e come sprite.
I requisiti di questo nostro roguelike sono:
  • mappe caricate da file (non è molto "rogue", ma è per semplificarvi la vita)
  • movimento all'interno di mappe più grandi dello schermo
  • salvataggio e caricamento delle partite
  • gestione delle caratteristiche del personaggio
  • gestione degli oggetti di gioco (armi, cartelli, pozioni, ecc.)
  • Intelligenza artificiale dei mostri
 Provate a pensare a cosa significherebbe programmarlo in C++ su Ubuntu. Terminatolo, provate a pensare di farne la conversione in C++. Pensate a come evitare i memory leak e le ricerche fuori da un array. Pensate a riscriverlo in un altro linguaggio (Java, Python, Ruby... fate voi). Vi garantisco che le performance non se risentiranno, ma il tempo di sviluppo si (e anche tanto).

La Conclusione
Il C++ è nato con l'obiettivo di aggiungere le classi al linguaggio C mantenendo alta la velocità di esecuzione e la compatibilità con l'illustre predecessore. E' stato impiegato in quasi tutti i grandi progetti software dal 1995 in poi (Autocad, Quake 3, KDE...) e i suoi meriti sono indubbi.
Lo scopo di questa serie di articoli non è mai stato dire "il C++ fa schifo", ma invitare chi inizia a fare un progetto a chiedersi se valga davvero la pena affrontare anche tutte le problematiche che lo sviluppo di un programma C++ richieda.
Se poi i requisiti sono tali per cui  non si può davvero fare a meno del C++, è stata mia intenzione rivolgere l'attenzione del lettore al debugger, uno strumento utile che viene sottovalutato in diversi ambienti, ma che è un compagno inseparabile di chi lavora con i linguaggi compilati.
Del C++ non ci si sbarazzerà facilmente: la sua ubiquità, velocità di esecuzione e astrazione sono necessari in una miriade di contesti (videogames, sistemi realtime, controlli hardware, ecc.): ma la presenza di altre soluzioni software (Python, Ruby,Java) deve spingere lo sviluppatore a fare delle buone analisi e vedere cosa effettivamente vuole ottenere.
Analisi, pochi pregiudizi e attenzione.
E buona programmazione!

Note
Un paio di link utili come spunto per ulteriori riflessioni
 All'anonimo autore del "provocatorio" commento (che ho apprezzato ;) ) dico che mi ha dato una bella idea per un prossimo post su Java.
Post a Comment