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.

5 comments:

FABIO said...
This comment has been removed by the author.
FABIO said...

Dunque... in questo momento non ho un gioco basato sull'Unreal Engine 3 ma ricordo chiaramente che è strutturato in una folder root con 3-4 subfolder, di cui una sola colma di .dll (un centinaio circa).
Un qualunque gioco basato sul Source ha bisogno di due cose: l'SDK base o la versione 2007 e le librerie del gioco stesso.
Il Source è strutturato in decine e decine di subfolder con una media di 50-200 .dll al loro interno.
http://img41.imageshack.us/img41/4063/dllsteam.jpg
Moltiplica questa immagine per 20 o 30 volte, questa è la media minima.

FABIO said...

Da notare comunque che ogni gioco o applicazione Source-based ha dipendenze interne che fanno riferimento ad eseguibili come hl2.exe o librerie di nome hl2.dll (hl2 è Half Life 2) e quindi, paragonabile ad una sorta di virus che la Valve si porterà sempre dietro.
Se riesci a generare un errore in una qualunque applicazione Source vedrai nel log stesso che fa riferimento ad errori originati da hl2.exe o hl2.dll

Anonymous said...

Caro Jac,
sono d'accordo quasi in tutto , ma vorrei permettermi di perfezionare un minimo la metafora c++ - bomba a neutroni:

Ritengo il c++ più un bisturi che una cosa distruttiva: è uno strumento potentissimo in mano a chi sa usarlo , e per lo scopo giusto; è altresì una disgrazia in mano a chi non sa usarlo , o lo utilizza per scopi sbagliati.

Il c++ a mio parere personalissimo rappresenta l'apoteosi dello sviluppo: se lo si usa correttamente sarebbe pulito, ordinato,facilmente manutenibile.

Il problema che a mio parere porta a detestare il c++ è il fatto che, essendo potente, viene utilizzato per qualunque cosa, proprio come una bomba per scavare una buca.
Questo ovviamente porta a codice orribile, pesante, non ragionato / progettato e di scarsa portabilità.

Ma pensa invece a quanto fa nei casi in cui davvero serve: hai a disposizione strumenti proprio come un bisturi: puoi intervenire sulle minime necessità. ogni singolo bit che viene processato dal programma è alterabile,modificabile,controllabile.
Penso di conseguenza che il c++ non sia una bomba, ma un bisturi: se lo dai a jack lo squartatore verrà sempre fuori una schifezza, se lo dai alla valve vedrai che meraviglie tira fuori dal cappello =P

Jacopo Prendin said...

Caro anonimo (so chi sei, ma se non hai voluto firmarti rispetto questa scelta) son perfettamente d'accordo con quel che dici. Un passo, in particolare, m'è piaciuto:

«[...]è il fatto che, essendo potente, viene utilizzato per qualunque cosa, proprio come una bomba per scavare una buca»

Il punto di questa serie di post era sottolineare questo. Che, purtroppo, ho sempre l'impressione che ci siano più Squartatori che programmatori Valve. Ma, dopotutto, se vengono pagati così bene ci sarà un motivo ;)