Newsgroup: it.comp.lang.c++
Titolo: Template si o no? Domande su linked list / divisione in moduli

Ciao a tutti,
	nonostante sia passato al C++ (dal C) da qualche tempo, ci
sono ancora alcune cosette che "non mi ispirano". In particolare
templates e exceptions. Per oggi mi limito alla prima delle due cose :)
Nonostante i templates siano comodissimi, mi piacciono poco per
diverse ragioni:
1) "ufficializzazione" del cut'n'paste. Non capisco bene che
differenza c'e' fra un template e il copiacopia selvaggio. Un template
e' piu' comodo, ma quando si va a stringere e' come riscrivere la
stessa roba in 27 salse diverse. Ma e' davvero buona programmazione?
2) ci sono situazioni incasinate in cui faccio meno fatica a rifarmi
le cose a mano. Esempio classico: oggetti che stanno in parecchie
linked list contemporaneamente. Mi piacerebbe usare un template,
aggiungendo alla mia classe una classe base linked list, ma questo
giochetto lo posso fare solo una volta, visto che non posso avere la
stessa classe come base 10 volte (oddio, in effetti posso...).
Usare diverse linked list che tengono puntatori all'oggetto mi sembra
pericolossissimo, a meno che non decida di "fare le cose per bene" e
tenere neglio oggetti in numero di volte che sono "referenced" da
qualcuno, per evitare di cancellare cose che non dovrei (cosa che mi
aggiunge livelli di indirezione e classi "reference").
Inoltre i template di linked list offrono sempre milioni di metodi che
non mi servono a nulla, ma che contribuiscono al problema qui sotto.
3) tempo di compilazione. Nel programma in cui lavoro ora usavo una
hash table (map della STL) per fare ricerche usando una stringa come
chiave. I tempi di compilazione erano talmente lunghi che alla fine
sono passato a delle linked list e ricerca lineare. I miei insiemi
sono al massimo di 500 elementi, e 1 secondo in piu' di esecuzione
e' un prezzo molto basso da pagare per risparimiare un minuto di
compilazione ogni volta che cambio una virgola.
Restando su questa 3, quale e' il metodo migliore di separare un
programma in moduli? "Anticamente" io usavo moduli piccoli e agili e
un unico header, ma ora con gli include iniziali che possono prendere
un mucchio di tempo i files lunghi mi stanno sempre piu' simpatici.
Il sistema di separare gli include, in modo da non tenere tutte le
dichiarazioni delle classi in un singolo file e quindi poi includere
in ogni file sorgente solo le dichiarazioni delle classi che vengono
utilizzate funziona bene in certi casi, ma non in tutti.
Nel programma con cui giocherello ora le mie classi sono abbastanza
collegate l'una con l'altra, esiste un qualche trucco per ridurre il
numero di include? Mi spiego:
objA contiene un puntatore a objB (e ci chiama metodi sopra).
objB contiene un puntatore a objC (e ci chiama metodi sopra).
objC.....etc.etc.
Esiste un qualche modo per non essere costretto a re-includere tutto
tutte le volte che compilo i metodi di objA?
Ciao,
Alberto
-- 
Alberto BARSELLA
PGP fingerprint = 13 3F 22 D2 0B 0A D3 25  F1 89 FE B5 82 AD 75 2A
** Beliefs are dangerous. Beliefs allow the mind to stop functioning.
A non-functioning mind is clinically dead.  Believe in nothing... **

