Newsgroup: it.comp.lang.c++
Titolo: alternativa alle eccezioni e ad errno globale

Molte volte si usano le eccezioni per segnalare un errore in funzioni
che non possono restituire il codice di errore stesso (ad esempio
Vector::operator[]).
In C in tali casi viene settata la variabile globale errno (che comporta
i suoi problemi).
C'č un modo molto semplice per risolvere una situazione del genere:
#include <cstddef>
const bool success = true;
const bool failure = false;
enum errors_t { EOVERFLOW };
template<typename T> class ReturnValue
{
   private:
      T value;
      bool result;
      int err_type;
   public:
      ReturnValue(T v, bool r = success, int err = 0)
      : value(v), result(r), err_type(err) {  }
      operator T()  { return value; }
      T Value()     { return value; }
      bool Result() { return result; }
      int Errno()   { return err_type; }
};
// esempio
class Vector
{
   private:
      int v[10];
   public:
      ReturnValue<int&> operator[](std::size_t i)
      {
         if(i < 10) return v[i];
         else return ReturnValue<int&>(v[9], failure, EOVERFLOW);
      }
      ReturnValue<const int&> operator[](std::size_t i) const
      {
         if(i < 10) return v[i];
         else return ReturnValue<const int&>(v[9], failure, EOVERFLOW);
      }
};
#include <iostream>
int main()
{
   Vector v;
   int a = v[1];
   std::cout << "v[1] = " << a << '\n';
   ReturnValue<int&> b = v[15];
   if(!b.Result()) std::cerr << "errore: " << b.Errno() << '\n';
   else std::cout << "v[15] = " << b.Value() << '\n';
}
E' una tecnica accettabile?
Saluti  Manlio Perillo

 }
Ciao,
Nicola

 E' una tecnica accettabile?
Se l'obbiettivo e` quello di obbligare il chiamante al controllo
"c'e` per caso stato un errore?" ad ogni pie` sospinto, con la
garanzia di nascondere gli errori (e quindi, presumibilmente,
massimizzare le possibilita` di corruzione di dati persistenti,
emissione di risultati sballati, eccetera) se per caso il chiamante
non fa i dovuti controlli, mi pare che questa sia una buona
strada per avvicinarsi a questo obbiettivo.
Bisognerebbe, se mai, chiedere se _l'obbiettivo_ e` accettabile...
a me non pare che lo sia.
Alex

 guadagni di chiarezza e prestazioni sono davvero notevoli).
Non credo che con la sua soluzione Manlio volesse eliminare tutte le
eccezioni. Penso pero' che ci siano casi in cui i codici di errore siano
utili. Un esempio pratico: nella mia applicazione c'e' una funzione per
il calcolo del rendimento di un investimento, che lancia un'eccezione in
caso di errore. Questa eccezione era intercettata dal sottosistema GUI
che stampava "Non calcolabile".
Poiche' il calcolo e' oneroso ho deciso di memorizzarne il valore alla
prima richiesta e non ricalcolarlo se non cambiano le condizioni al
contorno. Cosi' mi trovo a dover "memorizzare" l'intercettamento di
un'eccezione per poterla rilanciare al momento della richiesta.
Ciao,
Nicola


 Nicola
Ciao   Manlio Perillo

 ReturnValue che specifichi se lanciare eccezioni o meno.
D'accordo, ma introducendo l'eccezione nelle funzioni di conversione
obblighi l'utente a controllare il valore di ritorno, che non e' un
male. Se gli piacciono le eccezioni sfruttera' la conversione implicita
del valore di ritorno:
ReturnValue<int> f();
try
{
    int i = f();
}
catch (...)
{
}
Altrimenti gestira' l'eventuale errore direttamente:
ReturnValue<int> rv = f();
if ( rv.Success() )
{
    int i = rv;
}
Ciao,
Nicola

 C'è un modo molto semplice per risolvere una situazione del genere:

