Quanto è importante l'incapsulamento? [duplicare]

6

Come studente in programmazione, ho imparato che l'incapsulamento è uno dei principi più importanti della programmazione orientata agli oggetti.

Tuttavia, seguo questo principio solo quando ritengo che sia adatto al mio scopo. A volte lascio le variabili di classe interne pubbliche se sono intese per essere letti direttamente in un dato momento e usano solo cose come setter e getter quando ci sono calcoli effettivi (e assegnazioni di altre variabili) coinvolti nell'assegnazione / valutazione di una variabile (ad esempio , una getDegrees() di una classe Angle che memorizza solo i radianti internamente).

Se trovo che una procedura eseguita con una classe implichi molte modifiche delle variabili interne e sia facilmente raggruppabile in una singola operazione, la inserirò in una funzione della classe piuttosto che avere il codice esterno chiama più funzioni più piccole . Tuttavia, non lo imporrò sempre nell'interfaccia rendendo invece private le variabili interessate.

Sto violando qualche principio facendo questo? Se sì, quanto severamente? Il codice che fa questo in genere non è rivolto verso l'esterno, poiché presta molta attenzione a come viene elaborato l'input fuori programma.

    
posta Joe Z. 21.02.2013 - 16:25
fonte

3 risposte

11

Uno dei vantaggi dell'utilizzo di getter e setter (o proprietà) piuttosto che di campi pubblici è che la logica può cambiare senza dover cambiare il consumatore. In questo momento potresti semplicemente aver bisogno di leggere e scrivere su / da una variabile, ma in futuro?

Ad esempio, nella tua classe Angle, cosa succederebbe se decidessi che d'ora in poi vuoi memorizzare l'angolo come gradi anziché come radianti? Ora è necessario un metodo getRadians () che esegue il calcolo appropriato e tutto il codice che ha consentito l'accesso a Angle.radians direttamente deve essere modificato per utilizzare questo nuovo metodo. D'altra parte, il metodo getDegrees () potrebbe ancora essere utilizzato. Tutto ciò che avrebbe bisogno di cambiare è la sua implementazione.

Se avessi usato entrambi i metodi getRadians () e getDegrees () per cominciare, questa modifica interna (da radianti a gradi) non riguarderebbe affatto i consumatori dell'oggetto - il suo contratto pubblico rimane lo stesso.

Uno dei principi di incapsulamento è che la rappresentazione interna di un oggetto non dovrebbe riguardare i suoi consumatori.

    
risposta data 21.02.2013 - 17:15
fonte
4

Sto lavorando su un codice base che suona molto come stai programmando. È abbastanza orribile. Quando sei al college (come lo sono stato di recente) questi principi non hanno molto senso, perché sono semplicemente asseriti. Tuttavia, tutti i tuoi compiti saranno molto piccoli rispetto alle applicazioni del mondo reale e raramente avranno la possibilità di diventare abbastanza complessi al punto da renderli difficili da gestire.

Questa nozione è preoccupante:

I sometimes leave internal class variables public if they are intended to be directly modified at some time

Quando si lavora su piccoli progetti, a volte sembra più conveniente lasciare che le variabili dei membri vengano alterate da classi esterne. Questa è quasi sempre una cattiva idea. Più variabili interne permetti al programma esterno di alterare, meno bene puoi ragionare sullo stato della tua classe in ogni punto del programma.

Questo tipo di design è indicativo di un modello oggetto errato. Se stai scoprendo di avere una classe con variabili che non solo devono essere lette, ma anche scritte spesso da altre parti del programma, è probabile che quelle variabili non siano logicamente parte di quella classe.

Nella mia esperienza, il miglior tipo di classe con cui lavorare è uno che è quasi, se non totalmente, immutabile dall'esterno, e solo permesso di apportare modifiche a se stesso internamente. Ancora meglio se non cambia mai una volta creato.

Ricorda che non tutte le variabili richiedono un getter and setter . Dovresti evitare di scriverne uno completamente finché non scopri che devi assolutamente averli. I getter saranno quasi sempre più comuni dei setter.

    
risposta data 21.02.2013 - 16:40
fonte
0

Come ho imparato di più su OO Development, ho realizzato che un oggetto con molti getter e setter non è realmente un oggetto ... è più di una struttura.

Alle persone piace usare esempi del mondo reale da illustrare specialmente quando si parla agli studenti. Quindi, usiamo un esempio che tutti possono capire.

Quando una persona è concepita, lui (o lei) sta dando determinati parametri che formeranno il suo aspetto. Altezza, peso, tono della pelle, colore degli occhi, struttura della mascella ecc. Ecc. Sono tutti determinati al momento del concepimento tramite DNA. Considerare il concepimento come costruttore di una persona e il DNA della madre e del padre come parametri per tale costruttore.

Ci sono alcune proprietà sulla persona che possono essere impostate dopo la costruzione (come il suo nome e la sua data di nascita - anche se è MOSTAMENTE determinata internamente), ma tutto il resto può essere osservato solo non modificato (beh, tranne che con la chirurgia, ma tu ottenere la mia direzione). Le modifiche all'altezza di una persona si verificano internamente ... nessuno dice "Michael, cresci due centimetri" il mio corpo determina quanto io cresca in base agli input che gli diamo (cibo, riposo, anche se fumo o no, e naturalmente il mio DNA ).

Gli oggetti complessi in un'applicazione dovrebbero essere come questo modello di un essere umano. Forniamo alcuni parametri in fase di costruzione. Possiamo eseguire operazioni su di esso (o anche eseguire operazioni su se stesso) e osservare i risultati del nostro input e la sua interazione con il resto del sistema. Ma i suoi dati principali dovrebbero essere immutabili all'esterno.

Anche gli oggetti semplici che hanno dati e poca logica dovrebbero essere immutabili perché rappresentano valori. Ad esempio, guarda una stringa in C # dopo averla inizializzata, non puoi cambiare quella copia della stringa allo stesso modo con Date. I dati inviati tra gli oggetti devono essere immutabili o una copia dell'originale (C # supporta questo in modo nativo tramite Structs che vengono passati per valore rispetto a Classi che sono considerati per riferimento).

    
risposta data 21.02.2013 - 19:32
fonte

Leggi altre domande sui tag