Dr. Carlo Pescio
Intervista a Bjarne Stroustrup

Pubblicato su Computer Programming No. 50


Il progettista del C++ risponde ad alcune domande sul passato, presente e futuro del linguaggio. Tra gli argomenti affrontati: cosa vorrebbe cambiare nel C++, cosa pensa di Java e del nuovo ANSI C, e come dovrebbe evolversi il C++.

Bjarne Stroustrup è il creatore del C++, uno dei linguaggi di maggiore successo nella storia dell’informatica. È anche una persona molto disponibile, che ha immediatamente accettato la mia proposta per un’intervista sul passato, presente e futuro del linguaggio. Inevitabilmente, in alcuni punti non abbiamo resistito alla tentazione di confrontare le nostre idee con qualche riga di codice, e più di una volta gli argomenti sono scivolati sul lato più tecnico della progettazione ed uso del linguaggio. Tuttavia, nel suo insieme l’intervista dovrebbe risultare leggibile ed interessante anche per chi non conosce il C++ nei suoi dettagli più minuti, ed anche per chi non lo conosce affatto. Volete sapere come scrivere un linguaggio di successo? Qui troverete la ricetta del progettista del C++.

Nel seguito, le iniziali CP e BS indicheranno le parti di testo da attribuire a me ed a Stroustrup rispettivamente.

CP:
Sei soddisfatto dal risultato e dal ritmo di avanzamento dell'attività di standardizzazione del C++? Ovvero, da un lato la standardizzazione è una prova del successo del linguaggio, ma dall'altro sta aggiungendo non poca burocrazia; ti manca in qualche modo la libertà iniziale rispetto alle decisioni fondamentali?

BS:
Naturalmente, la mia pazienza è stata ampiamente messa alla prova, ma in effetti sono molto contento del risultato della standardizzazione. Con qualche eccezione minore, l'ISO C++ avrà le caratteristiche che ritengo siano necessarie e nessuna che ritengo pericolosa. ISO C++ è un linguaggio molto più potente e coerente delle precedenti versioni del C++ , e nulla è stato aggiunto al linguaggio su cui io non abbia lavorato e che non abbia infine approvato. Alcuni dettagli dell'ISO C++ possono mostrare i segni di "design da comitato", ma l'insieme generale corrisponde alla mia visione originale del C++ più di quanto non fosse vero per le prime versioni del linguaggio.
La ragione principale per cui ho partecipato al lavoro di standardizzazione è stata la costituzione di un comitato in un momento in cui il linguaggio era ancora incompleto. Il C++ senza template ed eccezioni sarebbe stato inaccettabile, e senza i namespace ed il run-time type information sarebbe decisamente più povero di quanto sia oggi.
Non voglio esagerare la mia "libertà iniziale": ho deciso molto presto di volere il mio linguaggio compatibile con il C ed ho voluto supportare utenti reali. Ciò ha limitato sin dall'inizio le mie possibilità; l'alternativa sarebbe stata la progettazione di un altro linguaggio "di culto".
Tuttavia non ho potuto attendere sino al completamento dello standard: la comunità C++ ha bisogno di uno standard, ma io ho bisogno del tempo che ho dovuto dedicare alla standardizzazione negli ultimi sei anni circa. Credo che il linguaggio abbia ottenuto notevoli benefici dalla mia attività nel comitato di standardizzazione. Sono stato a capo del sotto-comitato per le estensioni al linguaggio ed ho valutato tutte le richieste per le estensioni ed ogni altro punto fondamentale relativo al linguaggio stesso, ed ho avuto parte in molte altre decisioni di rilievo, inclusa la libreria standard.
La standardizzazione è necessaria per un linguaggio con il numero di utenti del C++, tuttavia non posso dire che sia divertente. Molto credito, molto di più di quanto sia usualmente concesso agli "anonimi membri del comitato", va in effetti alle persone che hanno offerto volontariamente il loro tempo e compiuto notevoli sforzi negli ultimi anni all'interno del comitato. Diversi dei loro nomi sono riportati nel mio libro "The Design and Evolution of C++".

CP:
Molti lettori vorrebbero sapere se stai lavorando ad una terza edizione di "the C++ language" o ad una seconda edizione del "C++ Annotated Reference Manual".