_secondo me_, è inutile restituire v[ 9] se stai cercando v[ 15],
avresti memorizzato un valore per cui non hai nessun interesse ed è
fin troppo facile per colui che utilizzerà il tuo codice dimenticarsi
di andare a verificare se b.Result()  è true oppure false! Preferisco
l'approccio del vector STL, che dispone di due meccanismi di accesso
ai suoi elementi: uno unsafe (l'operator []) e l'altro safe( metodo
at()). Un'altra piccolissima critica la riservo alla classe
ReturnValue: nel caso tu stia specializzando il template per un void
*, è possibile
chiamare inavvertitamente la delete su un oggetto di quel tipo (non
sull'indirizzo, occhio!) e non avere *nessun* tipo di avvertimento da
parte del compilatore (questo comunque basta documentarlo
chiaramente).
Un'altra cosa che potresti fare è dichiarare ReturnValue friend di
Vector e mettere il costruttore protected, così potrai instanziarlo
solo da lì.

guadagni di chiarezza e prestazioni sono davvero notevoli).
Personalmente credo che le exceptions dovrebbero essere usate
per le cose realmente *eccezionali* ovvero quelle che *non*
devono succedere durante l'uso normale di una applicazione.
Ad esempio una funzione che apre un file il cui nome e' stato
fornito dall'utente non dovrebbe lanciare una exception (e'
perfettamente possibile che la open fallisca) mentre l'errore
durante l'apertura di un file contenente i parametri di
configurazione del programma stesso potrebbe essere segnalato
con una exception (in questo caso significa che
l'installazione e' errata)
In particolare il commento di Nicola che usa exceptions per
segnalare che un calcolo e' fallito (e il calcolo e' previsto
che possa fallire) mi sembra un uso poco corretto.
Se una funzione puo' fallire in condizioni "normali" allora
quel fallimento non e' un vero "errore" ... ma uno dei
possibili valori di ritorno e come tale dovrebbe secondo me
essere gestito.
Riguardo ad altri usi di exception ho letto che e' il caso di
fare *molta* attenzione a non cadere nella tentazione di usare
le exception come scorciatoie (es. tornare un risultato da
una funzione di ricerca ricorsiva)... in alcune
implementazioni una throw richiede *decine di migliaia* di
volte piu' tempo di uno statement di return.
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 essere gestito.
Il problema con questa filosofia e` che in questo modo il
codice "normale" della mia applicazione resta oberato e
nascosto dai diecimila controlli per "anomalie che pero`
non sono eccezioni".  Mantenere il "caso normale" come
flusso principale del programma, alleggerendolo dai mille
controlli altrimenti necessari, e spostare questi ultimi
agli exception handler, e` un GRANDE miglioramento di
chiarezza.  La chiarezza di un programma e` un obbiettivo
la cui importanza mi e` sempre piu` chiara man mano che
crescono le dimensioni dei sistemi che sviluppo...
Alex

 un'eccezione per poterla rilanciare al momento della richiesta.
Scusa, ma (senza voler escludere che i codici di errore abbiano
degli usi validi) non mi sembra un buon esempio.  Visto che la
gestione dell'eccezione stessa e` tipicamente molto costosa, non
e` secondo me un problema se invece di "memorizzarla" essa viene
generata ex novo ogni volta, ripetendo i calcoli errati.  Se lo
fosse, basterebbe comunque che il "memorizzatore" (che decora il
vero sistema di calcolo) intercettasse (per poi ri-alzarla) la
exception, provvedendo a memorizzare i dettagli che essa contiene
(if any) e un flag di tipo bool.
Un esempio in cui l'uso dei codici di errore e` preferibile puo`
essere un compilatore a discesa recursiva che sta cercando di
parsare una produzione di tipo:
    <pippo> ::= <pluto> || <paperino>
La routine che parsa 'pippo' puo` chiamare quella che parsa
'pluto', se e` andata bene tornare, se no provare quella che
parsa 'paperino'.  Qui il "fallimento" del parse di 'pluto'
e` uno caso TIPICO, tutt'altro che raro, quindi l'uso di
exception per comunicare "non riesco a parsare la produzione
che mi spetta" potrebbe dare problemi di prestazioni.
Alex

 crescono le dimensioni dei sistemi che sviluppo...
Anche nel mio piccolo (nel piccolo delle mie applicazioni) considero la
chiarezza un aspetto fondamentale, alla pari con la aderenza alle
specifiche. E questo mi è chiaro ormai da diversi anni.
EMG

crescono le dimensioni dei sistemi che sviluppo...
Sicuramente vero. Credo pero' che un uso intelligente
della logica a return code possa mantenere una buona
leggibilita' senza le insidie delle exceptions.
In particolare credo che la massima eleganza nell'uso
di exceptions ci sia quando si considerano casi banali
che vengono mostrati sui testi... secondo me pero' i
vantaggi non "scalano" quando ci si sposta nei casi
concreti in cui la complessita' e' superiore.
Si corre inoltre a mio parere il grosso rischio di
scrivere codice "brutto" e poco sicuro senza rendersene
conto e anzi illudendosi di aver fatto le cose per bene.
Andrea
(che si scusa per il solito messaggione :DDDD)


