[PHP] Guestbook

Stato
Discussione chiusa ad ulteriori risposte.
sydarex ha detto:
Appunto, rendere un membro private limita il riutilizzo del codice, in quanto l'utilizzatore è limitato nell'utilizzo; private limita l'utilizzo della classe per i task per cui è stata pensata.
Non penso proprio. Allora mettiamola così, io creo un attributo privato, anzi no pubblico, però è una variabile che ha senso solo ed esclusivamente all'interno del contesto della classe, cioè all'esterno perde totalmente significato.. immagina l'handle di un processo o di un thread parallelo. Io adesso ho questo attributo pubblico, lo posso modificare dall'esterno e invece dell'handle che dovrebbe avere ne metto un altro. Quale beneficio mi porta aver dichiarato pubblico quell'attributo?

sydarex ha detto:
Non ho capito. Se ciò che volevi scrivere è una domanda, allora:
- Tu se codi una classe e vuoi mantenere un attributo privato (intendo: per uso interno), realizzi le set/get?
- Ha senso utilizzare set/get invece che modificare direttamente i membri? A che pro, incapsulamento? Mi pare un ragionamento fallace, una cosa che si fa per abitudine, ma ti sarei grato se ti spiegassi meglio.
Si, è per il secondo motivo. Ti faccio un ulteriore esempio. Io creo una classe con degli attributi, alcuni attributi (che ne so, variabili intere) devono rimanere all'interno di un range per essere 'sensate' (vedi i mesi di un anno 1-12). Ora, io posso rendere l'attributo pubblico, ma, dall'esterno, chi lo modifica potrebbe mettere qualsiasi valore all'interno dell'attributo stesso. Ora, possiamo fare un controllo d'integrità ogni volta che dobbiamo manovrare con tale attributo, oppure eliminare il problema alla radice. Fornire un metodo get che restituisce il valore dell'attributo, e un metodo set che invece lo setta, solo ed esclusivamente se il valore passato è coerente con quello che deve contenere.