BS:
In effetti sto lavorando ad una terza edizione e pensando a qualcosa con cui rimpiazzare l'ARM. Tuttavia, non voglio scrivere un libro se non ho molte cose nuove da dire, quindi il mio progresso è lento. Il mio obiettivo è scrivere una terza edizione che migliori la seconda almeno quanto la seconda ha migliorato la prima; in altre parole, voglio qualcosa più avvicinabile della seconda, ma allo stesso tempo con informazioni nuove ed interessanti per ogni programmatore C++.
Non so dire quando completerò il libro, ma nessuno che abbia bisogno di un libro di testo dovrebbe attendere la terza edizione. La seconda è comunque uno dei testi più completi ed aggiornati disponibili al momento. E naturalmente, non posso pubblicare un nuovo ARM fino a che non vi sarà uno standard da annotare.
Fino a quando non avrò finito, D&E è la migliore fonte di informazioni sulle nuove caratteristice del C++ ed in generale sulle decisioni di design che hanno portato al C++.

CP:
C'é qualche decisione tecnica che in retrospettiva ti piacerebbe cambiare - non qualcosa che non avresti avuto modo di far accettare sin dall'inizio, ma qualcosa che l'esperienza ha dimostrato in qualche modo essere imperfetto, e che vorresti cambiare se ne avessi la possibilità. Tralasciando al momento la compatibilità con il C++ esistente, ma non con il C.

BS:
Ci sono molti dettagli con i quali mi piacerebbe giocare, ma non ci sono caratteristiche che vorrei eliminare, anche se potessi, o qualcosa di importante che vorrei aggiungere e che saprei come aggiungere. Spesso vengono mosse delle critiche all'ereditarietà multipla o al RTTI, ma devo dire che senza uno di essi il C++ sarebbe decisamente meno espressivo. Io uso entrambi a fondo e le soluzioni che dovrei utilizzare in mancanza di esse sono tutt'altro che eleganti; ci sono anche esempi in D&E...

CP:
In effetti, avevo in mente più che altro alcune modifiche alle funzioni virtuali: per esempio, il fatto che una funzione virtuale possa essere ridefinita in una classe derivata come private è abbastanza pericoloso. La funzione non è accessibile - tuttavia è ridefinibile; questo limita un pò l'utilità dell'ereditarietà privata.
Più in generale, probabilmente ricorderai le pubblicazioni di Sakkinen sui principi dell'ereditarietà in C++: alcuni dei suoi commenti erano veramente azzeccati, ed in particolare mi sembrava interessante il fatto che, sotto regole più restrittive, la responsabilità di invocare il costruttore di una virtual base class non dovesse essere necessariamente propagata sino in fondo al grafo di derivazione. In effetti, anche se capisco le ragioni per le attuale regole per le virtual base class in C++, devo anche dire che invocare il costruttore di una virtual base class indebolisce l'incapsulazione fornita da classi intermedie...
D'altra parte, noi conosciamo i punti forti e deboli del C++ attraverso anni di uso, e probabilmente le proposte di Sakkinen avrebbero comportato altri punti deboli (diversi dagli attuali), anche se devo dire che tali proposte mi trovano favorevole, almeno per quanto riguarda lo stile di programmazione.

BS:
In molti casi, queste considerazioni sono puramente accademiche e di scarso interesse per la programmazione reale. È possibile progettare un costruttore per accedere maliziosamente ad alcune informazioni, ma un costruttore che inizializza solo i suoi dati è fondamentalmente innocuo. Inoltre, se la virtual base class è pubblica, come ho sempre suggerito, allora tutte le classi derivate dovrebbero sapere che esiste e dovrebbero chiamarne il costruttore; in questi casi, una classe base virtuale non è diversa dalle altre classi base. Se le classi base virtuali sono dichiarate private da una parte e pubbliche da un'altra, e se la classe più derivata inizializza la classe base in modo inadatto per la parte privata, allora è vero che l'incapsulazione della parte privata è stata indebolita. Penso però che se questi sono i problemi peggiori, allora siamo molto fortunati...
Non vedo invece problemi nel ridefinire una funzione virtuale privata o di una classe derivata privatamente. Se consideri la classe base come un'interfaccia, non è una preoccupazione di chi usa l'interfaccia come l'implementazione (nelle classi derivate) sia realizzata. Posso anche immaginare una classe derivata che definisce private le sue funzioni virtuali proprio per prevenirne l'uso, eccetto attraverso l'interfaccia fornita da una classe base. Se la base è privata, può essere comunque accessibile a classi friend, oppure la classe derivata potrebbe fornire un puntatore alla base su richiesta. Per esempio, una classe derivata potrebbe restituire in puntatore alla sua interfaccia base (privata) come risultato di una operazione che esegue controlli di sicurezza a livello di sistema, come in:

class A
  {
  virtual void f() ;
  } ;
 
class B : private A 
  {
  void f(); // implementation
  A* get_A(Rights& r) 
    { 
    /* check rights */ 
    return (*A)this; 
    }
  } ;

 

CP:
D'altra parte, l'ereditarietà privata non è transitiva, quindi in un caso come:

class A
  {
  virtual void f() ;
  } ;