Condivido pienamente.
Forse allora non ho capito. Si sta dicendo di mettere
un try/catch in ogni punto in cui una exception potrebbe
essere generata per usare una exception per gestire tutte
le possibili anomalie ?
Secondo me il problema con le exception e' il codice che
viene "interrotto" senza che ci sia una gestione esplicita:
il problema non e' chi lancia una exception o chi la
gestisce... ma i poveri intermedi che vengono interrotti
senza aver la possibilita' di rimettere a posto il loro
stato interno o le "mezze modifiche" che stavano facendo
allo stato globale.
Se questo codice non esiste o e' presente in percentuale
bassa oppure se si e' prestata la *massima attenzione* a
scrivere sempre codice che fosse exception-safe (cosa che
non credo sia cosi' banale) allora il discorso fila.
Resta secondo me discutibile che questo approccio porti
a codice piu' chiaro e manutenibile di una logica a
return-code per i casi non veramente eccezionali.
Praticamente bisognerebbe scrivere codice pensando
continuamente che quasi ad ogni istruzione (anzi... anche
a meta' di molte delle singole espressioni) l'esecuzione
potrebbe essere interrotta. Salvarsi dalla perdita di
risorse e' semplice... salvarsi dal lasciare le cose
"sporche" nello stato dell'oggetto oppure nello stato
globale del programma e' secondo me decisamente piu'
complicato.


 complicato.
Scrivere codice "a transazioni" non e` banale (benche`
spesso indispensabile) se non hai supporto di tipo
infrastrutturale.  Per fortuna di solito lo hai, perche`
i DB relazionali veraci (lasciamo perdere MySql..:-)
le transazioni le supportano eccome -- per cui in
molti casi si tratta di scegliere fra un commit e
un rollback *a fine transazione* con l'atomicita`
comunque garantita in modo abbastanza solido.
Il supporto di "atomicita`" all'interno del programma
applicativo di solito viene "quasi gratis" se progetti
il programma in modo da supportare livelli illimitati
di UNDO e REDO, esigenza comunque tipica dei programmi
professionali di tipo interattivo.  Per il supporto
generale a undo e redo, occorre comunque potere avere
degli "snapshot di stato" (di oggetto o globale) e
degli oggetti "delta di stato rispetto all'ultimo
snapshot".  Questi oggetti fanno molto comodo per
progettare un livello di atomicita` di transazione
all'INTERNO dell'applicazione!  Comunque, i problemi
non sono molto diversi se questa atomicita` (e quindi
la possibilita` di regredire i cambiamenti parziali
di stato!) la vuoi implementare in una funzione che
controlla i codici di ritorno di tutte quelle che
chiama, ovvero in una che gestisce la finalizzazione
in apposititi distruttori di oggetti auto: nel secondo
caso le cose sono meglio incapsulate e quindi spesso
strutturate in modo piu` chiaro, manutenibile, ecc, ma
il livello di difficolta` e` comunque paragonabile.
Forse se facciamo qualche esempio un po' astratto e`
piu` facile mettere a fuoco i problemi.  Supponiamo
che la ns strategia base sia una a snapshot/restore
piuttosto che una a delta (questioni di interfaccia,
internamente snapshot/restore si puo` implementare
in termini di delta).  Con controllo esplicito errori:
int midlevel_controlla(appobject& app)
{
    snapshot snap(app);
    int rc1 = lowlevel1(app);
    if(iserror(rc1)) {
        snap.rollback();
        return rc1;
    }
    int rc2 = lowlevel2(app);
    if(iserror(rc2)) {
        snap.rollback();
        return rc2;
    }
    int rc3 = lowlevel3(app);
    if(iserror(rc3)) {
        snap.rollback();
        return rc3;
    }
    snap.commit_work();
    return success;
}
Con gestione basata sulle eccezioni:
void midlevel_exceptions(appobject& app)
{
    snapshot_with_rollback_on_dtor snap(app);
    lowlevel1(app);
    lowlevel2(app);
    lowlevel3(app);
    snap.commit_work();
}
Ove, se occorre, evidentemente:
class snapshot_with_rollback_on_dtor: public snapshot {
public:
    snapshot_with_rollback_on_dtor(appobject& app):
        snapshot(app) {}
    ~snapshot_with_rollback_on_dtor() {
        this->rollback();
    }
};
Templatizza a piacere, complica la business logic
di midlevel() cosi` da avere condizionali e cicli,
ecc, ecc, non cambia poi tanto... la versione
midlevel_exceptions e` piu` semplice e lineare
della midlevel_controlla, *E* quest'ultima non
e` exception safe (anche se le lowlevel1() ecc sono
throw(), io non sarei tranquillo... le exception
specification in C++, ahime`, NON sono fra le parti
piu` limpide, possenti e funzionali del linguaggio).
L'unico problema sostanziale puo` essere uno di
prestazioni SE il ritorno "di errore" da una o
piu` delle lowlevelN() avviene con una certa
frequenza _E_ l'intera midlevel() e` parte di
un bottleneck di un qualche tipo di use-case.
Togliere le exception a favore di controlli piu`
espliciti su di un codice d'errore puo` dunque
essere visto come una possibile OTTIMIZZAZIONE.
Nulla di strano dunque che complichi un poco le
cose, puo` comunque valere la pena SE l'effetto
sulle prestazioni e` molto positivo.  Ma ricorda:
"l'ottimizzazione prematura e` la radice di tutti
i mali" (citazione di Knuth, credo...)...!-)
Alex (MVP di Brainbench per il C++)

 che mi spetta" potrebbe dare problemi di prestazioni.
Mi viene da pensare che anche in questo caso il problema possa essere
affrontato estendendo l'insieme dei valori validi con uno o piu' valori
convenzionali. Tra l'altro il problema in un compilatore e' non
"impazzire", ovvero cercare di riprendere la compilazione correttamente
il prima possibile. Per questo e' importante che il valore ritornato
"sembri" valido.
Ciao,
Nicola

 }
Ciao,
Nicola

 concreti in cui la complessita' e' superiore.