sydarex ha detto:
Ma è proprio l'utilità dell'incapsulamento che critico, e che è FUORI dalla definizione teorica originaria della programmazione orintata agli oggetti.
Quanto a protected, ancora, non ne vedo l'utilità ancora più che di private, visto che mi basta fare una classe wrapper per aggirarla.
Non è meglio usare una convenzione per i metodi privati (come l'underscore iniziale, o ancora addirittura il name mangling se proprio si vuole), visto che:
- Private limita l'uso, il riuso e l'estendibilità della classe
- Protected è aggirabile
Quindi:
- Se questa filosofia di OOP è per ARRESTARE l'uso libero del codice, allora fallisce perché aggirabile;
- Se questa filosofia di OOP è per EVITARE GLI ERRORI PERMETTENDO L'USO LIBERO CONSAPEVOLE, allora fallisce perché va aggirata artificiosamente.
In entrambi i casi fallisce.
Private non limita niente, ti ho già detto come fare per poter ovviare al problema, incapsulamento, protected, e, anzi, ne aggiungo un altro, classi friend. Ora, se io invece volessi proprio che una classe non possa ereditare un bel niente ma solo quello che gli dico io? Cosa dovrei fare? Visto che tu dici che il private non dovrebbe essere usato e nemmeno il protected.

Non capisco cosa intendi quando dici che protected è aggirabile, è nato proprio per dare la possibilità di accesso ai membri della classe da una classe derivata.
 
stoner ha detto:
Non penso proprio. Allora mettiamola così, io creo un attributo privato, anzi no pubblico, però è una variabile che ha senso solo ed esclusivamente all'interno del contesto della classe, cioè all'esterno perde totalmente significato.. immagina l'handle di un processo o di un thread parallelo. Io adesso ho questo attributo pubblico, lo posso modificare dall'esterno e invece dell'handle che dovrebbe avere ne metto un'altro. Quale beneficio mi porta aver dichiarato pubblico quell'attributo?
Supponi che io voglia usare quella classe in un modo a cui tu, programmatore, non hai pensato.
Allacciandomi al tuo esempio, a me serve l'handle di quel processo, cosa che tu non hai previsto.
L'utilità sta nel fatto che me lo prendo accedendo all'attributo, invcece che incasinandomi con i puntatori o modificando il file header.
stoner ha detto:
Si, è per il secondo motivo. Ti faccio un ulteriore esempio. Io creo una classe con degli attributi, alcuni attributi (che ne so, variabili intere) devono rimanere all'interno di un range per essere 'sensate' (vedi i mesi di un anno 0-12). Ora, io posso rendere l'attributo pubblico, ma, dall'esterno, chi lo modifica potrebbe mettere qualsiasi valore all'interno dell'attributo stesso. Ora, possiamo fare un controllo d'integrità ogni volta che dobbiamo manovrare con tale attributo, oppure eliminare il problema alla radice. Fornire un metodo get che restituisce il valore dell'attributo, e un metodo set che invece lo setta, solo ed esclusivamente se il valore passato è coerente con quello che deve contenere.
Sei arrivato al punto: il C++ inculca questa mentalità, il non fidarsi dell'utente.
E' giusto realizzare un metodo che modifichi *solo se nel range*, ma nel caso vada inserito da input; cioè, è il programmatore a decidere quando usarlo e quando accedere direttamente. Non ha senso pretendere che il programmatore, che ha letto la tua documentazione e SA che il valore deve essere nel range, usi la get, aggiungendo overhead al programma quando basterebbe dargli la libreria e avvertirlo che non dovrebbe farlo.
Cioè, non "non puoi", bensì "puoi, ma non dovresti se non sei sicuro".
stoner ha detto:
Private non limita niente, ti ho già detto come fare per poter ovviare al problema, incapsulamento, protected, e, anzi, ne aggiungo un altro, classi friend.
Come non limita? Mi impedisce l'accesso diretto a un membro della classe. Che poi tu preveda una set e una get è un altro discorso.
stoner ha detto:
Ora, se io invece volessi proprio che una classe non possa ereditare un bel niente ma solo quello che gli dico io? Cosa dovrei fare? Visto che tu dici che il private non dovrebbe essere usato e nemmeno il protected.
In tal caso usi private; ma facendolo sai che comunque l'utente può aggirarlo, perciò è inutile.
Meglio un approccio basato su convenzioni, come quello di Python o Lisp: un attributo il cui nome inizia per underscore è privato. Non per questo non posso accedervi se ne ho necessità, si tratta di convenzione.
stoner ha detto:
Non capisco cosa intendi quando dici che protected è aggirabile, è nato proprio per dare la possibilità di accesso ai membri della classe da una classe derivata.
Si; ma se creo una classe wrapper, cioè uguale in tutto e per tutto a quella originale tranne per il fatto che consente l'accesso un attributo protected, è null'altro che un aggiramento di protected, che potevo semplicemente evitare se protected/private non esistessero affatto.
 
sydarex ha detto:
Supponi che io voglia usare quella classe in un modo a cui tu, programmatore, non hai pensato.
Allacciandomi al tuo esempio, a me serve l'handle di quel processo, cosa che tu non hai previsto.
L'utilità sta nel fatto che me lo prendo accedendo all'attributo, invcece che incasinandomi con i puntatori o modificando il file header.
Ancora con i puntatori? Se voglio che l'handle sia visibile all'esterno metto un metodo get ma non fornisco un metodo set. Così posso VEDERLO ma non posso MODIFICARLO.

sydarex ha detto:
Sei arrivato al punto: il C++ inculca questa mentalità, il non fidarsi dell'utente.
L'esperienza mi insegna che il 99,99% dei problemi è proprio dovuto all'utente.

sydarex ha detto:
E' giusto realizzare un metodo che modifichi *solo se nel range*, ma nel caso vada inserito da input; cioè, è il programmatore a decidere quando usarlo e quando accedere direttamente. Non ha senso pretendere che il programmatore, che ha letto la tua documentazione e SA che il valore deve essere nel range, usi la get, aggiungendo overhead al programma quando basterebbe dargli la libreria e avvertirlo che non dovrebbe farlo.
Cioè, non "non puoi", bensì "puoi, ma non dovresti se non sei sicuro".

Si, ma così è inconsistente. Io definisco l'attributo pubblico, tu lo modifchi come ti pare, dentro ai membri che accedono a tale attributo faccio il controllo di integrità, cosa ci ho gudagnato? Ho spostato un controllo dalla funzione set a tutte le funzioni membro che accedono a quell'attributo, così se domani decido che i mesi vanno da 3 a 11 devo modificarmi tutto il resto, invece che un'unica funzione.

sydarex ha detto:
Come non limita? Mi impedisce l'accesso diretto a un membro della classe. Che poi tu preveda una set e una get è un altro discorso.
Sono io che scrivo la classe, e sono io a decidere se devi o non devi accedere ad un menbro, e sono sempre io che definisco le modalità di accesso. Il motivo è semplice, preservare l'integrità dei dati. E poi i motivi te li ho elencati 200 volte sopra, rileggiteli se te li sei scordati.

sydarex ha detto:
In tal caso usi private; ma facendolo sai che comunque l'utente può aggirarlo, perciò è inutile.
Allora che è tutto questo macello sul private? Tu dici che se vuoi puoi modificarlo, allora io ti do la classe come l'ho pensata io e come credo che sia giusto che debba essere implementata, poi se tu vuoi modificarla sei libero di farci quello che vuoi.
 
quando si scontrano due filosofie di programmazione c'è poco da fare... entrambi i contendenti avranno sempre qualcosa da ribattere fino a quando nn si arriva alla rindondanza.

Per quello che importa concordo con sydarex io, abituato al python in cui col doppio underscore, per accedere a tale attributo era necessario scrivere, nelle classi derivate _classeMadre.__varibile (almeno, così nel 2.5.2) ritengo che questo sia il modo migliore: io ti dico che per quello che ho previsto questa variabile deve non essere modificata direttamente, se tu poi scrivi quel papiro per accedervi, la modifichi e per questo motivo crasha: "cazzi tuoi". Poi nulla vieta di usare get e set per semplificare, io amo il metodo property per questo..
 
Scaricati qualsiasi framework o libreria in un qualsiasi linguaggio OOP completo e vedrai che nessun programmatore specifica tutto a public. Non devi neanche andare tanto lontano, sfoglia i sorgenti della libreria uSock di BlackLight o la libreria xmlpp di meh. Se non sei contento vai su SourceForge o CodeProject e cerca.

Magari sono anni che stiamo sbagliando tutti, grazie per averci illuminato :D
 
Dark-Snake1992 ha detto:
quindi? alla fine chi è quello che ce l'ha più lungo?
C'é chi ama discutere, oltre che fare help desk a voi.
stoner ha detto:
Ancora con i puntatori? Se voglio che l'handle sia visibile all'esterno metto un metodo get ma non fornisco un metodo set. Così posso VEDERLO ma non posso MODIFICARLO.
stoner, non stai afferrando ciò che dico. Non sto dicendo che così NON E' POSSIBILE CREARE BUONE LIBRERIE, ma che è un modo di fare ridondante, una filosofia che parte da basi errate. Se non prevedi sto metodo get, io non posso accedervi in modo canonico. Ritengo sia una filosofia sbagliata; non è che ti ho chiesto di listare i modi per fare buoni programmi lo stesso. =)
stoner ha detto:
L'esperienza mi insegna che il 99,99% dei problemi è proprio dovuto all'utente.
Quindi il C++, si potrebbe dire, è un linguaggio da baby sitters. :asd:
E' questo ciò su cui non concordo. Il limitare l'utente per salvarlo dai suoi stessi errori; certo, forse è più difficile sbagliare se si usa private, perché l'uso "scorretto" (anche quando non lo sarebbe) genera errori a compile-time, ma l'uso di convenzioni rigide porta allo stesso risultato senza limitare l'utente consapevole.
stoner ha detto:
Si, ma così è inconsistente. Io definisco l'attributo pubblico, tu lo modifchi come ti pare, dentro ai membri che accedono a tale attributo faccio il controllo di integrità, cosa ci ho gudagnato? Ho spostato un controllo dalla funzione set a tutte le funzioni membro che accedono a quell'attributo, così se domani decido che i mesi vanno da 3 a 11 devo modificarmi tutto il resto, invece che un'unica funzione.
No, tu stai facendo il percorso logico che fa un programmatore che segue quella filosofia.
Lascia che ti spieghi in modo più approfondito la diversa filosofia di cui parlo.

Supponiamo di avere, in pseudocodice, una classe come quella di cui parli; in stile OOP del C++ faremmo:
Codice:
class Month {
	private int month;
	
	bool setMonth (int newmonth) {
		if(1<=newmonth<=12) { // Se rientra nel range setta e ritorna true
			this->month = newmonth;
			return true;
		}
		return false; // Altrimenti torna false.
	}
	
	int getMonth() {
		return this->month;
	}
}
Che succede? Che comunque vada, anche se devo settare month con dei literal che sono sicuro saranno validi, devo usare la set. Che se voglio fare delle test unit con dati errati, devo modificare la classe, altrimenti si fermerà alla set e non potrò vedere come si comporta il codice successivo (lascia perdere il controllo d'integrità che assicura la bontà dei dati); insomma, sono limitato, e in caso di classi più complesse potrei essere impossibilitato a fare un uso particolare o insolito, ma non errato, della classe. In più, non ho modo di evitare l'overhead delle chiamate a metodi, neanche per una semplice printf.

Invece usando uno stile basato sulle convenzioni:
Codice:
class Month {
	int __month; // Il doppio underscore significa che è a uso interno e non andrebbe manipolato direttamente.
	
	bool setMonth (int newmonth) {
		if(1<=newmonth<=12) { // Se rientra nel range setta e ritorna true
			this->month = newmonth;
			return true;
		}
		return false; // Altrimenti torna false.
	}
}
Uso setMonth quando ho necessità di fare il controllo di integrità. E se voglio realizzare test, usare literal evitando l'overhead del test d'integrità, lo faccio con facilità.

Un'altra cosa che sfugge ad un programmatore non abituato all'uso di questi linguaggi, è che le convenzioni sono molto più sentite che in altri linguaggi. Non è come la notazione ungara che non la conosce nessuno, per esempio. TUTTI i programmatori Python sanno che _attributo indica che attributo è a uso interno, è privato. E' scritto nel manuale, è un concetto allo stesso livello del for.
stoner ha detto:
Sono io che scrivo la classe, e sono io a decidere se devi o non devi accedere ad un menbro, e sono sempre io che definisco le modalità di accesso. Il motivo è semplice, preservare l'integrità dei dati. E poi i motivi te li ho elencati 200 volte sopra, rileggiteli se te li sei scordati.
A scapito della flessibilità. Non è che non concordo con il preservare l'integrità, è che non concordo sull'imporlo anche quando non è necessario.
stoner ha detto:
Allora che è tutto questo macello sul private? Tu dici che se vuoi puoi modificarlo, allora io ti do la classe come l'ho pensata io e come credo che sia giusto che debba essere implementata, poi se tu vuoi modificarla sei libero di farci quello che vuoi.
Filosofia di programmazione.
stoner ha detto:
Scaricati qualsiasi framework o libreria in un qualsiasi linguaggio OOP completo e vedrai che nessun programmatore specifica tutto a public. Non devi neanche andare tanto lontano, sfoglia i sorgenti della libreria uSock di BlackLight o la libreria xmlpp di meh. Se non sei contento vai su SourceForge o CodeProject e cerca.
Certo, nei linguaggi che prevedono l'incapsulamento di quel tipo lo usi, giustamente. Non era questo che mettevo in discussione, facevo un discorso astratto.
stoner ha detto:
Magari sono anni che stiamo sbagliando tutti, grazie per averci illuminato :D
In effetti, questo modo di effettuare l'incapsulamento è al centro di una polemica che va avanti dagli anni 70. =)
 
sydarex ha detto:
stoner, non stai afferrando ciò che dico. Non sto dicendo che così NON E' POSSIBILE CREARE BUONE LIBRERIE, ma che è un modo di fare ridondante, una filosofia che parte da basi errate. Se non prevedi sto metodo get, io non posso accedervi in modo canonico. Ritengo sia una filosofia sbagliata; non è che ti ho chiesto di listare i modi per fare buoni programmi lo stesso. =)

E qui parla di mala programmazione, se programmo male la classe è un problema di chi la programma non del fatto che abbia optato per quel tipo di 'filosofia' (come la chiami tu). E poi potrebbe anche esserci un membro della classe che viene usata come 'variabile d'appoggio' e non deve essere per forza visibile all'esterno della classe.

sydarex ha detto:
Quindi il C++, si potrebbe dire, è un linguaggio da baby sitters. :asd:
E' questo ciò su cui non concordo. Il limitare l'utente per salvarlo dai suoi stessi errori; certo, forse è più difficile sbagliare se si usa private, perché l'uso "scorretto" (anche quando non lo sarebbe) genera errori a compile-time, ma l'uso di convenzioni rigide porta allo stesso risultato senza limitare l'utente consapevole.

In quel caso parlavo di utente che utilizza il programma. E comunque non è mai colpa del linguaggio ma di chi ci programma.

Se il valore che passo lo prendo dall'esterno, dallo stream di input, come faccio a sapere che quello che mi arriva è giusto? Meglio fare un controllo esterno? O uno interno alle classe? E se il programmatore si dimentica di fare il controllo esterno (accedendo diretto al membro)? Magari non si è letto tutta la documentazione?
In ogni modo, è meglio prevedere una classe robusta che sia in grado di lavorare correttamente anche quando il programmatore la usa in modo 'non cristiano' che non farlo per niente lasciandolo in balia di se stesso.

sydarex ha detto:
No, tu stai facendo il percorso logico che fa un programmatore che segue quella filosofia.
Lascia che ti spieghi in modo più approfondito la diversa filosofia di cui parlo.

Supponiamo di avere, in pseudocodice, una classe come quella di cui parli; in stile OOP del C++ faremmo:
Codice:
class Month {
	private int month;
	
	bool setMonth (int newmonth) {
		if(1<=newmonth<=12) { // Se rientra nel range setta e ritorna true
			this->month = newmonth;
			return true;
		}
		return false; // Altrimenti torna false.
	}
	
	int getMonth() {
		return this->month;
	}
}
Che succede? Che comunque vada, anche se devo settare month con dei literal che sono sicuro saranno validi, devo usare la set. Che se voglio fare delle test unit con dati errati, devo modificare la classe, altrimenti si fermerà alla set e non potrò vedere come si comporta il codice successivo (lascia perdere il controllo d'integrità che assicura la bontà dei dati); insomma, sono limitato, e in caso di classi più complesse potrei essere impossibilitato a fare un uso particolare o insolito, ma non errato, della classe. In più, non ho modo di evitare l'overhead delle chiamate a metodi, neanche per una semplice printf.
[Tralasciamo la sintassi errata della classe, tanto ho capito cosa intendi dire]

Per fortuna mi risulta che non ci siano ancora esemplari dell'ENIAC in giro, quindi i programmi girano su computer realtivamente potenti. Invece di concentrarti sui problemi di overhead dovuto al richiamo di una funzione membro, mi concentrei sull'algoritmo risolutivo (che nella maggior parte dei casi è la causa della lentezza del programma, e dello sperpero delle risorse).

Per quanto riguarda il test, sei sicuro che i dati sono corretti perchè l'unico modo per accedere all'attributo è dato dalla funzione set.

sydarex ha detto:
Invece usando uno stile basato sulle convenzioni:
Codice:
class Month {
	int __month; // Il doppio underscore significa che è a uso interno e non andrebbe manipolato direttamente.
	
	bool setMonth (int newmonth) {
		if(1<=newmonth<=12) { // Se rientra nel range setta e ritorna true
			this->month = newmonth;
			return true;
		}
		return false; // Altrimenti torna false.
	}
}
Uso setMonth quando ho necessità di fare il controllo di integrità. E se voglio realizzare test, usare literal evitando l'overhead del test d'integrità, lo faccio con facilità.

Un'altra cosa che sfugge ad un programmatore non abituato all'uso di questi linguaggi, è che le convenzioni sono molto più sentite che in altri linguaggi. Non è come la notazione ungara che non la conosce nessuno, per esempio. TUTTI i programmatori Python sanno che _attributo indica che attributo è a uso interno, è privato. E' scritto nel manuale, è un concetto allo stesso livello del for.

Si ma chi ti dice che non venga usato l'accesso diretto all'attributo invece della funzione setMonth? In quel caso tu dovresti fare tutti i controlli anche dentro alle funzioni che accedono direttamente all'attributo __month per verificare l'integrità. Nel modo precedente invece sai già che è giusto il valore che hai perchè l'attributo è stato settato grazie alla funzione setMonth.

sydarex ha detto:
A scapito della flessibilità. Non è che non concordo con il preservare l'integrità, è che non concordo sull'imporlo anche quando non è necessario.

Nessuno impone un'incapsulamento di quel tipo anche quando non necessario. Se ho un attributo di tipo string che PUO' contenere qualsiasi carattere ASCII allora lo posso anche lasciare pubblico perchè so che l'accesso a quel membro dall'esterno non mi causerà danni all'interno della classe. Di contro, se devo prevedere un attributo di tipo string che ha come range di valori a - z, preferisco fare due membri get/set per evitare problemi di consistenza dei dati.

sydarex ha detto:
Certo, nei linguaggi che prevedono l'incapsulamento di quel tipo lo usi, giustamente. Non era questo che mettevo in discussione, facevo un discorso astratto.
Il C++ permette di incapsularti i dati come ti pare, se gli autori delle librerie sopra citate avessero voluto fare come hai detto l'avrebbero fatto, il fatto che non lo hanno fatto implica che i benefici che porterebbe una cosa del genere sarebbero minori rispetto ai danni.

sydarex ha detto:
In effetti, questo modo di effettuare l'incapsulamento è al centro di una polemica che va avanti dagli anni 70. =)

E il fatto che a 39 anni di distanza si continua ad usare il modo che ti ho descritto io (tranne che in pochi altri linguaggi) implica che il metodo non è così malvagio.
 
Mah, stoner, inutile che continuiamo a risponderci senza capirci; sto ripetendo le stesse cose da post su post e non si va avanti.
Il mio pensiero dovresti averlo capito: ritengo che per garantire la robustezza della classe non serva limitare l'utente ma dargli gli strumenti per utilizzarla al meglio, senza però limitarlo.

Solo:
stoner ha detto:
E il fatto che a 39 anni di distanza si continua ad usare il modo che ti ho descritto io (tranne che in pochi altri linguaggi) implica che il metodo non è così malvagio.
No, implica soltanto che ai tempi non c'era di meglio come linguaggio general purpose, e che non è che ci fosse tutta sta cultura in fatto di OOP.
 
stoner ha detto:
sydarex ha detto:
stoner, non stai afferrando ciò che dico. Non sto dicendo che così NON E' POSSIBILE CREARE BUONE LIBRERIE, ma che è un modo di fare ridondante, una filosofia che parte da basi errate. Se non prevedi sto metodo get, io non posso accedervi in modo canonico. Ritengo sia una filosofia sbagliata; non è che ti ho chiesto di listare i modi per fare buoni programmi lo stesso. =)

E qui parla di mala programmazione, se programmo male la classe è un problema di chi la programma non del fatto che abbia optato per quel tipo di 'filosofia' (come la chiami tu). E poi potrebbe anche esserci un membro della classe che viene usata come 'variabile d'appoggio' e non deve essere per forza visibile all'esterno della classe.

sydarex ha detto:
Quindi il C++, si potrebbe dire, è un linguaggio da baby sitters. :asd:
E' questo ciò su cui non concordo. Il limitare l'utente per salvarlo dai suoi stessi errori; certo, forse è più difficile sbagliare se si usa private, perché l'uso "scorretto" (anche quando non lo sarebbe) genera errori a compile-time, ma l'uso di convenzioni rigide porta allo stesso risultato senza limitare l'utente consapevole.

In quel caso parlavo di utente che utilizza il programma. E comunque non è mai colpa del linguaggio ma di chi ci programma.

Se il valore che passo lo prendo dall'esterno, dallo stream di input, come faccio a sapere che quello che mi arriva è giusto? Meglio fare un controllo esterno? O uno interno alle classe? E se il programmatore si dimentica di fare il controllo esterno (accedendo diretto al membro)? Magari non si è letto tutta la documentazione?
In ogni modo, è meglio prevedere una classe robusta che sia in grado di lavorare correttamente anche quando il programmatore la usa in modo 'non cristiano' che non farlo per niente lasciandolo in balia di se stesso.

sydarex ha detto:
Invece usando uno stile basato sulle convenzioni:
Codice:
class Month {
	int __month; // Il doppio underscore significa che è a uso interno e non andrebbe manipolato direttamente.
	
	bool setMonth (int newmonth) {
		if(1<=newmonth<=12) { // Se rientra nel range setta e ritorna true
			this->month = newmonth;
			return true;
		}
		return false; // Altrimenti torna false.
	}
}
Uso setMonth quando ho necessità di fare il controllo di integrità. E se voglio realizzare test, usare literal evitando l'overhead del test d'integrità, lo faccio con facilità.

Un'altra cosa che sfugge ad un programmatore non abituato all'uso di questi linguaggi, è che le convenzioni sono molto più sentite che in altri linguaggi. Non è come la notazione ungara che non la conosce nessuno, per esempio. TUTTI i programmatori Python sanno che _attributo indica che attributo è a uso interno, è privato. E' scritto nel manuale, è un concetto allo stesso livello del for.

Si ma chi ti dice che non venga usato l'accesso diretto all'attributo invece della funzione setMonth? In quel caso tu dovresti fare tutti i controlli anche dentro alle funzioni che accedono direttamente all'attributo __month per verificare l'integrità. Nel modo precedente invece sai già che è giusto il valore che hai perchè l'attributo è stato settato grazie alla funzione setMonth.

e qui torniamo sul discorso: se un programmatore sta usando la tua libreria ma non rispetta la tua documentazione, è evidente che nn è un buon programmatore, e nn dovrebbe relativamente importare se ne fanno un uso errato.
Inoltre, come detto, se lo fanno volontariamente, possono farlo anche con private/protected, se lo fanno involontariamente.. nn lo faranno involontariamente: per accedere direttamente all'attributo in questione, dovranno pur scrivere il nome dell'attributo con i relativi underscore? vedendo tali underscore, capiscono che è privato, dunque guardano la documentazione, e scoprono il set.
Ma se loro deriderano, consci di come è strutturata la classe, modificare direttamente la variabile, fregandosene degli eventuali controlli posti all'interno del set, allo scopo di una diversa implementazione, vuol dire che nn sono programmatori così novizi da dover essere protetti, ma possono autonomamente notare quali siano i problemi che possono incorrere in un'assegnamento errato.
stoner ha detto:
E il fatto che a 39 anni di distanza si continua ad usare il modo che ti ho descritto io (tranne che in pochi altri linguaggi) implica che il metodo non è così malvagio.

beh, forse il fatto che il 90% dei linguaggi esistenti una una sintassi C-style ed ahnno mutuato la probrammazione ad oggetti da esso con relativamente poche modifiche è sintomo di qualcosa: pensa un attimo: tutti i linguaggi + moderni (ad eccezzione del C# per ovvi motivi di derivazione) non presentano strutture per private, se non convenzioni come quelle del Python.
 
sydarex ha detto:
Mah, stoner, inutile che continuiamo a risponderci senza capirci; sto ripetendo le stesse cose da post su post e non si va avanti.
Il mio pensiero dovresti averlo capito: ritengo che per garantire la robustezza della classe non serva limitare l'utente ma dargli gli strumenti per utilizzarla al meglio, senza però limitarlo.

Appunto, ti ho mostrato che si può fare tutto quello che vuoi semplicemente attuando un buon incapsulamento e non dare tutti i privilegi a chi userà la classe.

sydarex ha detto:
No, implica soltanto che ai tempi non c'era di meglio come linguaggio general purpose, e che non è che ci fosse tutta sta cultura in fatto di OOP.

Ovvio, nel 70 era ancora un concetto puramente teorico implementato in pochi linguaggi di programmazione. Come ben saprai, e so che lo sai, la diffusione è avvenuta successivamente, tra la metà degli anni 80 e l'inizio degli anni 90.

Malex ha detto:
e qui torniamo sul discorso: se un programmatore sta usando la tua libreria ma non rispetta la tua documentazione, è evidente che nn è un buon programmatore, e nn dovrebbe relativamente importare se ne fanno un uso errato.
Inoltre, come detto, se lo fanno volontariamente, possono farlo anche con private/protected, se lo fanno involontariamente.. nn lo faranno involontariamente: per accedere direttamente all'attributo in questione, dovranno pur scrivere il nome dell'attributo con i relativi underscore? vedendo tali underscore, capiscono che è privato, dunque guardano la documentazione, e scoprono il set.
Ma se loro deriderano, consci di come è strutturata la classe, modificare direttamente la variabile, fregandosene degli eventuali controlli posti all'interno del set, allo scopo di una diversa implementazione, vuol dire che nn sono programmatori così novizi da dover essere protetti, ma possono autonomamente notare quali siano i problemi che possono incorrere in un'assegnamento errato.

Ok, un giorno mi spiegherai come mai il 99% dei programmatori non fa come dici tu, ma come dico io. Forse siamo tutti cattivi programmatori, si vede che dovrò imparare da voi (ma sono in buona compagnia a quanto pare).

Malex ha detto:
beh, forse il fatto che il 90% dei linguaggi esistenti una una sintassi C-style ed ahnno mutuato la probrammazione ad oggetti da esso con relativamente poche modifiche è sintomo di qualcosa: pensa un attimo: tutti i linguaggi + moderni (ad eccezzione del C# per ovvi motivi di derivazione) non presentano strutture per private, se non convenzioni come quelle del Python.

Ma non è assolutamente vero, non sparare minchiate. Ogni linguaggio ha una sua storia e costruire un nuovo linguaggio non vuol dire per forza adottare tutti gli schemi del linguaggio dal quale si prende la sintassi.
Vuoi un esempio? In Java non esistono i puntatori e non esiste l'ereditarietà multipla, cose che in C++ ci sono, stessa cosa vale per il C# (il C# è molto più simile al Java di quanto non lo sia al C++, ed inoltre la frase 'per ovvi motivi di derivazione' è del tutto fuori luogo in quel contesto, per il semplice fatto che il C# non deriva dal C++, anche se in un contesto unsafe è possibile usare i puntatori nel C#).. e tante altre differenze.
La stessa cosa vale per il PHP, gli oggetti in php4 (se così vogliamo definirli) prevedevano l'adozione di una classe senza specificatori d'accesso, ovvero tutto era public. Ora, come mai in php5 hanno aggiunto gli specificatori d'accesso (insieme ad altre cose)?? Se era così sconventiente per quale ragione l'avrebbero fatto? Gli oggetti in php esistono da relativamente poco, quindi seguendo il tuo filo logico avrebbero dovuto adottare una soluzione simile al Python eppure non l'hanno fatto. Un motivo ci sarà..
Inoltre esistono linguaggi che non hanno niente da spartire con il C++ che utilizzano sempre gli specificatori d'accesso (visto che dici che gli specificatori d'accesso sono stati inseriti soltanto per il fatto che siano stati ereditati dal C++), esempi lampanti sono Delphi e Visual Basic.
 
stoner ha detto:
Appunto, ti ho mostrato che si può fare tutto quello che vuoi semplicemente attuando un buon incapsulamento e non dare tutti i privilegi a chi userà la classe.
stoner, non ho mai detto il contrario.
stoner ha detto:
Ovvio, nel 70 era ancora un concetto puramente teorico implementato in pochi linguaggi di programmazione. Come ben saprai, e so che lo sai, la diffusione è avvenuta successivamente, tra la metà degli anni 80 e l'inizio degli anni 90.
Per l'appunto, principalmente con C++, che ha portato questa filosofia, a torto o a ragione, come standard de facto.
stoner ha detto:
Ok, un giorno mi spiegherai come mai il 99% dei programmatori non fa come dici tu, ma come dico io. Forse siamo tutti cattivi programmatori, si vede che dovrò imparare da voi (ma sono in buona compagnia a quanto pare).
stoner, scherzi a parte, ma i miei messaggi li leggi? Ho detto e ribadito:
sydarex ha detto:
... nei linguaggi che prevedono l'incapsulamento di quel tipo lo usi, giustamente. Non era questo che mettevo in discussione, facevo un discorso astratto.
Cioè, in C++ si fa così, punto.
stoner ha detto:
Ma non è assolutamente vero, non sparare minchiate. Ogni linguaggio ha una sua storia e costruire un nuovo linguaggio non vuol dire per forza adottare tutti gli schemi del linguaggio dal quale si prende la sintassi.
Vuoi un esempio? In Java non esistono i puntatori e non esiste l'ereditarietà multipla, cose che in C++ ci sono, stessa cosa vale per il C# (il C# è molto più simile al Java di quanto non lo sia al C++, ed inoltre la frase 'per ovvi motivi di derivazione' è del tutto fuori luogo in quel contesto, per il semplice fatto che il C# non deriva dal C++, anche se in un contesto unsafe è possibile usare i puntatori nel C#).. e tante altre differenze.
La stessa cosa vale per il PHP, gli oggetti in php4 (se così vogliamo definirli) prevedevano l'adozione di una classe senza specificatori d'accesso, ovvero tutto era public. Ora, come mai in php5 hanno aggiunto gli specificatori d'accesso (insieme ad altre cose)?? Se era così sconventiente per quale ragione l'avrebbero fatto? Gli oggetti in php esistono da relativamente poco, quindi seguendo il tuo filo logico avrebbero dovuto adottare una soluzione simile al Python eppure non l'hanno fatto. Un motivo ci sarà..
Inoltre esistono linguaggi che non hanno niente da spartire con il C++ che utilizzano sempre gli specificatori d'accesso (visto che dici che gli specificatori d'accesso sono stati inseriti soltanto per il fatto che siano stati ereditati dal C++), esempi lampanti sono Delphi e Visual Basic.
Vedi la risposta al secondo quote: ormai è lo standard de facto, per colpa di C++; ciò non significa che sia l'approccio migliore.
 
sydarex ha detto:
Per l'appunto, principalmente con C++, che ha portato questa filosofia, a torto o a ragione, come standard de facto.
...
stoner, scherzi a parte, ma i miei messaggi li leggi? Ho detto e ribadito:
sydarex ha detto:
... nei linguaggi che prevedono l'incapsulamento di quel tipo lo usi, giustamente. Non era questo che mettevo in discussione, facevo un discorso astratto.
Cioè, in C++ si fa così, punto.

Mi viene il dubbio che sei tu che non leggi i miei. Ti ho appena detto qualche messaggio addietro che il C++ mette a disposizione degli strumenti che i programmatori decidono di utilizzare, volendo, come ti ho anche scritto, si può semplicemente mettere tutto a public, il C++ non obbliga il programmatore ad utilizzare per forza quel tipo di incapsulamento, ma è discrezione del programmatore attuare quello che ritiene opportuno.


sydarex ha detto:
Vedi la risposta al secondo quote: ormai è lo standard de facto, per colpa di C++; ciò non significa che sia l'approccio migliore.

Vedi sopra.
 
stoner ha detto:
Mi viene il dubbio che sei tu che non leggi i miei. Ti ho appena detto qualche messaggio addietro che il C++ mette a disposizione degli strumenti che i programmatori decidono di utilizzare, volendo, come ti ho anche scritto, si può semplicemente mettere tutto a public, il C++ non obbliga il programmatore ad utilizzare per forza quel tipo di incapsulamento, ma è discrezione del programmatore attuare quello che ritiene opportuno.
C++ adotta uno stile di OOP basato su questo tipo di incapsulamento.
Si, volendo puoi lasciare tutto a public, ma non ha alcun senso: il liunguaggio è progettato per essere usato in quel modo.
 
sydarex ha detto:
C++ adotta uno stile di OOP basato su questo tipo di incapsulamento.
Si, volendo puoi lasciare tutto a public, ma non ha alcun senso: il liunguaggio è progettato per essere usato in quel modo.

Dai troppa importanza al linguaggio, è il programmatore che definisce il modo di programmare, non il linguaggio. Meglio avere un linguaggio che mette a disposizione il più alto numero di strumenti, poi sta al programmatore decidere come utilizzarli. Se poi per te è ancora un problema di linguaggio, per quanto ti riguarda, non dovresti averlo visto che non programmi in C++, ma in Python.
[ot]
L'unica cosa, mi chiedo se hai mai sostenuto un esame universitario, magari programmazione orientata agli oggetti, presentando una classe con tutti membri public...
[/ot]
bronsa ha detto:
ma risolvere in pvt no?

cioè non centra un emerito pazzo con sto topic...



Almeno, diversamente dai vostri ot, qui si parla di programmazione. Se non hai niente da dire sull'argomento non c'è bisogno che posti per forza, nessuno ti obbliga ...
 
stoner ha detto:
Dai troppa importanza al linguaggio, è il programmatore che definisce il modo di programmare, non il linguaggio. Meglio avere un linguaggio che mette a disposizione il più alto numero di strumenti, poi sta al programmatore decidere come utilizzarli. Se poi per te è ancora un problema di linguaggio, per quanto ti riguarda, non dovresti averlo visto che non programmi in C++, ma in Python.
Mmh, è il tuo pensiero e lo rispetto; tuttavia non sono d'accordo: credo che la struttura di un linguaggio vada comunque rispettata per usarlo al meglio.
 
Ovvio, ma non bisogna mica sottoscrivere qualsiasi cosa del linguaggio. Se non amo le regex in PHP non le uso, se non mi piace LINQ in .NET neanche, stessa cosa vale per il private, se lo considero inutile dichiaro tutto public.
(Non hai risposto alla pseudo-domanda che ti ho fatto nel tag ot)
 
stoner ha detto:
(Non hai risposto alla pseudo-domanda che ti ho fatto nel tag ot)
Perdonami, non l'avevo proprio vista. XD
No, non vado ancora all'Uni.
Comunque, la risposta è semplice: se ti presenti con una classe tutta a public è ovvio che vieni bocciato.
Questo perché C++ prevede questo tipo di incapsulamento, e l'esame consiste nell'usare C++ rispettando le (sue) regole di OOP.
 
Mah, tutta questa discussione mi da da pensare...

Di sicuro sydra non hai ragione, in via teoria appoggio completamente stoner, e secondo me non ci sarebbe nemmeno da discuterne. Nell'OOP, generalmente parlando, è così che si fa, non è nessuna idea inculcata da nessun linguaggio.

Quello che mi da da pensare è proprio il fatto che il python adotta questo metodo, però la spiegazione più plausibile risiede probabilmente nella differenza sostanziale tra i due linguaggi, ovvero che uno è compilato e uno interpretato, in C++ puoi ovviamente nascondere i dettagli d'implementazione, in python no, quindi deh, serve a poco definire membri private (nel senso che non devono essere accessibili dai client, che il parser da proprio errore) se poi posso modificarmi il file di libreria come mi pare e piace. Invece, un approccio di "sensibilizzazione", in cui la responsabilità viene data al programmatore finale, può funzionare anche meglio nel contesto del linguaggio-python.

Sydarex, ti faccio un esempio, vedi il ruby (che considero il linguaggio OOP per eccellenza, di sicuro quello che meglio implementa l'idea di OOP) non ha niente a che vedere con il C++, ma addirittura NON viene data al progettista della classe la possibilità di definire attributi con visibilità a livello di classe che siano pubblici, vengono settati automaticamente privati, e ci sono specifici comandi per dire alla classe di creare automaticamente i metodi get e set, ovvero
attr_accessor :nomeAttributo

o, se devono essere solo leggibili o solo scrivibili
attr_reader :solaLettura
attr_writer :solaScrittura

Secondo me state discutendo inutilmente, 1° perché stoner ha assolutamente ragione, 2° perché i progettisti del python avranno avuto i loro buoni motivi, di sicuro nessuno di loro critica l'implementazione della programmazione ad oggetti nel C++.

EDIT: ah già, sono anche mod. SIETE COMPLETAMENTE OT!!!!oneoneon
 
io, per quel che ho visto del ruby, lo giudico essenzialmente un buon linguaggio OOP, struttura sostanzialemnte bene, ma a mio parere è alla pari con altri come interpretazione della filosofia OOP. Questa probabilmente è una mia idea che verrà ampiamente criticata, ma così la penso.

Cmq certo, sono OT, ma meglio questo ot dialettico che gli ot-cazzata che ci sono in certi post seri.
 
Stato
Discussione chiusa ad ulteriori risposte.