class B : private A 
  {
  void h() { f() ; }
  } ;

class C : public B
  {
  virtual void f() ;
  }

La classe A non è un'interfaccia per la classe C, A :: f() non è accessibile in C, ma è ridefinibile nella classe C. Possiamo dire che il colpevole sia l'implementatore della classe C, che ha basato la sua classe su un dettaglio implementativo della classe B (ovvero, il fatto che B sia-implementata-usando la classe A). Ma alcuni potrebbero volere che ciò fosse proibito dal linguaggio.

BS:
È vero, questo è veramente un problema. Purtroppo, non è facile ricavare un insieme di regole che prevengono ogni problema senza rendere illegale codice che alcuni ritengono scorretto, ma che per altri è essenziale per completare un lavoro. In generale, sono abbastanza contrario alle restrizioni. Non considero l'ortogonalità un criterio di design primario, ma certamente preferisco l'ortogonalità ogni volta che non vi siano ragioni di primissimo ordine per un design non-ortogonale. Le regole di accesso del C++ sono veramente ortogonali (rispetto alle regole di naming, ridefinizione, ecc) e non vedo ragioni abbastanza forti per cambiarle. Alcune regole possono sorprendere i programmatori, ma anche regole meno ortogonali potrebbero farlo.

CP:
Un punto di vista certamente condivisibile. È per questo che questo tipo di regole mi sembrano adatte a figurare in una definizione di "stile di programmazione". Vi sono casi in cui violare tali regole può essere utile (ad esempio riusando da una libreria di cui non si ha il sorgente), ed è quindi apprezzabile che il C++ abbia la necessaria flessibilità. Non dovrebbero però essere utilizzate senza ottime ragioni...

BS:
Mi sarebbe piaciuto rendere il C++ in grado di segnalare molti degli errori logici dei programmatori. In effetti, molte delle caratteristiche del C++ hanno esattamente questo effetto se paragonate al codice che di dovrebbe scrivere in C per ottenere una funzionalità analoga. Tuttavia, non credo che questo tipo di sicurezza debba essere ottenuto a spese di soluzioni semplici a problemi reali; questo limita ciò che può essere fatto per rendere il linguaggio più pulito, esattamente come i problemi di compatibilità.

Spesso le librerie sono un buon modo per rendere il C++ più sicuro in determinati contesti: per esempio, chi è preoccupato dalla mancanza di range-checking negli array del C++ può semplicemente usare una classe vettore con range-checking. Io lo faccio abitualmente, soprattutto per debugging.

CP:
Torniamo alla retrospettiva sul C++...

BS:
Nel bene e nel male, ho mantenuto un alto grado di compatibilità con i C sin dai primi giorni, ed il comitato di standardizzazione ha seguito la mia politica di restare "vicini al C quanto possibile - ma non oltre". Molte cose in C++ potrebbero essere migliori da un punto di vista di teoria dei linguaggi, ma ciò non è realistico. Quando sono partito ho deciso per la compatibilità ed ho sempre tentato di convivere con difetti secondari, eliminando solo i problemi relativi al type system. L'alternativa era quella di costruire un altro linguaggio di culto, bellissimo agli occhi dei suoi adepti ed in grado di suscitare poco più che uno sbadiglio da parte di tutti coloro che programmano per ottenere dei risultati. Se non ci fosse stato il C con cui essere compatibile, avrei scelto un altro linguaggio con cui esserlo. Ero, e sono tuttora, convinto che il mio tempo non sarebbe stato ben speso inventando giusto un altro modo per scrivere un loop.
Anche la concorrenza è un argomento che continua ad emergere; molti usano o vogliono usare qualche tipo di concorrenza e vorrebbero che fosse direttamente supportato dal C++. Tuttavia, non esiste un singolo modello di concorrenza che sia adatto ad una frazione significativa dei programmatori C++ che hanno realmente bisogno della concorrenza. Chi scrive sistemi operativi ha bisogno di un modello, chi scrive database di un alto, chi scrive applicazioni di rete un altro ancora. Per questo ho deciso di non includere un supporto per la concorrenza in C++; chi ha bisogno di un modello specifico può supportarlo attraverso estensioni al linguaggio, o quando è possibile con librerie. Il comitato standard mi ha appoggiato in questa decisione, perché conoscevamo molti schemi di concorrenza piuttosto attraenti, ma nessuno adatto alla maggioranza degli utenti del C++; il numero di aree dove il C++ viene usato è davvero incredibile.
Tempo fa mi hanno chiesto di scrivere un articolo per la seconda conferenza dell’ACM sulla storia dei linguaggi di programmazione (ne tengono una ogni 15 anni!); per quell’articolo, mi hanno chiesto quale considerassi il più grande errore del C++. Dal mio punto di vista, c’era un solo candidato al titolo di "grande errore": non sono riuscito a fornire una buona libreria di classi insieme alla release 1.0 nel 1985. La mia scusante è che non sapevo come scrivere una libreria che fosse adeguata, e che avevo bisogno dei template per scrivere classi contenitore efficienti, flessibili, e type-safe. Il risultato è l’attuale caos di librerie incompatibili, basate su filosofie diverse, e con qualità molto distanti.
Fortunatamente, il comitato ha deciso di fornire un’eccellente libreria standard; ora abbiamo ciò che non sono riuscito a produrre anni fa, e che all’epoca non avrei saputo come progettare ed implementare. Il framework di classi contenitore e algoritmi fondamentali che costituisce la parte centrale della libreria standard è soprattutto opera di Alex Stepanov, anche se ha alcune radici nella nostra ricerca sui principi e le tecniche per costruire componenti di libreria, ricerca che risale a prima della release 1.0.