Buffo, perche` la situazione reale mostrata dalla mia
esperienza e` esattamente IL CONTRARIO di quel che tu
affermi.  Tieni presente inoltre che, oltre a scrivere
io stesso codice C++, faccio da "consulente/guru" di C++
per (ormai) un paio di centinaia di sviluppatori in
questa azienda (
www.think3.com
), il che "amplifica"
l'esperienza in quanto vengo sistematicamente richiesto
di intervento nei casi problematici.
Le architetture che "non scalano" sono quelle in cui
le exception NON sono usate; avere centinaia di persone
che sviluppano codice "insieme", in otto laboratori
in tre continenti, e` l'elemento principale di questi
"problemi di scaling" tipici del software development
"su grande scala" -- non certo l'unico, ma esaspera
quelli che su tipica scala artigianale, una o tre o
dieci persone in una o due location, si possono forse
ancora gestire "a cucci e spinte".
Prendi ad esempio il tuo codice, che qui ho snippato,
in cui la chiamata a
    iof->Leggi(uncampo, specifiche)
puo` _silenziosamente_ NON settare 'uncampo' se lo
stato di iof e` in errore.  Questa peculiare semantica
puo` non essere chiara al programmatore di Bangalore
che si trova domani a manutenere questo codice; egli
ragionevolmente supporra` che 'uncampo' SIA ora settato
a qualcosa e procedera` a testarlo/usarlo, causando
ALTRI errori.  Il debugging in teleconferenza fra due
o tre siti in fusi orari diversi e` poco divertente,
ti assicuro, ed e` esattamente quel che la mia personale
(vasta) esperienza mi porta a predire osservando l'uso
di questa design-pattern.
Purtroppo non posso continuare a dedicare ore ogni
giorno a questo dibattito (che in effetti mi fa ricordare
perche` ho smesso a suo tempo di seguire i.c.l.c++...
le cose piu` interessanti sono tipicamente quelle
sullo sviluppo in grande scala, e NON e` facile in
poche centinaia o migliaia di righe convincere chi
non si e` ancora mai trovato a coordinare progetti
di milioni di righe su scala globale:-).  Penso che
solo l'esperienza, non le discussioni, possa avere
valore di convincimento.  Se non dedichi tempo ed
energia a farti esperienza sull'uso delle exception
(anzitutto studiando bene il testo di Sutter, ma poi
*usandole*: la prova del budino sta nel mangiarlo),
non credo che nessuna chiacchierata potra` mai
convincerti che sbagli, no?  Tieni solo presente il
dato di fatto che alcuni di noi, CON milioni di righe
e oltre dieci anni di esperienza C++, si sono
gradualmente convinti che (anche in questo) l'esperienza
enorme complessivamente contenuta nel comitato di
standardizzazione del C++ li ha portati sulla strada
giusta (sia per le exception, sia per aspetti come
la loro natura terminating e non retryable, ecc, ecc;
non su tutto -- le exception-specifications lasciamole
perdere... funziano in Java, ma il 'retrofit' in C++
lascia troppo a desiderare:-).  Delle exception e della
relativa safety non si puo` fare a meno come non si
puo` farlo dei template o dei const:-).
Sullo specifico problema di QUALI errori vadano poi
segnalati con exception e quali diversamente troverai
pareri discordi anche fra gente con esperienza da
vendere (alla lettera:-), ma il dibattito viene
comunque a svolgersi entro il contesto in cui *la
exception safety NON e` facoltativa*.  VISTO che
l'exception-safeti C'E` (ci DEVE essere!), io trovo
che (prestazioni a parte) sia il caso di farne uso
per migliorare la semplicita` in molti casi "di
errore" -- basta che la probabilita` d'occorrenza
dei casi sia BASSA, non occorre che essi debbano
rappresentare orrende impensabili emergenze.
Condivido, insomma, l'eccellente filosofia della
Boost Library (
www.boost.org
):
"""
Use exceptions to report errors where
appropriate, and write code that is safe
in the face of exceptions;
Avoid exception-specifications.
"""
Naturalmente e` possibilissimo che Abrahams, Adler,
Bonnard, Brey, Collings, Colvin, Corfield, Dawes,
Dimov, Gurtovoy, Henney, Hinnant, Josuttis, Kempf,
Kuehl, Lee, Maddock, Maurer, Moore, Powell, Rodgers
e Siek commettano un gravissimo errore a specificare
che vanno usate le eccezioni per far rapporto degli
errori ove appropriato, quanto Martelli ad essere
d'accordo con loro.  Sulla parte "scrivi codice che
e` sicuro a fronte di eccezioni", invece, non c'e`
tanto da discutere...:-).


 "sembri" valido.
Le tecniche a sentinella sono usabili anche qui, ma per la
maggior parte delle grammatiche non sono le migliori per
"risincronizzare" la compilazione in caso di errore (meglio
gli stop-symbol).  Comunque l'idea di cercare di diagnosticare
Nmila errori in un run e` uno di quei fossili dell'era delle
schede perforate... Hejlsberg aveva l'idea giusta quando fece
Turbo Pascal -- semplificare il parser, migliorare le sue
prestazioni, ecc, facendogli diagnosticare solo il PRIMO
errore.  Tanto le probabilita` che su 99 diagnostiche io
possa riconoscerne e correggerne piu` di una e` praticamente
trascurabile -- in pratica sistemo il primo errore e riprovo
(prova tu a dare UNA diagnostica in un compilatore C++ per
UN caso di 'typedef' che diventa 'tyepdef'... 99, o qualsiasi
sia il limite di segnalazione, e` piu` probabile!-).


 Nicola
saluti,
/fabio

 sufficientemente simile alla versione con le eccezioni da elevare il
