Come viene utilizzato l'incapsulamento per la sicurezza?

8

Sto imparando OOP. Ho studiato molto sull'incapsulazione ma più leggo e più mi confondo.

Capisco di nascondere (rendendo privati) i dati e di esporli all'utente della classe (altri sviluppatori) come proprietà o metodi. Capisco anche per incapsulamento che nascondiamo i dettagli.

In un articolo (http://www.csharp-station.com/Tutorial/CSharp/lesson19) ho letto:

Estratto dall'articolo

Quando progetti un oggetto, devi pensare a come gli altri potrebbero usarlo. Nel migliore dei casi, qualsiasi programma che utilizza l'oggetto sarebbe ben progettato e il codice non cambierebbe mai. Tuttavia, la realtà è che i programmi cambiano spesso e in un ambiente di squadra molte persone toccano lo stesso codice in una volta o nell'altra. Pertanto, è utile considerare cosa potrebbe andare storto così come l'immagine incontaminata di come l'oggetto dovrebbe essere usato.

Nel caso dell'oggetto BankAccount, esaminare la situazione in cui il codice esterno all'oggetto può accedere a un campo Importo decimale o a un campo CustomerName stringa. Nel momento in cui il codice è scritto, tutto funzionerebbe bene. Tuttavia, più avanti nel ciclo di sviluppo, ti rendi conto che l'oggetto BankAccount dovrebbe tenere traccia di un CustomerID int anziché della stringa CustomerName perché non vuoi duplicare le relazioni tra le informazioni (o qualche altro motivo valido per alterare la definizione di stato interno) . Tali modifiche causano un effetto di increspatura nel codice perché è stato creato per utilizzare la classe BankAccount, come originariamente progettato (con CustomerName come stringa) e ora devi modificare il codice che accede a tale stato nell'intero applicazione.

Il principio orientato agli oggetti di Incapsulamento aiuta a evitare tali problemi, consentendo di nascondere lo stato interno e l'accesso astratto ad esso, anche se si digitano membri come metodi, proprietà e indicizzatori. L'incapsulamento aiuta a ridurre l'accoppiamento tra gli oggetti e aumenta la manutenibilità del codice.

Domanda In che modo l'incapsulamento aiuta quando si apportano modifiche nel codice e dai suoi effetti a increspature. Per un membro dati, se cambio il suo tipo da int a float, (anche se sto esponendo questo usando la proprietà) dovrò cambiare tipo di variabile dove sto usando già usando questo codice.

Gentilmente guidami come l'incapsulamento ti aiuterà con questi cambiamenti.

Grazie per questo aiuto e guida.

    
posta haansi 17.05.2012 - 16:21
fonte

6 risposte

8

How will encapsulation help when making changes in code and from its rippling effects. For a data member, if I change its type from int to float, (even if I am exposing this using property) I will need to change variable type where I am using already using this code.

Il vantaggio dell'incapsulamento è che ti consente di modificare l'implementazione interna senza rompere il codice client. Non ti protegge se decidi che devi cambiare l'interfaccia con il tuo codice, ma è diverso.

Esempio: Supponiamo che tu abbia un valore che rappresenta il prezzo per unità di una certa merce. Il prezzo è espresso in centesimi, e poiché non ti occupi di centesimi frazionari hai deciso di rendere la proprietà un numero intero (userò C qui perché non ho molta familiarità con C #):

int _price

int pricePerUnit(void) {
    return _price;
}

int priceForUnits(int units) {
    return units * _price;
}

Tutto funziona bene fino a quando un giorno qualcuno noterà che la tua azienda sta perdendo molti soldi a causa di errori di arrotondamento. Molte delle materie prime che vengono monitorate vengono acquistate e vendute in molte migliaia di unità, quindi è necessario iniziare a tracciare il prezzo con una precisione di almeno 0,001 cent. Poiché sei stato abbastanza intelligente da incapsulare il prezzo invece di consentire ai clienti di accedervi direttamente, puoi apportare questa modifica abbastanza rapidamente:

double _dprice

int pricePerUnit(void) {
    return (int)_dprice;
}

int priceForUnits(int units) {
    return (int)(units * _dprice);
}

L'interfaccia che i clienti utilizzano per ottenere i prezzi rimane la stessa, ma i dati che ottengono sono ora più accurati. Se il prezzo per unità è $ 1.001, priceForUnits(1000000) restituirà ora un prezzo superiore di $ 1000 rispetto a prima. Ciò accade anche se non hai affatto cambiato l'interfaccia con il tuo sistema e quindi non hai rotto alcun codice client.

Ora, potrebbe non essere sempre tutto ciò che devi fare. A volte devi modificare o aumentare l'interfaccia in modo da poter riportare il prezzo in modo più accurato anche ai clienti:

double pricePerUnit() {
    return _dprice;
}

Una modifica del genere interromperà il codice client, quindi potresti invece mantenere la vecchia interfaccia e fornire una routine nuova e migliore:

int pricePerUnit() {
    return (int)_dprice;
}

double accuratePricePerUnit() {
    return _dprice;
}

Tu e il resto del tuo team potete quindi intraprendere il processo di conversione di tutti i client del vostro sistema per utilizzare il più recente, migliore accuratePricePerUnit() . Il codice cliente diventerà più preciso man mano che avanzi in questo compito, ma anche le vecchie cose dovrebbero continuare a funzionare come in passato.

Ad ogni modo, il punto è che l'incapsulamento ti permette di cambiare il modo in cui gli interni lavorano mentre presenta un'interfaccia coerente, e questo ti aiuta a fare cambiamenti utili senza infrangere altro codice. Non ti protegge sempre dal dover aggiornare altro codice, ma può almeno aiutarti a farlo in modo controllato.

    
risposta data 17.05.2012 - 19:46
fonte
3

Nella mia esperienza, l'incapsulamento rende la cosa "sbagliata" molto più difficile. È possibile raggruppare le funzionalità che vanno insieme semanticamente e isolarle da funzionalità che possono portare a comportamenti negativi o imprevedibili. Può anche aiutare a nascondere i dettagli all'utente finale, il che può contribuire ad aumentare la sicurezza e l'affidabilità.

Considera questo post di John D Cook . Considera di avere un oggetto Bread . Una cosa naturale per tagliare questo pane. Quindi scrivi una funzione slice() , quindi puoi fare

slice(loaf)

con un nuovo oggetto loaf che hai creato. Questo ha senso. Ma se non stai attento, potresti chiamare accidentalmente

slice(finger)

con un oggetto finger da qualche parte nel tuo progetto. Questo potrebbe portare a cose molto brutte. Invece, incapsula questa funzione / metodo in una classe Bread , quindi puoi farlo

loaf.slice()

Questo sicuramente aiuta ad evitare di chiamare finger.slice() accidentalmente, poiché finger probabilmente non ha un metodo slice() ad esso associato.

Questo è un esempio un po 'forzato ma l'ho trovato utile. L'incapsulamento può a volte essere un aspetto sottovalutato di OOP, ma è buono.

    
risposta data 17.05.2012 - 18:54
fonte
2

L'incapsulamento aiuta grandi gruppi di sviluppatori a coordinare il loro lavoro in modo più efficiente. Ogni gruppo di sviluppatori lavora su diversi moduli, e questi moduli sono incapsulati - separano il codice in un numero ristretto di operatori ampiamente disponibili il cui uso non possono controllare strettamente, e un gran numero di operatori interni che possono controllare strettamente. Ciò significa che ciascun gruppo di sviluppatori può definire invarianti che sono importanti perché il loro modulo mantenga e si assicuri che tali invarianti siano validi indipendentemente dagli sviluppatori degli altri moduli.

Poiché l'incapsulamento consente la conservazione invariante, viene spesso utilizzato per mantenere invarianti sicurezza / sicurezza, ad es.

  • che un archivio dati non è mai accessibile senza credenziali appropriate
  • che un conto bancario non ha mai più denaro aggiunto di quello rimosso da un altro
  • che alcune operazioni sono sempre registrate

Il modello di capacità degli oggetti è una metodologia per scrivere codice sensibile alla sicurezza incapsulato sugli steroidi.

The security model relies on not being able to forge references; see Synthesizing addresses of actors.

Objects can interact only by sending messages on references. A reference can be obtained by:

  1. initial conditions: In the initial state of the computational world being described, object A may already have a reference to object B. parenthood: If A creates B, at that moment A obtains the only reference to the newly created B.
  2. endowment: If A creates B, B is born with that subset of A's references with which A chose to endow it.
  3. introduction: If A has references to both B and C, A can send to B a message containing a reference to C. B can retain that reference for subsequent use.

In the Object-capability model, all computation is performed following the above rules.

Advantages that motivate object-oriented programming, such as encapsulation or information hiding, modularity, and separation of concerns, correspond to security goals such as least privilege and privilege separation in capability-based programming.

    
risposta data 17.05.2012 - 19:10
fonte
2

How will encapsulation help when making changes in code and from its rippling effects.

Lascia che ti dia un esempio tipico e semplicistico. Innanzitutto, supponi di non utilizzare l'incapsulamento: Si dispone di un set di dati e si utilizza una matrice per archiviare tali dati e un'altra parte del programma utilizza tale matrice. Ora, se ad un certo punto decidi che una lista collegata è una scelta migliore per la memorizzazione dei tuoi dati. Se sostituisci un array con un elenco collegato, che cosa succederà? Il tuo programma si interromperà, a meno che tu non apporti modifiche in tutto il luogo per sostituire la logica di elaborazione della matrice con la logica di elaborazione delle liste collegate.

Ma, se usi OO / Encapsulation, allora partizionerai il tuo programma in classi, uno che memorizza i dati e altro, che usa i dati. Nella prima classe, nascondi la tua implementazione (incapsulamento) e esponi i tuoi servizi attraverso metodi come

size()
remove(int index)
add(int index, Object o)
get(int index)

...

In questo secondo caso, se si modifica l'implementazione della classe di memorizzazione dall'array alla lista collegata o a qualsiasi altra cosa, ciò non influirà sui client. Nessun effetto a catena.

    
risposta data 17.05.2012 - 19:38
fonte
1

Il modo principale in cui l'incapsulamento aiuta a ridurre gli effetti increspanti del cambiamento è quello di mantenere il maggior numero di dettagli di implementazione privati nella classe. Limitando l'interfaccia solo a quei membri necessari per utilizzare la classe, molte modifiche possono essere apportate all'implementazione senza influire su alcun codice che utilizza la classe.

Questo sembra essere il punto che viene fatto dal testo che hai citato, anche se ho trovato un po 'di confusione nella mia prima lettura.

    
risposta data 17.05.2012 - 16:31
fonte
1

Penso che ti permetta di cambiare la funzionalità della tua classe senza, anche se non sempre, introducendo interruzioni BC (compatibilità binaria o comportamentale). Cioè, puoi cambiare il modo in cui la tua classe fa 'qualcosa' senza dover cambiare il modo in cui l'utente finale gli dice di fare quel 'qualcosa'.

L'esempio che hai dato di cambiare il tipo di ritorno è un'interruzione BC, perché chiunque abbia usato la tua classe in precedenza non sarà in grado di utilizzare la nuova versione senza ricompilare. Questo è qualcosa che dovrebbe essere fatto solo come ultima risorsa, e in un contesto professionale può essere fatto solo con la liquidazione da parte degli architetti e dopo che è stata archiviata la documentazione, i clienti hanno comunicato, ecc.

Ti dà anche il controllo completo sullo stato del tuo oggetto.

    
risposta data 17.05.2012 - 18:31
fonte

Leggi altre domande sui tag