CP:
Come sai vi sono proposte per aggiungere alcune delle caratteristiche del C++ al C9x, la nuova release dell’ANSI C. Ad esempio, intendono fornire un supporto limitato per le classi; mi è sembrato un tentativo un pò improvvisato, perché non esiste il concetto di costruttore, di operatore di assegnazione, eccetera. Qual è la tua posizione sul nuovo ANSI C?

BS:
Mi sembra non solo improvvisato, ma le spiegazioni che lo accompagnano dimostrano una mancanza di attenzione all’evoluzione del C++ sotto la spinta del feedback degli utenti. Io avevo, e continuo ad avere, una visione globale di cosa il linguaggio debba fare, ma all’interno di questa visione d’insieme, sono stato molto attento a ricercare un feedback che gli permettesse di evolvere sulla base delle esigenze ed esperienze degli utenti reali. Il tentativo di estrarre un piccolo sottoinsieme del C++ per ottenere "un linguaggio molto più semplice con quasi tutta la potenza del C++" a mio parere è destinato a fallire. A meno che non venga scelto con una attenta analisi basata su esperienze reali, questo sottoinsieme supporterà solo parzialmente uno stile di programmazione coerente, ed ogni elemento tenderà a farne aggiungere un altro. Solo sotto la guida di una visione d’insieme le aggiunte manterranno la coerenza del linguaggio finale.
Non sarebbe però ragionevole per me cercare di imporre alla comunità C la mia visione di come il loro linguaggio debba essere standardizzato. Se lo facessi, i miei consigli non sarebbero comunque benvenuti, perché chi li apprezza probabilmente sta pensando comunque di passare al C++. Il comitato per il C farà ciò che riterrà più opportuno, e presumibilmente conosce al meglio le esigenze della sua comunità di sviluppatori. Dal punto di vista del C++, vorrei che ogni estensione al C fosse compatibile con il C++ per quanto possibile; la comunità dei programmatori non ha bisogno di un altro dialetto C incompatibile con gli altri. Il K&R C non è ancora morto, l’ANSI C attuale persisterà a lungo dopo la promulgazione del nuovo standard, e varie forme del C++ esisteranno anche dopo che il C++ standard sarà ufficiale. Le cose tendono a richiedere più tempo di quanto si vorrebbe; aggiungere nuove caratteristiche al C9x porterà inevitabilmente a delle instabilità nel C e nel C++.

CP:
Parlando dei figli del C++, non posso evitare di menzionare Java... a tuo parere, quanto è grande l’effetto carovana, e dove vedi invece i veri punti di forza di Java? So bene che come progettista di linguaggi, sei molto cauto nel criticare i lavori altrui (d’altro canto, ogni linguaggio ha una nicchia), ma quali sono le tue sensazioni?

BS:
Java ha una sintassi simile al C++, ma è un linguaggio molto diverso che supporta una cultura differente ed un diverso (e più limitato) insieme di stili di programmazione. Java non è certamente il linguaggio C++-like che avrei progettato io in assenza di problemi di compatibilità. Attualmente Java è visto come una incredibile promessa, in parte grazie allo sforzo economico di marketing di Sun, ma anche per la sua integrazione con il Web. Il tempo ci dirà quanto sia adatto come linguaggio general-pourpose, e come la maggioranza dei programmatori e dei manager reagirà scoprendo che la "sicurezza" di Java e soprattutto di Javascript lasciano molto a desiderare. Molti confondono la sicurezza sui tipi (type safety, che una implementazione corretta di Java fornisce) con la "sicurezza" (security), ovvero la preservazione dell’integrità e della privacy del sistema, che può essere seriamente compromessa con Java. Chi si occupa di sicurezza da noi scherza su Java chiamandolo "il linguaggio per l’implementazione di virus" e insiste che Java e Javascript vengano disabilitati nei nostri browser. Comunque, tornando alla discussione sui linguaggi, il C++ è un C migliore, supporta la programmazione per ADT, supporta la programmazione object oriented, e supporta la programmazione generica. Di questo, Java supporta solo la parte orientata agli oggetti, ed in modo significativamente diverso dal C++.