No.  Un livello illimitato di annidamento presenta
una struttura arbitrariamente differente da una
perfettamente piana e lineare.
Come dimostrazione di complessita` dell'annidamento,
penso basti fare UNA semplice considerazione sul
codice che hai appena postato.  Fai "una provocazione",
quindi TI ASPETTI naturalmente (bonarie) polemiche,
quindi quel che posti ci tieni che sia corretto -- e
sei un programmatore di vaglia.
Bene, CON TUTTO QUESTO... cosa succede nella tua
versione se lowlevel1() ha successo ma poi invece
lowlevel2() fallisce?  Risposta (esamina il tuo
codice!): non viene chiamata NE` .rollback() NE`
.commit_work() sullo snapshot, e midlevel() torna
asserendo tranquillamente e falsamente che tutto
e` andato benone.
"Oops, un errorino, succede".  *APPUNTO*.  E`
appunto perche` siamo umani, ed errare e` umano,
che utilizzare annidamenti dove si possono usare
strutture lineari e` peggio di un errore, e`
HUBRIS -- e gli dei la hubris la puniscono.  Nota
quanto facilmente possono confondere gli annidamenti
ed i controlli espliciti d'errore.
(Questo porta anche a un pensiero positivo verso
Java: in Java il compilatore ti segnalerebbe un
errore perche` non puoi ridefinire uno stesso nome
di variabile in due blocchi annidati fra loro.
L'annidamento e` *troppo complesso*: il progetto
di Java riconosce ed ammette questo fatto, e pone
delle limitazioni formali al programmatore, pero`
in cambio gli salva la ghirba rispetto ad errori
del genere, di quelli che "si fanno le quattro di
mattina col debugger" per un nonnulla... il C++
a volte un pizzico di hubris ce l'ha:-).
Alex (MVP Brainbench per il C++)

}
A parte l'ovvia svista di ripetere "int rc" che comporta problemi
di funzionamento quello mostrato e' comunque un metodo abbastanza
scomodo di gestire la cosa (mi ricorda tanto DirectX, che
personalmente credo sia il risultato di anni di studio di un
comitato votato a complicare le cose semplici).
Se la funzione puo' "fallire" in contesti non critici io
preferisco utilizzare il valore di ritorno per indicare il
successo dell'operazione (con un bool) e passare per riferimento
dove memorizzare il risultato in caso di successo.
Con questo sistema il codice diventa:
   bool midlevel_controlla(appobject& app)
   {
     snapshot snap(app);
     if (lowlevel1(app) &&
         lowlevel2(app) &&
         lowlevel3(app) &&
         snap.commit_work())
       return true;
     log_error("Errore in midlevel_controlla");
     snap.rollback_work();
     return false;
   }
In questo modo a chi guarda il codice diventa anche molto chiaro
che le funzioni lowlevel* possono fallire.
In alcuni casi (vedi fopen) il valore di ritorno puo' essere
usato efficacemente come indicatore di un fallimento possibile
anche in condizioni non eccezionali.
Le exception generano dei percorsi di esecuzione diversi non
molto differenti da delle if (anzi... da dei goto) ma lo fanno
in modo implicito. Se di queste cose ci si potesse
disinteressare perche' tutto funziona comunque allora
concorderei con l'uso di exception per anomalie di ogni livello
(leggi: "se fosse presente un sistema di rollback automatico
sullo stato del sistema"); questo pero' non e' vero in generale
e quindi credo che nascondere questa complessita' (che e'
presente e che puo' creare problemi se sottovalutata) sia una
mossa discutibile.
Con una gestione implicita di rollback di stato trovo che le
exceptions siano un modo *molto elegante* di semplificare la
programmazione (per chi e' interessato ho provato tempo fa
a implementare la cosa in un caso particolare... vedi
"Gestione transazioni in C++" nella mia homepage, sezione
"Documenti").


un bottleneck di un qualche tipo di use-case.
Ripeto che ho citato il problema di prestazioni perche'
la tentazione di uso di exceptions a sproposito puo'
essere forte. Questo tipo di usi non lo ritengo molto
diverso da programmi C basati su longjmp dove non
realmente necessario.


...:-).
E' qualcosa che costa. A volte ha riflessi anche
sull'interfaccia che si vuole dare alle classi.
Se non e' richiesta e' una operazione inutile. O no ?
Andrea


    }
In effetti il codice risulta piuttosto pulito, e la sua struttura non e'
molto diversa da quella che avrebbe in presenza di gestione di
eccezioni.
Ciao,
Nicola

 di milioni di righe su scala globale:-).
Qui sollevi un problema fondamentale: per quel che ne so tutta la
letteratura sull'argomento, e con l'eccezione del libro di Lakos, piu'
in generale la massima parte della letteratura sul C++ punta su aspetti
microscopici e non su aspetti macroscopici. Ho la sensazione che si sia
in qualche modo creata una frattura tra chi scrive a proposito di grossi
progetti e tende a concentrarsi su aspetti manageriali, trascurando
quelli tecnici, e chi scrive di aspetti tecnici e tende a trascurare la
programmazione "in the large", se non tutta quell'area grigia che serve
a trasformare un programma in un prodotto.
Bisognerebbe che qualcuno scrivesse un libro intorno ad un'applicazione
concreta di qualche migliaio di linee di codice, disegnata applicando
prassi derivata da progetti molto piu' ampi. Se e' vero che non sono
approcci presentabili in un newspost, penso che le dimensioni che ho
indicato sopra permettano di dare un'idea concreta. Quando hai finito
"Python in a Nutshell"... :-)
Ciao,
Nicola

 molto diversa da quella che avrebbe in presenza di gestione di eccezioni.
...eccetto che la struttura non e` minimamente generalizzabile con
modifiche locali a fronte della piu` minima tweak di specifiche,
tipo "e lowlevel2 va chiamato N volte", come gia` indicavo.  Vabbe`,
raga`, evidentemente quando si postano esempi giocattolo bisogna
stare molto attenti a dargli quel MINIMO di 'ricchezza' che renda
impossibili le soluzioni triviali; scusate, evidentemente mi sono
abituato di recente a fare consulenze piu` che altro con validi
professionisti che "vedono" subito, quando io scrivo "a poi b poi
c", che OVVIAMENTE questo e` il tipo di specifiche che nel release
0.01 diventa "a poi N volte b poi c", e voglio naturalmente un
approccio che si generalizzi per trasformazioni locali di codice
a questi prevedibili e inavitabili "generalizzazioni".  Se torno
a postare regolarmente in i.c.l.c++ dovro` starci piu` attento...
Alex

 "Python in a Nutshell"... :-)