tutte le volte che compilo i metodi di objA?
In generale, se A dipende da B, B dipende da C, eccetera, puo`
darsi che tu abbia introdotto dipendenze eccessive.  Tuttavia,
non e` detto.  Prendiamo il caso da te citato, ovvero semplificando
(e rovesciando l'ordine alfabetico per comodita`:-) supponiamo che
la struttura sia del tipo:
class A {
public:
    void methodA();
};
void A::methodA() { }
class B {
private:
    A* pA;        // e ovviamente un qualche modo di settarlo:-)
public:
    void methodB();
};
void B::methodB() { pA->methodA(); }
class C {
private:
    B* pB;        // e ovviamente un qualche modo di settarlo:-)
public:
    void methodC();
};
void C::methodC() { pB->methodB(); }
e cosi` via.  Ora, si puo` ottenere questo come segue (ometto
le ovvie guardie contro doppia inclusione, ecc ecc);
:file A.h
class A {
public:
    void methodA();
};
:file A.cpp
#include "A.h"
void A::methodA() { }
:file B.h
class A;    // forward declaration
class B {
private:
    A* pA;        // e ovviamente un qualche modo di settarlo:-)
public:
    void methodB();
};
:file B.cpp
#include "A.h"
#include "B.h"
void B::methodB() { pA->methodA(); }
:file C.h
class B;
class C {
private:
    B* pB;        // e ovviamente un qualche modo di settarlo:-)
public:
    void methodC();
};
:file C.cpp
#include "B.h"
#include "C.h"
void C::methodC() { pB->methodB(); }
e cosi` via.  Cruciale e` notare che persino Z.cpp in questa
sequenza NON include molti header -- solo Z.h (la classe
che esso stesso implementa) e Y.h (l'unica altra classe di 
cui ha bisogno di conoscere i metodi).
Ci sono anche paradigmi specifici per ridurre e tenere sotto
controllo le dipendenze, che Martin spiega molto bene.  Il
principale schema e` la "inversione di dipendenza": dove
"di natura" avremmo che una certa classe A dipende da una
classe B e _non_ vogliamo che cio` avvenga, rendiamo
invece entrambi dipendenti da una terza classe, C, astratta
e percio` piu` stabile -- B eredita da C e la implementa.
In tutti questi casi occorre tipicamente anche essere in grado
di generare opportunamente oggetti di una classe senza
conoscere la classe stessa; a cio` servono le varie pattern
e idiomi di tipo "factory".
Comunque questo poco c'entra coi template, e il post e` gia`
molto lungo, per cui rimandiamo ad altre occasioni...
Alex

 molto lungo, per cui rimandiamo ad altre occasioni...
Non ci sono problemi, sono sempre pronto a leggere e a salvare i
messaggi! :)
Ciao e grazie,
Alberto
PS: fra un po' faccio un'altra sparata su perche non mi piacciono le
eccezioni....


 
Una possibilita' (ma attenzione agli effetti potenzialmente disastrosi sulla
manutenibilita') e' usare una forward declaration quando dichiari soli
*puntatori* ad oggetti - al compilatore non serve la dimensione della classe
(e quindi la sua dichiarazione C) per compilare correttamente.
In C++, COM e' un altro buon modello che, come effetto collaterale, puo'
migliorare i tempi di compilazione - disaccoppiando implementazioni instabili
da interfacce stabili. Non serve tutto - solo l'idea di usare classi astratte
come cuscinetto tra il codice utilizzatore e quello di implementazione.
Saluti,
	Cris
-- 
Cristiano Sadun
Software Engineering & Consulting
email address: cris#sun6$itim$mi$cnr$it 
(for actual address please replace # by @ and $ by .)

eccezioni....
Non contare che io ci risponda, ho la Visual C++ Developers'
Conference a Boston fra una decina di giorni e la preparazione
sta diventando frenetica...:-).
Alex

sull'UML)
Che cosa e' la "notazione Booch" ?
Che cosa e' un "UML" ?
Ciao
---------------------------------------
Email: sostituire "nospam" con "netsis"

Che cosa e' un "UML" ?
Entrambe notazioni, e metodologie, per la progettazione orientata
agli oggetti (OOD, Object Oriented Design).  Booch e` uno dei
principali studiosi del settore e inventore della notazione (e metodo)
che da lui prende nome; UML e` lo Unified Modeling Language, che
Booch ha recentemente sviluppato con gli altri "due grandi", cioe`
Rumbaugh e Jacobson (dopo che la ditta di Booch aveva comprato
quella di Rumbaugh, e Jacobson aveva lasciato la grande azienda
in cui lavorava per entrare nella stessa ditta di Booch).  I tre tizi in
questione sono ora anche noti nella comunita` OOD come "los
tres amigos" (perche` in spagnolo, non lo so proprio!).
Personalmente, penso che UML sia parecchio superiore alla
precedente notazione di Booch, ma naturalmente essendo nuova
parecchi programmi di supporto per l'OOD, specialmente quelli
che si trovano in rete come shareware, ancora non supportano
UML ma solo Booch (o solo Rumbaugh, graficamente piu`
semplice di Booch, e tra l'altro piu` simile alla veste grafica
dell'UML come alla fine concordato fra gli amigos).
Alex

dell'UML come alla fine concordato fra gli amigos).
Se non ho capito male, esistono software che trasformano in codice C++ la
descrizione di un problema effettuata con tali linguaggi (grafici) !


descrizione di un problema effettuata con tali linguaggi (grafici) !
Esatto!!!  "Rational Rose", per esempio.  Inoltre ti fanno anche il
"reverse engineering" -- parti dal C++, Rational Rose te lo analizza,
crea i diagrammi UML (o Booch), puoi editare quelli a livello design
e rigenerare C++ modificato...
NON sono sostituti per un'eccellente conoscenza del C++, attenti!
Solo "acceleratori di produttivita`" (anche di un ordine di grandezza,
per problemi MOLTO grandi -- milioni di righe di codice C++).
Quelli davvero buoni non li regala nessuno (migliaia di dollari,
ragazzi...!).
Alex

 [...]
In effetti i template sono solo escamotage con cui il C++ "tenta" di
implementare uno dei suoi piu' grossi limiti intrinseci che altri
linguaggi ad oggetti (es. Smalltalk ed Eiffel) non hanno, la
genericita' implementata a livello di classi. Ad esempio in Eiffel tu
puoi fare:
class LINKABLE [pippo] feature
	item: pippo
		-- valore associato al singolo elemento
	right: LINKABLE [pippo];
		-- l'elemento concatenato a destra
	left: LINKABLE [pippo];
		-- l'elemento concatenato a sinistra
	add (val: pippo) is
		-- la funzione che aggiunge un elemento
	[...]
eccetera.
Poi ovviamente puoi dichiarare:
emplink: LINKABLE [STRING] o
emplink: LINKABLE [TWO_WAY_LIST]
e via di seguito.
Questo grazie alla potente concezione ad oggetti del linguaggio.
Il fatto che non si possa fare in C++ se non utilizzando escamotage od
estensioni alla sintassi come sono i template ha la sua origine nella
concezione stessa del linguaggio, che e' "funzionalmente" limitata.
Ovviamente questo ha un motivo di essere ed ha anche i suoi pro (es.
in Eiffel ed in Smalltalk almeno per adesso non e' possibile
realizzare il dynamic binding, forse con i soliti "escamotage"
l'Eiffel potra' farlo. La comodita' di una cosa e' ripagata con la
difficolta' in un'altra e viceversa, come sempre).
Saluti

difficolta' in un'altra e viceversa, come sempre).
Cosa intendi in questo contesto per "dynamic binding" -- l'uso di DLL
scelte e caricate nel corso del runtime invece che alla partenza di
una applicazione?  Se si`, non c'e` particolare differenza a livello _di
linguaggio_ fra il supporto fornito da C++, Eiffel, Smalltalk... se sia o
meno possibile e` interamente questione di libreria (in Smalltalk, in
particolare, che e` all'estremo opposto da {C++ e Eiffel}, e punta
*tutto* sul dinamismo, anche a scapito della "type safety", sarebbe
il massimo dell'ironia se il caricamento e binding dinamico di nuove
classi non fosse ben supportato... mi pareva che IBM VisualAge, che
e` un'implementazione di Smalltalk, di simili feature non difettasse, ma
e` tanto che non ci lavoro).
Se c'e` un diffuso interesse ai linguaggi Eiffel e/o Smalltalk, perche` non
vi fate gli opportuni gruppi it.comp.lang.eiffel e it.comp.lang.smalltalk?
Non vi manchera` certo quel centinaio di voti che occorrono...!  Il C++
e` argomento sin troppo ricco e complesso -- anche e soprattutto
perche` qui vengono a finire anche tutta una serie di questioni non
sul linguaggio, ma su varie librerie e framework spesso usate con
esso -- per doversi mettere qui a discettare anche di altri linguaggi
totalmente diversi...
Alex

sul linguaggio, ma su varie librerie e framework spesso usate con
Io non avevo intenzione di parlare di implementazioni, al contrario,
del linguaggio in se'.
In ogni caso, hai completamente ragione e mi scuso... sono stato
troppo polemico, fin dal mio atteggiamento iniziale. Credetemi, non e'
da me voler scatenare "guerre" vecchio stile del genere "il mio e'
meglio del tuo" stile Amiga/Atari ST... Appena ne avro' la
possibilita' procedero' a creare il gruppo di Eiffel.
Saluti

possibilita' procedero' a creare il gruppo di Eiffel.
A cui partecipero` volentieri, tempo permettendo, perche` e` un
linguaggio interessante _nonostante_ le continue polemiche di
Bertrand Meyer e altri adepti:-).
Alex

Bertrand Meyer e altri adepti:-).
Ovviamente io e Meyer abbiamo ragione eh eh
Ma che non lo sapevi che all'epoca io avevo due anni ma gia'
parteggiavo con lui perche' - come lui gia' dai primi anni 80
profetizzava - l'Amiga era meglio? ed infatti hai visto che e' durata
due anni in piu'?
Stai attento, noi della setta siamo anche dei selvaggi, all'ultimo che
ha chiesto l'ottimizzazione per MMX del codice dell'ISE gli e'
arrivata nei denti la costola della seconda edizione di "Object
oriented software contruction" ecc.
OK seppellisco l'ascia di guerra e mi fumo il calumet della pace
(augh) scusate l'intrusione polemica e a quanti vorranno ci risentiamo
tra un po', troveremo il tempo di tirarci addosso i libri dell'ISE (il
mio l'arsenale bellico e' decisamente da guerra fredda).
Saluti