CP:
Parecchie delle più recenti aggiunte al C++ sono stati utili dettagli, ma pur sempre dettagli, come explicit o mutable, oppure alcune "prese di distanza" dal C, come i nuovi tipi di cast. Vedi alcun futuro per un migliore supporto al design all’interno del linguaggio? Ad esempio, vi sono ottime ispirazioni in progetti come Annotated C++ o Larch-C++, più orientate verso la specifica e meno verso la codifica; sarebbe anche interessante aggiungere un pò più di semantica al linguaggio, ad esempio per rendere le decisioni di sharing degli oggetti più esplicite. Oppure la tua intenzione è di rendere il linguaggio ancora più forte dove è già forte, ovvero nelle aree della programmazione embedded, o di sistema, o dove le prestazioni sono critiche?

BS:
Il C++ si unirà ad una generale evoluzione verso uno stile di programmazione più dichiarativo. Tuttavia, per quanto riguarda la definizione ufficiale del linguaggio, voglio che le modifiche ad esso ed alle librerie si fermino, per dare ad utenti, implementatori di compilatori e di tool, insegnanti, eccetera, una possibilità di lavorare su un linguaggio stabile. Naturalmente, la sperimentazione continuerà, anche se probabilmente non da parte mia; il C++ è ora completo e coerente e sviluppi futuri dovranno rimanere in sotto-comunità, come le università, per un certo numero di anni.
Penso che si debba ancora scoprire l’intero potenziale dei template per ottenere alcune forme di specifica. Per esempio, questo è un abbozzo di come si possa definire una lista per condividere una singola interfaccia tra tutte le liste di puntatori:

//general list<T>:
template<class T> class list 
  { /* ... */ };

//specialization for 
//lists of void*:
template<> class list<void*> 
  { /* ... */ };

//general list of pointers 
//(implemented using list<void*>):
template<class T> class list<T*> :
list<void*> { /* ... */ };

Il meccanismo di specializzazione usato qui permette di scegliere implementazioni differenti (via type-deduction) ma di continuare a fornire all’utente una sola interfaccia generale. Questo rinforza la natura dichiarativa del C++, semplifica l’interfaccia con l’utente, e aumenta l’efficienza a run-time. Questa tecnica ci ha consentito di fornire una sola routine generale per il sorting nella libreria standard, che su casi reali ha battuto la funzione di libreria C qsort() di un fattore sette!

CP:
In IEEE Computer del febbraio 1995, il professor Wirth (creatore di Pascal, Modula 2, e più recentemente di Oberon) ha definito il C++ "un linguaggio che scoraggia il pensiero strutturato e la costruzione ordinata dei programmi". Non posso dire di essere daccordo, o che Oberon mi incoraggi ad una maggiore struttura e disciplina rispetto al C++, ma c’é nulla che vorresti concedere ai puristi ed agli accademici, che spesso devono decidere tra insegnare il C++ perché è utile nel mondo reale, e non insegnarlo perché è troppo distante dall’approccio più formale, orientato alle specifiche, che è alla base di molti corsi di Computer Science. È per questo che molti finiscono per insegnare Eiffel sulla scia del "programming by contract" oppure Smalltalk perché "é un linguaggio OO puro"...