...avendo imparato sulla mia pelle che fatica mostruosa e`
scrivere un libro degno di questo nome, dubito che ne scrivero`
altri per i successivi 23 anni...:-).


 altri per i successivi 23 anni...:-).
E' perche' hai scritto il primo libro a 23 anni o e' un numero "biblico"
come 40 o (con un attimo di commozione) 42?
Ciao,
Nicola

 a postare regolarmente in i.c.l.c++ dovro` starci piu` attento...
Nel nostro campo prendere le cose letteralmente e' a mio avviso un
pregio :-) Il problema e' che con i tuoi colleghi esiste comunque un
contesto di riferimento, mentre nel newsgroup ogni thread apre un
contesto nuovo. Comunque se "resti con noi" ci fai solo piacere.
Ciao,
Nicola

 da un punto di vista intellettuale.
Beh, finalmente ho risolto il problema del tempo che
mi stava prendendo questo thread.  Non capisco su che
basi mi stai accusando di disonesta` intellettuale,
chi sia colui che "ha gestito i sistemi per davvero"
(?) e chi colui "che semplice afferma".  Capisco pero`
che questa e` una diretta accusa di disonesta` che
considero di non avere fatto nulla per meritare, e
di conseguenza, *PLONK*.  E` bello avere un killfile.
Buona vita,
Alex

 Se non e' richiesta e' una operazione inutile. O no ?
Se "non e` richiesta" e` perche` chi ha steso la
richiesta non capisce molto della questione.  Se
cercare di approfittarti della sua ignoranza o meno
e` una questione anzitutto morale, ma a mio parere
alla lunga non conviene mai "tirare a fregare" chi
non e` (per ora) in grado di capire che lo stai
fregando -- pagherai in futuro un prezzo (perdita
di stima commerciale, ecc) per questi piccoli e
meschini guadagni a breve termine.  Questione di
scelta di filosofia professionale e di vita, se
vuoi.  Io mi trovo bene con la mia: fare il SW
*BENE* anche se il committente non ci capisce 1/2
acca e sarebbe (a breve) piu` felice di avere un
accrocco tenuto insieme con lo spago usato.
Comunque, ribadisco che non troverai supporto per
la posizione "non essere exception safe, tanto",
fra i professionisti 'scafati' del settore.  E`
una situazione ben diversa dal decidere se in un
dato caso specifico e` o meno ottimale usare una
exception, o anche da una filosofia generale che
puo` portare Mr X a usare exception nel 12% dei
casi e me invece nel 34% dei casi per una certa
applicazione con le stesse specifiche.
(Forse e` meglio che escluda da queste mie tesi
lo sviluppo di 'software embedded', che tante
volte sembra essere un mondo tutto a se e non
conosco abbastanza bene da prevedere in questo
modo -- mi dicono che sta diventando piu` normale
al crescere della potenza e al calare del costo
dell'HW su cui gira, ma in passato e` stato in
genere un mondo ibrido fra il SW e l'HW, con
esigenze real-time che possono rendere ad es.
l'allocazione dinamica di memoria inaccettabile,
e dunque immagino anche le exception o chissa`
mai che altro... parliamo di SW "vero"!-).
Alex

 come 40 o (con un attimo di commozione) 42?
http://everything2.com/index.pl?node=23
Alex

mai che altro... parliamo di SW "vero"!-).
Hmmm... in questo momento mi sto occupando anche di
software embedded. Forse la mia visione e la mia
necessita' di "evidenza" di cosa succede e perche'
derivano anche da questo.
Per chi lavora solo con un monitor forse la
stabilita' e' meno importante ("provi a uscire e
rientrare e mi richiami se il problema si ripete").


E` bello avere un killfile.
Dubito molto che tu non abbia capito cosa intendevo dire
con la non confrontabilita' del passato (che comunque qui
ci ha portato) con le promesse del futuro.
Ti confesso che un poco mi incuriosisce la morbosa
necessita' che senti di trovarti una giustificazione
per inserirmi nel tuo killfile... fallo e basta no ?
Se proprio ci tieni al limite mettici come nota
"in quanto non prende per oro colato quello che dico".


a postare regolarmente in i.c.l.c++ dovro` starci piu` attento...
Qui purtroppo non ci sono validi professionisti ?


direzione, la mia versione.
Personalmente anche io non apprezzo troppo gli annidamenti:
preferisco in questi casi avere codice tutto allo stesso
livello usando altri sistemi (operazioni che diventano NOP
se ci si trova in una condizione di errore oppure una variabile
di flag che "rompe" ad esempio i loop).


