Perché la privacy a livello di oggetto è difficile da utilizzare come paradigma e perché è auspicabile?

1

Ho sentito un noto designer del linguaggio notare che nessuna lingua oggi applica la privacy degli oggetti reali e non siamo ancora sicuri se sia possibile in pratica progettare un linguaggio che lo faccia.

Senza cercare di leggere la mente di questa persona in particolare, questo ha suscitato il mio interesse. Ci sono, credo, due concetti distinti al lavoro qui:

  • Le lingue con privacy a livello di classe offrono quasi sempre un modo per aggirare il problema, ad esempio con l'introspezione. Sono necessari questi accorgimenti, in quanto la loro assenza renderebbe alcuni problemi molto più difficili da risolvere nella lingua e, in caso affermativo, non indica che il paradigma della privacy è difettoso? In altre parole, le persone (ab) usano questi meccanismi quando vengono forniti e perché?

  • La privacy a livello di classe non è la privacy a livello di oggetto (un oggetto ha accesso allo stato privato di altri oggetti se appartengono alla stessa classe) e non sappiamo come fare quest'ultimo. Ma perché dovremmo farlo?

posta dgirardi 04.10.2014 - 07:29
fonte

3 risposte

2
  • Languages with class-level privacy almost always provide ways to work-around it - for example with introspection. Are these workarounds necessary, in that their absence would make certain problems much harder to solve in the language

La riflessione e l'introspezione sono particolarmente utili nei test white-box, in modo da garantire la copertura del codice e i requisiti di implementazione. Per questo, è necessario accedere al rilassamento in riflessione. Gli strumenti a livello di lingua (a seconda del runtime) possono anche fare uso della riflessione (immagina un debugger nativo che deve accedere ai campi privati).

Alcuni sostengono che se una classe è stata progettata correttamente, non è necessario eseguire il test white-box (quindi, il rilassamento dell'accesso) dell'interfaccia privata. Poiché le interazioni di un oggetto con altri oggetti sono definite dalla sua interfaccia pubblica (o, nel caso di parenti, le sue interfacce pubbliche e protette), l'interfaccia privata è irrilevante. Se la classe è così complessa da richiedere il test dell'interfaccia privata per garantire la stabilità, l'argomento va, quindi la classe probabilmente ha troppe responsabilità e dovrebbe essere refactored in più classi.

In alcuni casi, è possibile utilizzare casting in C ++ per accedere ai campi privati, ma questo non è un uso previsto .

L'ereditarietà può essere utilizzata per ridurre le restrizioni di accesso, ma non è una soluzione temporanea, ma un'intersezione di regole di accesso e ereditarietà ed è suggerita da LSP .

and if so, doesn't that indicate that the privacy paradigm is flawed?

Nota che i test e i debugger della white-box non fanno parte dell'esecuzione normale del software, quindi l'elusione delle regole di accesso non impedisce (in questi casi) i loro scopi.

In other words, do people (ab)use these mechanisms when they are provided, and why?

Considererei questa una domanda separata da quella precedente. Le persone abusano decisamente della riflessione e dell'eredità per rilassare indebitamente l'accesso. Direi di solito quando succede è perché c'è un difetto di progettazione nel programma (non nella lingua), ma è più un'opinione che non.

Il cast per aggirare l'accesso privato è un abuso.

Aumentare l'accesso usando l'ereditarietà è spesso (sempre?) un abuso. A volte è un altro tipo di difetto di progettazione: nominare una collisione, in questo caso che si verifica quando si ridefinisce un metodo di base privato con un metodo pubblico non correlato che ha lo stesso nome e amp; firma.

  • Class-level privacy is not object-level privacy (an object has access to private state of other objects if they are of the same class), and we don't know how to do the latter.

Al contrario, in Ruby, nessuna variabile di istanza è accessibile a un'altra istanza, anche della stessa classe; lo stesso vale per i metodi privati. Il termine Ruby è "istanza-privato", piuttosto che "privato a livello di oggetto". Lo stesso vale per Eiffel e lo stile OOP funzionale (dove gli oggetti sono funzioni che accettano un messaggio). Smalltalk ha campi istanza-privati, ma non veri metodi privati. Scala supporta i membri privati dell'istanza.

In generale, l'accesso ai campi di istanza al di fuori di un'istanza non è sintatticamente possibile nelle lingue che utilizzano un modello di messaggistica piuttosto che un metodo call / member-access / slots, quindi i primi hanno campi istanza-privati, sebbene la funzione non è necessariamente esclusiva per loro.

Vedi anche " Perché i campi privati sono privati del tipo, non l'istanza? ".

But why would we want to?

Lo stesso motivo secondario di tutte le forme di occultamento delle informazioni: tutto ciò che può sovrascrivere lo stato è una potenziale fonte di bug; limitare il più possibile la superficie di un oggetto aiuta a ridurre il numero e le posizioni di potenziali bug.

    
risposta data 04.10.2014 - 14:31
fonte
0
  • Class-level privacy is not object-level privacy (an object has access to private state of other objects if they are of the same class), and we don't know how to do the latter. But why would we want to?

La privacy a livello di oggetto rende difficile / impossibile realizzare alcuni tipi di incapsulamento. Ad esempio, considera un oggetto che rappresenta un formato di file di registro:

class i_write_things
{
    std::ostream* writer;
public:
    bool equal(i_write_things const& other) { return this->writer == other.writer; }
    void write_to(std::string const& message) { /* ... */ }
};

Se la privacy a livello di oggetto era in uso, l'implementazione equal non sarebbe in grado di visualizzare writer nell'altra istanza di i_write_things . Pertanto, è necessario creare un getter per questa proprietà per implementare equal , che è l'incapsulamento peggiore: espone che l'implementazione interna di i_write_things utilizza un ostream .

    
risposta data 06.10.2014 - 20:30
fonte
0

Se la classe Foo accetta riferimenti a oggetti del suo tipo dal codice esterno e ne usa membri privati, allora il codice esterno dovrà usare riferimenti di tipo Foo o uno dei suoi sottotipi. Se Foo non ha avuto bisogno di utilizzare membri privati del proprio tipo, ma ha implementato un'interfaccia che includeva tutti i membri che aveva bisogno di usare, allora sarebbe possibile che il codice esterno usasse quel tipo di interfaccia invece di Foo , consentendo a tale codice di funzionare con altre implementazioni di tale interfaccia.

Sarebbe possibile che i metodi di Foo accettino i parametri del tipo di interfaccia anche se il linguaggio non impone la privacy a livello di oggetto, ma non sarebbe in grado di accedere a nessuno dei membri privati degli oggetti identificati da tali riferimenti all'interfaccia. Ciononostante, la capacità dei metodi di Foo di utilizzare i membri privati dei riferimenti passati può servire a scoraggiare l'uso di tipi più generali come parametri del messaggio.

    
risposta data 26.07.2015 - 00:06
fonte

Leggi altre domande sui tag