BS:
Wirth non è famoso per la sua generosità verso i linguaggi che non ha progettato lui stesso, quindi non mi sorprende molto conoscere la sua opinione. D’altra parte, penso che si sbagli completamente. Il C++ è uno strumento più che adeguato per il buon design, per la programmazione su scala industriale, e per pensare in modo preciso su problemi seri e concreti. Penso anzi che questo sia un buon momento per esprimere la mia gratitudine ai progettisti del Simula e del C per avermi fornito una base molto solida su cui costruire il C++, e per essere persone così assolutamente gentili. Ho anche imparato parecchio da altri linguaggi: se sai dove guardare, puoi trovare tracce di Algol68, ML, Ada e BCPL in C++. Ci sono molti ottimi linguaggi in giro: ognuno dovrebbe cercare di conoscere più di un linguaggio - ciò è vero sia per i linguaggi di programmazione che per quelli naturali. Un nuovo linguaggio aggiunge molto alla nostra visione del mondo ed alle nostre capacità.
Ci sono molti punti che potrebbero essere migliori in C++; tuttavia ciò è vero per ogni linguaggio usato in progetti reali, anche quelli che si dichiarano "puri". Nella mia esperienza i problemi con il C++ non sono preoccupanti per chi vuole insegnarlo o utilizzarlo. Ovviamente, uno studente può non riuscire ad apprendere o un insegnante può usare un approccio che lo rende troppo difficile; tuttavia ciò vale per ogni linguaggio. Il C++ ha il vantaggio che il suo uso è scalabile a problemi reali in molte aree diverse; molta della facilità di apprendimento per i linguaggi didattici nasce da semplificazioni che forzano gli utenti ad abbandonare il linguaggio quando si scontrano con una applicazione fuori dal dominio in cui il linguaggio "pulito" è adeguato. Ovviamente, questo può succedere anche con il C++, ma di fatto avviene raramente, soprattutto se si resta abbastanza vicini al sistema.
Il C++ ha dei sottoinsiemi molto puliti e la complessità arriva quando si comincia a giocare con le caratteristiche e gli stili di programmazione (paradigmi) che richiedono una comprensione più completa del linguaggio. Normalmente è qui che gli utenti di linguaggi "più puliti" devono rivolgersi ad altri linguaggi, normalmente C o C++; secondo me, il C++ dovrebbe essere insegnato per tappe e con una forte enfasi sui concetti.

CP:
Mi sembra un ottimo spunto; d’altra parte, si potrebbe immaginare anche un sottoinsieme ancora più coerente del linguaggio, ad esempio un "C++ per studenti" dove non esista un cast implicito da array a puntatore, e con altre limitazioni con lo stesso spirito. Pensi che potrebbe essere un utile strumento di insegnamento (e magari anche un buon tool di programmazione per chi è meno vincolato dalla compatibilità con il C), o solo fonte di confusione?

BS:
In effetti sarei ben felice se esistesse un "C++ per studenti" dove gli array built-in non fossero affatto presenti. Gli studenti potrebbero usare classi per vettori, liste, stringhe fornite dall’insegnante e basate sulla libreria standard. Questo potrebbe essere ottenuto in un ambiente di insegnamento anche senza modificare il compilatore, semplicemente abbassando il voto se si usano gli array built-in. Nello stesso senso, un insegnante dovrebbe trovare semplice l’eliminazione dei cast espliciti, perché non hanno posto nel codice che uno studente dovrebbe scrivere.
La parte difficile nell’apprendimento del C++ (o di ogni altro linguaggio) è imparare le nuove tecniche di programmazione e di design, non i costrutti del linguaggio usati per esprimerle. Troppo spesso, le persone sono ossessionate dalle feature di un linguaggio. Fin troppo spesso, i programmatori si perdono in futili tentativi di comprendere ogni aspetto di un linguaggio ricco, senza il background sufficiente a capire le tecniche che il linguaggio supporta. Tra l’altro, il C++ è persino più semplice degli ambienti, framework ed applicazioni che usiamo nello sviluppo di applicazioni reali.
Nell’insegnamento, il C++ è stato danneggiato dalla sua stretta (ed utile) vicinanza al C; poiché il C++ è (più o meno) un superset del C, molti pensano che si debbano apprendere tutte le tecniche e le peculiarità del C prima di passare al C++. Non è così, perché il C++ è in molti sensi più ordinato del C, e le librerie possono essere usate per evitare agli studenti le complessità della manipolazione dei puntatori in C, il casting, gli array, ecc. Il C++ può essere, e talvolta è, un ottimo linguaggio per insegnare la programmazione, gli stili di programmazione e design, e così via; tuttavia, dobbiamo distinguere tra l’insegnamento della programmazione e l’insegnamento dei linguaggi. Una volta operata la distinzione, potremo progredire e forse addirittura evitare quelle ridicole guerre tra linguaggi che sprecano il nostro tempo.
Un punto di forza del C++ come linguaggio per l’insegnamento è che permette di presentare diverse tecniche di design e di programmazione. L’alternativa è di insegnare una varietà di linguaggi "più puliti" che illustrino lo stesso insieme di tecniche. Ciò che considero totalmente errato è di presentare un unico metodo di design e di programmazione, racchiuso in un unico linguaggio, come l’unico vero metodo. Un programmatore professionista o un informatico dovrebbe essere familiare con il C++, Smalltalk, ML, Lisp, ed Eiffel, tanto per citarne alcuni. Ovviamente, pochi potranno essere dei veri esperti in più di uno o due di essi allo stesso tempo, ma l’ideale è di acquisire una buona familiarità con tutti e nel tempo provare ognuno di essi in un progetto reale.