Ragazzi, un suggerimento : cercate di sintetizzare maggiormente i
messaggi.  Non credo sia agevole per nessuno leggere 698 righe di
messaggio.
--
Walkie...@Libero.It (ICQ# 8143647)

applicativo di solito viene "quasi gratis" se progetti
Una domanda banale : che si intende per "atomicita'" ?
--
Walkie...@Libero.It (ICQ# 8143647)

messaggio.
Effettivamente rileggendomi mi trovo prolisso e ripetitivo.... :(
Riguardo al quoting invece non mi sembra di esagerare molto.


 Riguardo al quoting invece non mi sembra di esagerare molto.
Per altro thread *densi* di contenuto di buon livello capitano di rado e
credo che i nostri lurker farebbero bene a cogliere al volo l'occasione.
Ciao,
Nicola

credo che i nostri lurker farebbero bene a cogliere al volo l'occasione.
I thread densi di contenuto di buon livello sono cio' che rincorriamo
da tempo (e quando c'e' Alex di mezzo, non puo' essere altrimenti). 
Il problema e' che non si riesce a stare dietro a messaggi cosi'
lunghi e forse a qualcuno interesserebbe anche partecipare alla
discussione... 
--
Walkie...@Libero.It (ICQ# 8143647)

 Una domanda banale : che si intende per "atomicita'" ?
O "transazionalita`": caratteristica di una "azione"
(alterazione dello stato di un programma o di stato
persistente, come file o parti di un database) che, o
viene compiuta interamente, oppure per nulla.  Non
viene, insomma, "fatta a meta`" (lasciando lo stato in
una situazione semanticamente non coerente).
Di solito si usa "atomicita`" parlando "su piccola
scala" (ad esempio in un contesto di threading) e
"transazionalita`" su scala maggiore, ma questa
sottile distinzione non e` rigorosamente necessaria.


 messaggio.
Dopo una overdose di lavoro che mi ha tenuto lontano dal NG sto rientrando
proprio su questo lungo thread (sia per numero che per dimensione dei messaggi).
Vero sono messaggi lunghi. Ma se le cose non sono cambiate nelle ultime due
settimane ... meglio un messaggio interessante di 700 righe che 70 messaggi OT
di 10 righe come avveniva, appunto, due o tre settimane fa (e sospetto avvenga
tutt'ora).
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

tutt'ora).
Non voglio polemizzare ma non credo che un messaggio di 700 righe sia
nel pieno rispetto della netiquette.  Nessuno lo puo' leggere
facilmente e messaggi cosi' lunghi finiscono per interessare solo chi
scrive e ribatte.  Cerchiamo di accorciarli, se possibile. 
--
Walkie...@Libero.It (ICQ# 8143647)

 scrive e ribatte.  Cerchiamo di accorciarli, se possibile.
Condivido.
EMG

 wrote in message
news:3B0ED52D...@flashnet.it...

Condivido in parte.
Condivido il non voler polemizzare.
Non condivido il discorso sulla netiquette: se il contenuto e' on topic, non si
e' ecceduto nel quoting e non vi sono prolissità e ripetizioni faziose e inutili
il messaggio rispetta la netiquette.
Non capisco il "nessuno lo puo' leggere facilmente". Io trovo piu' facile
leggere un unico testo, coerente, on topic e persino (ma questo e' soggettivo)
interessante nei contenuti che non 70 messaggi da 10 righe, spesso incoerenti o
che chiedono tutti la stessa cosa (la netiquette prescrive di seguire un NG per
qualche settimana prima di postare, ma ci sono domande che vengono poste ogni
due o tre giorni da persone diverse, e sono sempre le stesse), peggio se sono
OT, e raramente pongono domande interessanti (nel senso generale del termine,
ovvero domande che riguardano argomenti generali e non problemi specifici
assegnati dal tal professore).
Non condivido, e neppure capisco, in che senso un messaggio finisce con
l'interessare solo chi partecipa alla discussione se e' lungo. I messaggi che
interessano solo coloro che dibattono sono quelli legati a flame o quelli
sterili (per esempio questo stesso messaggio) non quelli lunghi.
In ogni caso, se l'argomento e' interessante e on topic e il messaggio raggiunge
lunghezze di centinaia di righe, propongo di "taggarlo" come [long], piu' che
evitare di scriverlo (a parte che sono pochi, credo, i NR che non ti permettono
di vedere la lunghezza di un post prima di scaricarlo).


l'interessare solo chi partecipa alla discussione se e' lungo. 
Perche' se uno non lo riesce a leggere, non riesce nemmeno a capirne i
contenuti e/o a ribattere.
--
Walkie...@Libero.It (ICQ# 8143647)

 di vedere la lunghezza di un post prima di scaricarlo).
Peccato che non tutti abbiano connessioni fisse. Io, con la mia semplice
dial-up, sono obbligato a fare il download completo e poi vedere cosa ho
scaricato. Fare la selezione on-line sarebbe, per me, troppo costoso.
EMG

 scaricato. Fare la selezione on-line sarebbe, per me, troppo costoso.
Stai dicendomi che il tuo programma di news non ti permette di scaricare solo
gli header? Non ci credo.


 contenuti e/o a ribattere.
Si, ma ho seguito thread (rari, purtroppo) di decine di messaggi, ciascuno di
qualche centinaio di righe, che ho trovato interessantissimi, senza flame, non
ripetitivi. E il fatto che non vi ho partecipato (e altri con me) o che i
partecipanti fossero solo 2 o 3 persone non li ha resi meno interessanti.


 contenuti e/o a ribattere.
Infatti. Se l'autore si prendesse anche l'onere di sintetizzare sarebbe
più facile per tutti.
EMG

scaricato. Fare la selezione on-line sarebbe, per me, troppo costoso.
Io avevo questi problemi qualche anno fa (con i modem lenti).
Ora onestamente il tempo di scaricamento con un 56k non e' un
granche'. Chiaro che io seguo solo un paio di gruppi (e leggo
solo una frazione dei messaggi di ciascuno).


 gli header? Non ci credo.
E quando ho scaricato gli header che faccio? Cancello quelli che non mi
interessano e faccio il download del body degli altri? Ci vuole troppo
tempo. Preferisco scaricare tutto e non leggere ciò che non mi
interessa.
EMG

 granche'.
Infatti. Il tempo di scaricamento è troppo rapido per confrontarlo con
quello che mi occorrerebbe per controllare gli header uno per uno. Mi
conviene scaricare anche i body e via. Inoltre non sempre dall'header si
capisce se il messaggio è interessante o meno.
EMG

Volevo aggiungere un paio di commenti a questo sub-thread, di cui
comprendo le motivazioni, ma che non condivido pienamente.
E' vero che i messaggi troppo lunghi non sono molto pratici, ma ci sono
argomenti perfettamente in topic nel nostro newsgroup che non si possono
sviscerare in quattro parole. Personalmente preferisco poter scegliere
se leggere *tutto* un messaggio interessante, che non inibire chi ha il
tempo di scriverli.
Quello che forse dovremmo cercare di evitare sono i messaggi che
abbracciano tutto lo scibile informatico, per non dire umano. Alcuni di
noi hanno competenze ampie e variegate, ma non per questo dovrebbero
sentire la necessita' di manifestarle *tutte* in ogni post :-)
Quindi cerchiamo di concentrarci sul C++ e sul suo utilizzo, limitando i
riferimenti "esterni" al minimo indispensabile per chiarire il proprio
punto di vista.
Ciao,
Nicola

 sentire la necessita' di manifestarle *tutte* in ogni post :-)
In generale è vero. Ma in particolare i post (ormai rari) di Alex
Martelli sarebbero incompleti senza quelle continue citazioni,
raffronti, analogie e riferimenti. Non mi sembra ci sia nessun altro di
noi (io poi sto all'ultimo posto) in grado di scrivere in quel modo.
EMG

piů facile per tutti.
perň non sempre č possibile farlo. Essere sintetici ed efficaci al
tempo stesso č impresa ardua. Allora tanto vale essere un po' piů
lunghi ma farsi capire bene. Altrimenti si rischia di generare una
serie di reply del tipo "cosa significa questo", "non ho capito", ecc.
ecc.
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 ecc.
Il problema č, secondo me, che per le spiegazioni dettagliate esistono i
libri...
EMG

libri...
Bello... praticamente un newsgroup in cui uno dice
 "Secondo me le exceptions bisogna usarle per tutte
  le 'anomalie'... siano esse veri errori oppure no.
  Chi ha dubbi si legga dei libri. Bye."
e uno risponde
 "Secondo me no. Chi ha dubbi si legga altri libri.
  Bye."
... mah ...


 ... mah ...
No, certo. Io mi riferivo piů che altro a domande del tipo "A cosa
servono i puntatori?" o "Come si usa il polimorfismo?". Beh, la risposta
si trova sui libri non su un newsgroup. Non sei forse d'accordo?
EMG

si trova sui libri non su un newsgroup. Non sei forse d'accordo?
Assolutamente. E la cosa peggiore e' che ogni tanto si vede
qualcuno che spiega (ovviamente male) i puntatori e le strutture
dati in 20 righe. Non so se si tratta di un vero aiuto per chi
comincia...


 libri...
Curioso. Ho sempre pensato esattamente il contrario.
Ovvero che i libri dovessero dare il background e le conoscenze di base. E nei
NG ci si potesse trovare approfondimenti sui dettagli che non sono nei libri
nonche' discussioni (ovvero confronti di opinioni) che per definizione non
stanno sui libri (un libro al massimo riporta una opinione, non una
discussione).
Che poi ci sia un sacco di gente che cerca di imparare il C++ leggendo le news
senza comperarsi dei libri ... questo e' un altro discorso.


 senza comperarsi dei libri ... questo e' un altro discorso.
Quindi, a quanto sembra (e contrariamente a quanto sembrava all'inizio
del messaggio), siamo praticamente d'accordo...
EMG

 si trova sui libri non su un newsgroup. Non sei forse d'accordo?
Non sono daccordo, molto spesso anche nel trattare argomenti "banali" 
escono spunti molto interessanti. 

 libri...
Vi rendete conto che state scrivendo in un thread con un subject che non 
centra niente con le argomentazioni ...
Non č meglio iniziare un nuovo thread ? Trovo piu' complicato seguire 
thred troppo "ramificati" che messaggi lunghi.