|
|
|
![]() |
|
Strumenti |
![]() |
#21 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Con le eccezioni esplicite lo scaricabarile non c'è, o al limite è voluto. Se si usa throws in Java (fortunatamente ti obbliga a farlo) e throw in C++ (accanto alla firma del metodo) non ci sono di questi problemi, perché l'eccezione sei obbligato a gestirla o al limite ad usare gli stessi throw e throws accanto alla firma del metodo chiamante.
Non concordo sul fatto che la gestione e l'implementazione delle eccezioni sia utile solo in funzioni di libreria. Io tra l'altro penso che un programma serio vada organizzato a moduli e che ogni modulo sia di fatto trattato come una libreria. Per questo penso sempre ad un modulo di un programma come un insieme coerente e di fatto ai fini esterni simile ad una libreria in cui gli utilizzatori sono gli altri moduli. Ultima modifica di cionci : 19-03-2010 alle 09:18. |
![]() |
![]() |
![]() |
#22 | |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Con la differenza che puoi sempre ignorare un codice di ritorno, ma non un'eccezione. Considera poi che tutti i metodi del .NET ma anche di Java ti ritornano delle eccezioni se non riescono ad eseguire per un qualunque motivo ovvero o hai il risultato desiderato o hai una eccezione. |
|
![]() |
![]() |
![]() |
#23 |
Member
Iscritto dal: Jun 2006
Messaggi: 117
|
Oh oh attenti... non sto mica dicendo di non usare le eccezioni!
La verita' e' che il modello delle eccezioni impone un lavoro massivo da parte del programmatore per gestire tutte le possibili eccezioni generabili. Di conseguenza cosa succede? Succede che se il metodo che genera le eccezioni e' una libreria di terzi, il programmatore finisce per ingoiarsi tutte le eccezioni con un unico catch Exception generico, che sostituisce magari 10 catch ognuno per ciascuna eccezioni generabile dal metodo in question (e Java con le checked exception ti costringerebbe a farlo, a differenza di tutti gli altri linguaggi). Se il metodo e' stato fatto dal programmatore stesso, quello finira' per far lanciare al metodo un'unica eccezione personalizzata per tutti i possibili errori in cui il suo metodo puo' incorrere, invece che creare un'eccezione per ciascuno di essi. E questo alla fine equivale a ritornare un booleano di controllo. Insomma la verita' e' che le eccezioni sono una fantastica idea che pero' e' efficacemente applicabile solo nel piccolo (o nella teoria!). Nella pratica, con applicazioni medio-grandi si finisce sempre per usare un unico catch Exception o, se possibile (non in Java), non fare alcun catch se non nel main. E questo non lo sostengo solo io sia chiaro, ma anche Bruce Eckel, i designer del C#... Personalmente mi piacerebbe riuscire a trovare un sistema di programmazione che mi faccia gestire in maniera pulita gli errori, senza costringermi a sporcare il codice con una miriade di catch come fa Java con le checked exception. Ma non l'ho ancora trovato... |
![]() |
![]() |
![]() |
#24 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Non voglio salire in cattedra anche perchè mi fa male un ginocchio ma un conto è un errore, un conto è un'eccezione.
Entrambi sono condizioni che determinano l'impossibilità logica per un blocco di codice di essere eseguito. L'errore è una condizione certa sia nel quando sia nel se. x = 0 y = 10 z = y / x; L'eccezione è "certa an, incerta quandum": sai quando si verifica ma non sai se si verificherà: funzione divide(x, y) = x / y;//eccezione Tutte le eccezioni dovrebbero essere controllate - altrimenti non ha senso averle. E' difficile - ma non impossibile - giustificare la presenza di eccezioni non controllate se non per l'atto pratico di voler evitare il sovrappiù di intercettazioni dovute all'uso di funzioni particolarmente frequenti (ad esempio la dereferenziazione).
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#25 | |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Nel primo caso ci sono forti discussioni sull'utilità delle checked exception (in .NET hanno deciso consciamente di non impiegarle) che diventano oltretutto parte integrante della firma di un metodo e in caso di refactoring sono dolori. Nel secondo caso invece in una manciata di chiamate a metodi del runtime sia esso Java o .NET dovresti mettere tanti di quei catch da diventare scemo. Ogni metodo ti solleva almeno un paio di eccezioni differenti, non è raro trovare metodi che ritornano 6 o più eccezioni. Ma quando li uso, una volta che so che quella chiamata è fallita, quasi mai mi interessa il motivo specifico, in ogni caso non saprei come porvi rimedio, mi sembrano non proprio comuni i casi in cui a seconda del tipo di eccezione si debbano compiere azioni differenti. |
|
![]() |
![]() |
![]() |
#26 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
La prima, vale a dire che mi riferisco all'obbligatorietà della gestione delle eccezioni.
La quantità di catch che uno dovrebbe mettere è irrilevante. Considera che ci sono alcune situazioni in cui Java rilascia eccezioni non controllate che sarebbe stato preferibile gestire in modi diversi. Ad esempio la NullPointerException rilasciata ad ogni dereferenziazione si inquadrebbe bene nel sistema dei tipi (con un'opzione o un supertipo "NotNull"). Non è andata così. Come disse Gosling, a un certo punto dovemmo rilasciare quel che avevamo senza poter appronfondire. Quanto a NET non è un buon esempio di alcunchè.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#27 | ||||||
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
Quote:
![]() Quote:
Quote:
Quote:
Codice:
class A { private: A(const A&) {} A &operator = (const A&) { return *this; } public: A() { if (inizializzazione di A fallisce) { throw false; } } ~A() { cleanup di A; } }; class B { private: B(const B&) {} B &operator = (const B&) { return *this; } public: B() { if (inizializzazione di B fallisce) { throw false; } } ~B() { cleanup di B; } }; class C { private: C(const C&) {} C &operator = (const C&) { return *this; } public: C() { if (inizializzazione di C fallisce) { throw false; } } ~C() { cleanup di C; } }; { A a; B b; C c; esegui operazione che usa a, b e c; } Quote:
Quote:
d'altra parte invece allocare le risorse in un metodo di inizializzazione a parte dal costruttore mi complica il programma perché introduce la possibilitá che l'oggetto si trovi in due stati diversi: inizializzato e non inizializzato. non mi conviene quasi mai. |
||||||
![]() |
![]() |
![]() |
#28 |
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
come no? catch block vuoto e prosegui.
|
![]() |
![]() |
![]() |
#29 |
Senior Member
Iscritto dal: May 2001
Messaggi: 12815
|
Non è obbligatorio gestire le eccezioni, per questo il punto è decidere cosa vuoi che il programma faccia in caso di errore.
Un esempio pratico di un programmino che ho fatto per controllare se un sito web è stato aggiornato (fa una request ogni tot secondi e controlla se la data del sito web è uguale alla precedente). Supponi che io disponga di una form in cui inserire l'URL, ora ho queste possibilità: - Controllare se l'url è ben formato in fase di inserimento, in caso contrario impedire che venga attivata la routine di controllo. - Dare per buono ciò che l'utente inserisce e gestire eventuali eccezioni. Ci sono casi in cui si è obbligati a seguire la seconda strada, ad esempio attivando la routine di controllo non puoi sapere a priori se il DNS troverà un riscontro per l'URL inserito. Cosa succede se il sito web esiste ma la connessione cade? Sapendo che il sito web esiste devo dedurre che si tratta di un problema "momentaneo", quindi potresti scegliere di ritentare tra tot tempo piuttosto che interrompere il programma. In questo caso è chiaro che io da utente preferirei che si occupasse il programma di gestire questa situazione. Non sempre tuttavia è possibile gestire gli errori e la sintassi di alcuni linguaggi non aiuta in questo (non si riesce ad evitare di aggiungere codice "superfluo", anche lì dove non serve). Ultima modifica di WarDuck : 19-03-2010 alle 14:49. |
![]() |
![]() |
![]() |
#30 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
![]() Non è solo in questo caso che sei obbligato a scrivere il costruttore di copia e l'operatore =. Con la tua filosofia oltre al costruttore attivo hai anche il distruttore attivo e di conseguenza con il distruttore attivo sarai obbligato ad implementare anche costruttore di copia e operatore =. Riguardo alla definizione: il costruttore definisce un modo per inizializzare un oggetto (questa a memoria è la definizione di Stroustrup). Quindi in teoria dovremmo metterci dentro solo l'inizializzazione. Implementando il costruttore di default che fa solo l'inizializzazione, potrai anche implementare i costruttori specializzati in modo attivo. Questo perché comunque ci sarà un modo per inizializzare in modo passivo l'oggetto e quindi sarai obbligato a gestire questa possibilità nel distruttore. Secondo me la tua non è una filosofia, ma è proprio un errore concettuale. Ultima modifica di cionci : 19-03-2010 alle 14:59. |
|
![]() |
![]() |
![]() |
#31 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Per questo ho scritto che gestirei con le eccezioni solo situazioni in cui un errore possa far fallire una sequenza di operazioni che mi aspetto che il chiamante faccia oltre alla corrente.
|
![]() |
![]() |
![]() |
#32 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Capisco il senso di errore in quella frase ma va precisato che nel contesto delle eccezioni "eccezione" ed "errore" sono mutualmente esclusivi: sono due tipi diversi di condizioni (che determinano l'impossibilità eccetera eccetera).
L'errore di cui parli è, presumo, un fatto esterno al programma - come può essere lo stato di un server http.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#33 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
L'esempio da cui prendevo l'ispirazione è proprio la connessione ad un DB e l'esecuzione di una query.
|
![]() |
![]() |
![]() |
#34 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Conoscere ciò di cui si parla prima di parlarne è un ottimo modo per evitare di dire stronzate (cit)
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#36 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#37 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Comunque, giusto per aggiungere qualcosa alla discussione, per coloro che intendessero mai scrivere prima o poi dei test per le proprie applicazioni (
![]() uno dei parametri principali per stimare la complessita' di una funzione e quindi la sua difficolta' di copertura e' la complessita' ciclomatica http://it.wikipedia.org/wiki/Comples...A0_ciclomatica Che non ha nulla a che fare con la complessita' computazionale. (le notazioni O(n) e Θ(n)). La complessita' ciclomatica da un'indicazione su quanti branches diversi di codice l'escuzione potrebbe potenzialmente suddividersi, e quindi su quanto e' difficile coprire completamente una funzione con tutti i test necessari per eventualmente scoprire qualche anomalia. Piu' la complessita' ciclomatica e' alta e piu' saranno necessari test per la copertura. Esistono tool di test aid che dichiarano, tra le altre cose, la complessita' ciclomatica di ogni metodo del proprio codice (NCover per C#, JTest ma anche altri per Java). Tali software sono anche molto utili per un altro parametro: la percentuale di copertura dei test che sono stati scritti, le percentuali di copertura per ogni metodo (rimando a wiki per il significato delle diverse percentuali date per ogni pezzo di codice - http://en.wikipedia.org/wiki/Code_Coverage) e la possibilita' di scoprire quali sono le righe di codice eventualmente non ancora coperte dai propri test. Quando si raggiunge 100% non significa comunque purtroppo che il software e' immune da test, proprio a causa della complessita' ciclomatica. Alcuni pezzi di codice devono essere testati appunto piu' volte. Da esperienze dirette, sebbene il significato operativo sia lo stesso, per ridurre la complessita' ciclomatica il precedente pezzo di codice sarebbe meglio scriverlo come segue: Codice:
if (!A) { Errore A Return } if (!B) { Errore B Return } if (!C) { Errore C Return } if(D) { Errore D Return } Ecco un esempio visuale da parte di un collega indiano che spiega l'operazione e anche altri motivi. http://technorati.com/videos/youtube...%3DQGfXoSxBOJQ Se tali condizioni non fossero funzioni, ma solo e semplicemente proprieta' con i loro valori, ovvero se si e' in presenza di puri e semplici controlli iniziali (e FINALI) del valore di alcune proprieta' allo scopo di eseguire o meno il metodo (le guards appunto), si suggerisce l'uso delle direttive di "Design by Contract" Tali direttive sotto C# verranno supportate da un plug-in di VS2010, e saranno semplicemente attributi. I benefici operativi li tralascio (Alcuni errori possono addirittura essere catturati in fase di complilazione, piu' controllo in fase di debug, ...) Il beneficio prinicipale nel Test Driven Developement e' proprio l'abbassamento della complessita' ciclomatica, e quindi il minor numero di test necessari, e quindi il poter dormire piu' tranquillamente quando si modifica un codice e si ha paura di regression bugs altrimenti potenzialmente molto difficili da scoprire. http://en.wikipedia.org/wiki/Regression_testing Qui maggiori info sul Design By Contract, e il concetto di PreConditions (le guards appunto) e PostConditions e alcuni dei vantaggi possibili. http://www.codeproject.com/KB/cs/designbycontract.aspx PS: Ma ste cose, ad ingegneria informatica, le spiegano oggi? Spiegano qualcosa, almeno l'esistenza, dell'Extreme Programming, dell'Agile programming etc.? Oppure sono ancora fermi a spiegare Waterfall, Incremental e soci, che non usa piu' nessuno?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 20-03-2010 alle 08:57. |
![]() |
![]() |
![]() |
#38 | |||
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
Quote:
Quote:
![]() Quote:
![]() |
|||
![]() |
![]() |
![]() |
#39 | |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quote:
Parlando di cose serie e visto che siamo in tema, tempo fa lessi di una società o neozelandese o australiana o che altro (è stato tempo fa e io ho quel tanto di alzheimer...) che aveva sviluppato un software accompagnato dalla prova matematica dell'assenza di bug. Naturalmente essendo una cosa interessante ho perso il link e non trovo la combinazione di parole per ripescarla con un motore di ricerca. Qualcuno l'ha per caso letta e può mettere il link qui?
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
![]() |
![]() |
![]() |
#40 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2774
|
A informatica (non ingegneria) dove vado io sì, nel corso di ingegneria del software (che nel mio indirizzo è obbligatorio, in altri no).
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 09:57.