CP:
Tra gli aspetti più complessi da apprendere e da usare correttamente del C++ vi sono senza dubbio le eccezioni. Oltre all’ormai famoso articolo di Cargill, anche gli auto_ptr sono stati introdotti per necessità nella libreria standard, per rendere i puntatori più gestibili in presenza di eccezioni, e vi è una certa impedenza tra i template e la specifica di eccezioni. D’altra parte sembrano anche difficili da implementare correttamente: Borland ha avuto seri problemi linkando DLL con e senza gestione delle eccezioni. E non voglio risollevare la diatriba sul "retry", che hai già discusso a lungo in D&E. In conclusione, considerando anche che le eccezioni rendono la curva di apprendimento del C++ più ripida, sei sempre convinto che le eccezioni così come sono implementate in C++ ripaghino dello sforzo?

BS:
Le novità vengono quasi sempre giudicate difficili da usare, costose, e non necessarie, almeno all’inizio. Dei vari "problemi" sollevati, relativamente pochi sono preoccupanti in casi reali; io trovo che le eccezioni rendano il mio codice più semplice. Come tutte le possibilità interessanti, richiedono una modifica nel pensiero e alcune modifiche nel modo in cui il codice viene strutturato: altrimenti, come potrebbero portare miglioramenti significativi? In sostanza, penso che siano veramente utili.
L’impedenza tra eccezioni e template mi sembra un pò fasulla. Le eccezioni servono a costruire dei recinti contro le condizioni di errore; ovvero, scegliamo un’interfaccia e decidiamo che solo certi errori potranno passarla. I template sono cattivi candidati per i recinti, perché devono interagire con i tipi definiti dall’utente ed avrebbe poco senso cercare di costruire dei recinti all’interno di codice con forti interazioni. Se c’é un problema di impedenza, così sia; tuttavia, io vedo più che altro una indipendenza di concetti: fanno cose diverse e possono essere usati insieme.

CP:
Però c’é un’impedenza tra i template e la specifica delle eccezioni: siccome i template usano gli argomenti in qualche modo, è quasi impossibile definire una corretta specifica del "recinto", anche in codice che sembra innocuo, come una funzione template per confrontare oggetti... potrei dire in generale che se c’é un lato oscuro nelle eccezioni, é che rendono codice che sembra innocente tutt’altro che innocente.

BS:
In effetti, a volte questo "codice che sembra innocente" non è mai stato innocente. Talvolta è pieno di condizioni di errore non verificate e che possono essere bypassate da setjmp/longjmp. Quindi, le eccezioni spostano l’attenzione su un problema che molti preferirebbero ignorare, ma la complessità è già qui, non è stata introdotta dalle eccezioni. Comunque non penso che abbia senso introdurre la specifica delle eccezioni nei template, almeno non nei comuni template. La ragione, come hai fatto notare, è proprio che le eccezioni potenzialmente sollevate sono quelle specifiche del template più quelle particolari degli argomenti; in questo senso ho ragione quando dico che i template non sono buoni candidati per i recinti. D’altra parte non ha senso rendere ogni piccola porzione di codice a prova di proiettile; preferisco identificare dei sottosistemi e rendere i confini tra sottosistemi dei recinti, ed è così che io uso la specifica delle eccezioni.

CP:
Un’area dove il C++ è ancora debole è la persistenza degli oggetti... esistono molti tool e librerie, ma in molti casi si finisce per utilizzare un preprocessore custom, o a scrivere parti del codice a mano. Il RTTI sembra una via promettente, ma senza uno standard, gli utenti rimarranno sempre legati a delle estensioni non portabili...

BS:
Non sono del tutto sicuro che la persistenza debba essere fornita da un linguaggio general-pourpose. Persone diverse necessitano di diversi tipi di persistenza, con requisiti di prestazioni, sicurezza, controllo degli accessi, natura delle interrrogazioni, ecc, completamente differenti. Per questo preferisco lasciare questo argomento ai produttori di librerie e di database; preferisco evitare l’uso dei preprocessori e di tool extra-linguaggio, ma qualche volta sono necessari. A mio parere, un linguaggio di programmazione non dovrebbe cercare di fare troppe cose: non potrebbe farle tutte bene comunque. E sicuramente l’uso del RTTI può aiutare ad implementare servizi di persistenza e di database.

CP:
Tu sei il progettista di uno dei linguaggi di maggior successo della storia: hai qualche suggerimento per le innumerevoli persone nelle università che partoriscono giusto-un-altro-linguaggio un giorno si ed uno no?

BS:
Fatevi guidare dai problemi. Un linguaggio utile è una soluzione ad un insieme ben noto di problemi, non qualcosa che corrisponde ai criteri di moda di come dovrebbe apparire un buon linguaggio di programmazione. Se non avete un problema serio che non possa essere ragionevolmente risolto con uno dei tanti linguaggi esistenti, non pensate neppure di progettare un altro linguaggio. La progettazione dei linguaggi è un campo dove la percentuale dei fallimenti si avvicina al 100%; nessuna persona sensibile dovrebbe entrare in questo settore se ha un’altra alternativa. Quindi, cercate dei problemi di programmazione seri e senza soluzioni accettabili, e cercate comunque di non avventurarvi nel design di un linguaggio. Se proprio dovete, cercate di copiare quanto più potete - con gli ovvii riconoscimenti - da un linguaggio esistente. Siate pronti a fallire, e con uno sforzo veramente enorme potreste anche avere successo.

CP:
Al momento, un altro linguaggio di successo è il Visual Basic. Alcuni dicono persino che il VB mantenga le promesse dell’OOP e del C++, ovvero molti componenti riusabili, magari un pò a spese di una architettura underengineered. Ti sembra corretto che l’interoperabilità tra compilatori C++ diversi sia lasciata a prodotti di terzi, come il SOM, e non sia garantita dallo standard? Ovviamente ogni standard binario limiterebbe la libertà dei produttori di compilatori, ma questo è vero per qualunque punto dello standard. Io potrei creare un compilatore più efficiente eliminando il supporto per l’ereditarietà multipla, ma questo non è un buon motivo per non lasciare l’ereditarietà multipla nello standard; perché uno standard binario deve essere considerato diversamente? (Ovviamente, uno standard binario è solo un passo verso i componenti software).

BS:
Per me, il C++ mantiene le sue promesse; d’altra parte, non possiamo aspettarci che mantenga le esagerazioni di chi vuole fornire sistemi o linguaggi orientati agli oggetti. Il C++ è un linguaggio di programmazione, non un linguaggio per la definizione di moduli o un sistema operativo. Come ogni linguaggio, non può essere qualunque cosa per chiunque; è possibile costruire dei "componenti software" in C++, ma non è lo scopo principale del C++ e quindi richiede un lavoro addizionale.
L’interoperabilità è un problema molto difficile; le persone tendono a dimenticare che solo attraverso un enorme lavoro ed un’enormità di accordi tra produttori concorrenti siamo arrivati all’interoperabilità tra frammenti di codice C compilati con strumenti diversi. Ci sono voluti accordi sulle sequenze di chiamata, il layout dei dati, i dettagli dell’aritmetica floating point, eccetera. Per il C++ è più complicato che per il C, ma non molto, perché quasi tutti i grandi problemi sono politici e non tecnici. Ad esempio, l’assenza dell’ereditarietà multipla dalle prime versioni del SOM riflette semplicemente la tendenza verso Smalltalk ed Objective C dei primi progettisti del SOM. In un linguaggio come il C++, che si basa sul type checking statico dell’interfaccia, l’ereditarietà multipla è essenziale per prevenire codice convoluto, interfacce poco sicure, o entrambi.

CP:
Per finire, hai qualche nuova idea su cui stai lavorando per il "C++ della nuova generazione" e che vorresti anticiparci? Capisco che vuoi un C++ stabile, ma penso che questo non ti impedisca di pensare a dei miglioramenti, anche solo a livello di implementazione.

BS:
Troppo spesso quando si parla di linguaggi si dimentica la sperimentazione e si pensa a questo campo come ad una branca della matematica o della filosofia. Invece, io penso che il C++ di nuova generazione dovrà nascere da problemi reali in applicazioni reali e dalla sperimentazione, non dalla speculazione e dalla ripulitura del linguaggio. In effetti mi sento più a mio agio descrivendo quello che ho fatto piuttosto che tentando di predire il futuro; mi piace la fantascienza, ma non quando è travestita da articolo tecnico. Ci sono troppi "religiosi" e troppo pochi sperimentalisti nel nostro campo: per migliorare i sistemi informatici abbiamo bisogno di molti esperimenti e di tonnellate di dati. Da questi verranno i suggerimenti che ci permetteranno di individuare i veri problemi e di risolverli; troppo spesso, i ricercatori filosofeggiano su opinioni e teorie invece di puntare ad un vero progresso.

Reader's Map
Molti visitatori che hanno letto
questo articolo hanno letto anche:

Biografia
Carlo Pescio (pescio@eptacom.net) svolge attività di consulenza in ambito internazionale nel campo delle tecnologie Object Oriented. Ha svolto la funzione di Software Architect in grandi progetti per importanti aziende europee e statunitensi. È incaricato della valutazione dei progetti dal Direttorato Generale della Comunità Europea come Esperto nei settori di Telematica e Biomedicina. È laureato in Scienze dell'Informazione ed è membro dell'ACM, dell'IEEE e della New York Academy of Sciences.