L'informazione si nasconde più di una convenzione?


20

In Java, C # e molti altri linguaggi fortemente tipizzati e controllati staticamente, siamo abituati a scrivere codice in questo modo:

public void m1() { ... }
protected void m2() { ... }
private void m2() { ... }
void m2() { ... }

Alcune lingue controllate dinamicamente non forniscono parole chiave per esprimere il livello di "riservatezza" di un determinato membro della classe e si affidano invece a convenzioni di codifica. Python ad esempio prefigura i membri privati ​​con un trattino basso:

_m(self): pass

Si può sostenere che fornire tali parole chiave in linguaggi controllati dinamicamente aggiungerebbe poco uso poiché è controllato solo in fase di esecuzione.

Tuttavia, non riesco a trovare un buon motivo per fornire queste parole chiave in lingue controllate staticamente. Trovo il requisito per riempire il mio codice con parole chiave piuttosto prolisse come protectedfastidiose e fonte di distrazione. Finora, non sono stato in una situazione in cui un errore del compilatore causato da queste parole chiave mi avrebbe salvato da un bug. Al contrario, sono stato in situazioni in cui una posizione errata protectedmi ha impedito di usare una libreria.

Con questo in mente, la mia domanda è:

Le informazioni che nascondono più di una convenzione tra programmatori vengono utilizzate per definire cosa fa parte dell'interfaccia ufficiale di una classe?

Può essere usato per proteggere l'attacco di uno stato segreto di una classe? La riflessione può scavalcare questo meccanismo? Cosa renderebbe utile per il compilatore imporre il nascondere le informazioni?


10
Spiacente, Eric Lippert è in vacanza :)
Benjol,

La tua domanda è un po 'difficile da capire. In pratica stai solo chiedendo se qualcuno può accedere a un membro privato dall'esterno?
Morgan Herlocker,


@ironcode: posso dire che in qualche modo non mi esprimo abbastanza chiaro da alcune delle risposte. Puoi dire cosa rende particolarmente difficile capire? Proverò a chiarire.
Blubb,

2
"Non ha senso fornire informazioni in fase di compilazione e quindi verificarle solo in fase di esecuzione" - davvero? Meglio dirlo a Microsoft perché è su questo che si basa un grosso pezzo dell'attuale framework .NET: opt-in o opt-out selettivo della tipizzazione statica. Non penso che questo sia davvero ciò che intendi; la domanda parla ripetutamente del controllo "statico" vs. "dinamico", ma queste sono caratteristiche del sistema di tipi; ciò che è veramente in questione qui è in fase di compilazione vs runtime vincolante .
Aaronaught,

Risposte:


4

Sto studiando per la certificazione Java e tutto questo riguarda come gestire i modificatori di accesso. E hanno un senso e dovrebbero essere usati correttamente.

Ho lavorato con Python e, durante il mio viaggio di apprendimento, ho sentito che in Python la convenzione è lì perché le persone, che lavorano con esso, dovrebbero sapere cosa significa e come applicarlo. Detto questo, nel carattere di _m(self): passsottolineatura mi avvertirebbe di non scherzare con quel campo. Ma tutti seguiranno quella convenzione? Lavoro con JavaScript e devo dire che non lo fanno . A volte ho bisogno di controllare un problema e il motivo era che la persona stava facendo qualcosa che non avrebbe dovuto fare ...

leggi questa discussione riguardo al carattere di sottolineatura principale di Python

Le informazioni che nascondono più di una convenzione tra programmatori vengono utilizzate per definire cosa fa parte dell'interfaccia ufficiale di una classe?

Da quello che ho detto, Sì.

Può essere usato per proteggere l'attacco di uno stato segreto di una classe? La riflessione può scavalcare questo meccanismo? Ci sono altri vantaggi offerti da un meccanismo più formale applicato dal compilatore?

Sì, può essere usato per proteggere lo stato segreto di una classe e non dovrebbe essere usato solo per quello, ma per impedire agli utenti di scherzare con lo stato degli oggetti per cambiare i loro comportamenti in qualcosa che pensano dovrebbero essere come l'oggetto dovrebbe avere sto lavorando. Come sviluppatore, dovresti pianificare e riflettere su di esso e progettare la tua classe in modo sensato, in modo che il suo comportamento non venga alterato. E il compilatore, come un buon amico, ti aiuterà a mantenere il codice nel modo in cui lo hai progettato applicando le politiche di accesso.

MODIFICATO Sì, la riflessione può, controlla i commenti

L'ultima domanda è interessante e sono disposto a leggere le risposte a riguardo.


3
La riflessione di solito può bypassare la protezione dell'accesso. Per Java e C #, entrambi possono accedere ai dati privati.
Segna H

Grazie! Le risposte qui: stackoverflow.com/questions/1565734/… spiegalo!
wleao,

1
La cultura Javascript è molto diversa dalla cultura Python. Python ha pep-08 e quasi tutti gli sviluppatori di Python seguono queste convenzioni. Le violazioni di PEP-08 sono spesso considerate un bug. Quindi penso che javascript / php / perl / ruby ​​experience si traduca molto poco in esperienza Python in questo aspetto: _private funziona molto bene in Python.
Mike Korobov,

1
In alcuni (ma non in tutti) i linguaggi di programmazione, la protezione delle informazioni può essere utilizzata per proteggere da codice ostile. Il nascondimento delle informazioni non può essere utilizzato per proteggere dagli utenti ostili.
Brian,

2
@Mike se le violazioni di PEP-08 sono così spesso "considerate come un bug" e nessun sviluppatore di Python sogna di non seguire le convenzioni, allora potresti anche farle applicare dal linguaggio! Perché i lavori umili quando la lingua può farlo automaticamente?
Andres F.

27

L'identificatore di accesso "privato" non riguarda l'errore del compilatore che genera la prima volta che lo vedi. In realtà si tratta di impedirti di accedere a qualcosa che è ancora soggetto a modifiche quando cambia l'implementazione della classe che tiene il membro privato.

In altre parole, non permetterti di usarlo quando funziona ancora ti impedisce di usarlo accidentalmente quando non funziona più.

Come sottolineato da Delnan sotto, la convenzione del prefisso scoraggia l'uso accidentale dei membri che sono soggetti a modifiche purché la convenzione venga seguita e compresa correttamente. Per un utente malintenzionato (o ignorante) non fa nulla per impedire loro di accedere a quel membro con tutte le possibili conseguenze. Nelle lingue con supporto integrato per gli identificatori di accesso ciò non accade nell'ignoranza (errore del compilatore) e si distingue come un pollice dolente quando dannoso (strane costruzioni da raggiungere per il membro privato).

L'identificatore di accesso "protetto" è una storia diversa: non pensare a questo semplicemente come "non abbastanza pubblico" o "molto simile a privato". "Protetto" significa che probabilmente vorrai usare quella funzionalità quando derivi dalla classe che contiene il membro protetto. I membri protetti fanno parte dell '"interfaccia di estensione" che verrà utilizzata per aggiungere funzionalità alle classi esistenti senza modificare quelle classi stesse.

Quindi, breve riepilogo:

  • pubblico: utilizzare in modo sicuro su istanze della classe, lo scopo della classe, non cambierà.
  • protetto: da utilizzare durante l'estensione (derivante da) la classe - può cambiare se l'implementazione deve cambiare drasticamente.
  • privato: non toccare! Può cambiare a piacimento per fornire una migliore implementazione delle interfacce previste.

3
Ancora più importante, qualsiasi convenzione (facilmente riconoscibile, come nel caso dei caratteri di sottolineatura principali) non applicata per "dettagli di implementazione, soggetti a modifiche" evita anche l'uso riservato da parte di membri privati. In Python, ad esempio, l'unica volta in cui un programmatore sano scrive codice usando un membro privato dall'esterno (e anche allora è accigliato) è quando è quasi inevitabile, sa esattamente cosa fa e accetta la potenziale rottura nelle versioni future . Cioè, una situazione in cui, ad esempio, i programmatori Java utilizzerebbero la riflessione.

3
@Simon Stelling - no, sto dicendo che l'implementatore originale della classe che ha reso qualcosa di privato ti sta dicendo "non usare questo, qualsiasi comportamento qui potrebbe cambiare in futuro". Ad esempio, una variabile membro privata di una classe che per prima contiene una distanza tra due punti può in seguito contenere la distanza tra due punti al quadrato per motivi di prestazioni. Tutto ciò che avrebbe fatto affidamento sul vecchio comportamento si sarebbe rotto in silenzio.
Joris Timmermans,

1
@MadKeithV: Quindi in che modo una parola chiave a livello di lingua che dice "non toccare perché ..." è diversa da una convenzione che significa la stessa cosa? Solo il compilatore lo impone, ma poi torniamo alla vecchia discussione statica vs. dinamica.

7
@Simon Stelling (e Delnan) - per me è un po 'come chiedere "come è un limitatore del motore diverso da un segno di limite di velocità".
Joris Timmermans,

1
Sono ben consapevole della differenza e non ho mai detto che non c'era. Trovo solo che la tua risposta e la maggior parte dei tuoi commenti di follow-up descrivono semplicemente i tipi di annotazioni per i membri e i metodi che possono essere fatti con convenzioni o parole chiave a livello di lingua e lasciano la differenza effettiva (presenza di applicazione a livello di lingua) inferito dal lettore.

11

Se stai scrivendo un codice che verrà utilizzato da qualcun altro, nascondere le informazioni può fornire un'interfaccia molto più semplice da comprendere. "Qualcun altro" potrebbe essere un altro sviluppatore del tuo team, sviluppatori che consumano un'API che hai scritto commercialmente o persino il tuo sé futuro che "semplicemente non riesce a ricordare come funziona la cosa pericolosa". È molto più semplice lavorare con una classe che ha solo 4 metodi disponibili rispetto a uno che ne ha 40.


2
Sono totalmente d'accordo, ma questo non risponde alla mia domanda. Se uso _membero private membernella mia classe è trascurabile, purché l'altro programmatore capisca che dovrebbe guardare solo publico membri senza prefisso.
Blubb,

6
Sì, ma la documentazione pubblica di una classe scritta in un linguaggio dinamico non ti lancia nemmeno quelle 36 parti private (almeno non di default).

3
@Simon L'affermazione che si tratta di "solo una convenzione" è fuorviante, dal momento che ha benefici reali. "Just a convention" è qualcosa come parentesi graffe nella riga successiva. Una convenzione con vantaggi è qualcosa di simile all'uso di nomi significativi, che direi totalmente diverso. L'impostazione di qualcosa su privato impedisce a qualcuno di vederti "metodi segreti"? No, non se sono determinati.
Morgan Herlocker,

1
@ Simone- inoltre, esponendo solo metodi sicuri da usare aumenta la probabilità che l'utente non rompa qualcosa quando prova a usare la classe. Esistono facilmente metodi che potrebbero causare l'arresto anomalo di un server Web se chiamato mille volte. Non vuoi che i consumatori della tua API siano in grado di farlo. L'astrazione è più di una semplice convenzione.
Morgan Herlocker,

4

Vorrei suggerire che per lo sfondo, si inizia leggendo sugli invarianti di classe .

Un invariante è, per farla breve, un'ipotesi sullo stato di una classe che dovrebbe rimanere vera per tutta la vita di una classe.

Usiamo un esempio C # davvero semplice:

public class EmailAlert
{
    private readonly List<string> addresses = new List<string>();

    public void AddRecipient(string address)
    {
        if (!string.IsNullOrEmpty(address))
            addresses.Add(address);
    }

    public void Send(string message)
    {
        foreach (string address in addresses)
            SendTo(address, message);
    }

    // Details of SendTo not shown
}

Cosa sta succedendo qui?

  • Il membro addressesviene inizializzato sulla costruzione della classe.
  • È privato, quindi nulla dall'esterno può toccarlo.
  • L'abbiamo anche realizzato readonly, quindi nulla dall'interno può toccarlo dopo la costruzione (questo non è sempre corretto / necessario, ma è utile qui).
  • Pertanto, il Sendmetodo può fare un'ipotesi che addressesnon sarà mai null. Non deve eseguire tale verifica perché non v'è alcun modo che il valore può essere modificato.

Se ad altre classi fosse permesso di scrivere sul addressescampo (cioè se lo fosse public), allora questa ipotesi non sarebbe più valida. Ogni singolo altro metodo nella classe che dipende da quel campo dovrebbe iniziare a fare controlli nulli espliciti o rischiare di arrestare il programma.

Quindi sì, è molto più di una "convenzione"; tutti i modificatori di accesso sui membri della classe formano collettivamente una serie di ipotesi su quando e come tale stato può essere modificato. Tali presupposti vengono successivamente incorporati in membri e classi dipendenti e interdipendenti in modo che i programmatori non debbano ragionare sull'intero stato del programma contemporaneamente. La capacità di formulare ipotesi è un elemento critico nella gestione della complessità del software.

A queste altre domande:

Può essere usato per proteggere l'attacco di uno stato segreto di una classe?

Sì e no. Il codice di sicurezza, come la maggior parte del codice, si baserà su alcuni invarianti. I modificatori di accesso sono sicuramente utili come indicazioni per i chiamanti fidati che non dovrebbero sbagliare. Il codice dannoso non se ne preoccuperà, ma neanche il codice dannoso deve passare attraverso il compilatore.

La riflessione può scavalcare questo meccanismo?

Certo che può. Ma la riflessione richiede che il codice chiamante abbia quel livello di privilegio / fiducia. Se stai eseguendo codice dannoso con piena fiducia e / o privilegi amministrativi, allora hai già perso quella battaglia.

Cosa renderebbe utile per il compilatore imporre il nascondere le informazioni?

Il compilatore lo applica già. Lo stesso vale per il runtime in .NET, Java e altri ambienti simili: il codice operativo utilizzato per chiamare un metodo non avrà esito positivo se il metodo è privato. Gli unici modi per aggirare quella restrizione richiedono un codice attendibile / elevato e il codice elevato potrebbe sempre scrivere direttamente nella memoria del programma. È applicato tanto quanto può essere applicato senza richiedere un sistema operativo personalizzato.


1
@Simon: Dobbiamo chiarire "l'ignoranza" qui. Il prefisso di un metodo _indica il contratto, ma non lo impone. Ciò può rendere difficile ignorare il contratto, ma non rende difficile rompere il contratto, soprattutto se confrontato con metodi noiosi e spesso restrittivi come Reflection. Una convenzione dice "non dovresti rompere questo". Un modificatore di accesso dice "non puoi romperlo". Sto Non cercando di dire che un approccio è meglio rispetto agli altri - sono entrambi bene a seconda della filosofia, ma sono comunque molto diversi approcci.
Aaronaught

2
Che ne dici di un'analogia: un modificatore A private/ protectedaccess è come un preservativo. Non devi usarne uno, ma se non lo farai, è meglio che tu sia dannatamente sicuro dei tuoi tempi e dei tuoi partner. Non impedirà un atto doloso e potrebbe anche non funzionare tutte le volte, ma ridurrà sicuramente i rischi di disattenzione e lo farà molto più efficacemente di dire "per favore, stai attento". Oh, e se ne hai uno, ma non usarlo, allora non aspettarti alcuna simpatia da me.
Aaronaught,

3

Nascondere le informazioni è molto più di una semplice convenzione; tentare di aggirarlo può effettivamente rompere la funzionalità della classe in molti casi. Ad esempio, è pratica abbastanza comune archiviare un valore in una privatevariabile, esporlo utilizzando una protectedo publicproprietà dello stesso tempo e, nel getter, verificare la presenza di null ed eseguire qualsiasi inizializzazione necessaria (ad esempio caricamento lento). O memorizza qualcosa in una privatevariabile, esponilo usando una proprietà e, nel setter, controlla se il valore è cambiato e incendi PropertyChanging/ PropertyChangedeventi. Ma senza vedere l'implementazione interna, non sapresti mai tutto quello che succede dietro le quinte.


3

Il nascondere le informazioni si è evoluto da una filosofia progettuale dall'alto verso il basso. Python è stato chiamato un linguaggio dal basso verso l'alto .

Il nascondere le informazioni viene applicato bene a livello di classe in Java, C ++ e C #, quindi non è davvero una convenzione a questo livello. È molto facile fare di una classe una "scatola nera", con interfacce pubbliche e dettagli nascosti (privati).

Come hai sottolineato, in Python spetta ai programmatori seguire la convenzione di non utilizzare ciò che si intende nascondere, poiché tutto è visibile.

Anche con Java, C ++ o C #, a un certo punto nascondere le informazioni diventa una convenzione. Non esistono controlli di accesso ai più alti livelli di astrazione coinvolti in architetture software più complesse. Ad esempio, in Java puoi trovare l'uso di ".internal". nomi dei pacchetti. Questa è puramente una convenzione di denominazione perché non è facile applicare questo tipo di informazioni tramite la sola accessibilità del pacchetto.

Una lingua che si sforza di definire formalmente l'accesso è Eiffel. Questo articolo sottolinea alcune altre debolezze che nascondono le informazioni di lingue come Java.

Contesto: il nascondiglio delle informazioni è stato proposto nel 1971 da David Parnas . Sottolinea in quell'articolo che l'uso di informazioni su altri moduli può "aumentare in modo disastroso la connettività della struttura del sistema". Secondo questa idea, la mancanza di occultamento delle informazioni può portare a sistemi strettamente accoppiati che sono difficili da mantenere. Continua con:

Desideriamo che la struttura del sistema sia determinata esplicitamente dai progettisti prima dell'inizio della programmazione, piuttosto che inavvertitamente dall'uso delle informazioni da parte di un programmatore.


1
+1 per la citazione "uso delle informazioni da parte del programmatore", esattamente (anche se alla fine hai una virgola in più).
jmoreno,

2

Ruby e PHP lo hanno e lo applicano in fase di esecuzione.

Il punto di nascondere le informazioni è in realtà la visualizzazione delle informazioni. "Nascondendo" i dettagli interni, lo scopo diventa evidente da una prospettiva esterna. Ci sono lingue che abbracciano questo. In Java, accedere ai valori predefiniti per il pacchetto interno, in haXe per proteggere. Li dichiari esplicitamente pubblici per esporli.

Il punto è quello di rendere le tue lezioni facili da usare esponendo solo un'interfaccia altamente coerente. Volete che il resto sia protetto, in modo che nessun ragazzo intelligente arrivi e faccia casino con il vostro stato interno per indurre la classe a fare ciò che vuole.

Inoltre, quando i modificatori di accesso vengono applicati in fase di esecuzione, è possibile utilizzarli per imporre un certo livello di sicurezza, ma non credo che questa sia una soluzione particolarmente buona.


1
Se la tua libreria viene utilizzata nella stessa azienda in cui lavori, ti importerà ... Se si blocca la sua app, avrai difficoltà a ripararla.
wleao,

1
Perché fingere di indossare una cintura di sicurezza quando potresti indossarla? Riformulerei la domanda e la farei, c'è qualche motivo per cui un compilatore non la imponga, se tutte le informazioni sono disponibili. Non vuoi aspettare fino a quando non hai un incidente per scoprire se valeva la pena indossare quella cintura di sicurezza.
Segna H

1
@Simon: perché ingombrare un'interfaccia con cose che non vuoi che le persone usino. Odio il fatto che C ++ richieda che ogni membro sia presente nella definizione della classe in un file di intestazione (capisco perché). Le interfacce sono per altre persone e non dovrebbero essere disseminate di cose che non possono usare.
Phkahler,

1
@phkahler: pydocrimuove _prefixedMembersdall'interfaccia. Le interfacce disordinate non hanno nulla a che fare con la scelta di una parola chiave verificata dal compilatore.
blubb

2

I modificatori di accesso possono sicuramente fare qualcosa che la convenzione non può fare.

Ad esempio, in Java non è possibile accedere a un membro / campo privato se non si utilizza la riflessione.

Pertanto, se scrivo l'interfaccia per un plug-in e nego correttamente i diritti di modifica dei campi privati ​​tramite la riflessione (e di impostare il gestore della sicurezza :)), posso inviare alcuni oggetti alle funzioni implementate da chiunque e sapere che non può accedere ai suoi campi privati.

Naturalmente ci possono essere alcuni bug di sicurezza che gli permetterebbero di superare questo, ma questo non è filosoficamente importante (ma in pratica lo è sicuramente).

Se l'utente esegue la mia interfaccia nel suo ambiente, ha il controllo e quindi può eludere i modificatori di accesso.


2

Non sono stato in una situazione in cui un errore del compilatore causato da queste parole chiave mi avrebbe salvato da un bug.

Non è tanto per salvare gli autori delle applicazioni dai bug quanto per consentire agli autori delle biblioteche di decidere quali parti della loro implementazione si stanno impegnando a mantenere.

Se ho una biblioteca

class C {
  public void foo() { ... }

  private void fooHelper() { /* lots of complex code */ }
}

Potrei voler sostituire fool'implementazione e possibilmente cambiare fooHelperin modo radicale. Se un gruppo di persone ha deciso di utilizzare fooHelpernonostante tutti gli avvisi nella mia documentazione, allora potrei non essere in grado di farlo.

privateconsente agli autori di biblioteche di suddividere le biblioteche in metodi di dimensioni gestibili (e privateclassi di supporto) senza il timore che saranno costretti a conservare quei dettagli interni per anni.


Cosa renderebbe utile per il compilatore imporre il nascondere le informazioni?

In una nota a margine, in Java privatenon viene applicato dal compilatore, ma dal verificatore bytecode Java .


La riflessione può scavalcare questo meccanismo? Cosa renderebbe utile per il compilatore imporre il nascondere le informazioni?

In Java, non solo la riflessione può sovrascrivere questo meccanismo. Esistono due tipi di privatein Java. Il tipo di privateciò impedisce a una classe esterna di accedere ai privatemembri di un'altra classe esterna che viene verificata dal verificatore bytecode, ma è anche privateusata da una classe interna tramite un metodo di accesso sintetico pacchetto-privato come in

 public class C {
   private int i = 42;

   public class B {
     public void incr() { ++i; }
   }
 }

Poiché la classe B(realmente denominata C$B) utilizza i, il compilatore crea un metodo Bdi accesso sintetico che consente di accedere C.iin un modo che supera il verificatore bytecode. Sfortunatamente, poiché ClassLoaderti permette di creare una classe da a byte[], è abbastanza semplice arrivare ai privati ​​che si Csono esposti alle classi interne creando una nuova classe nel Cpacchetto che è possibile seC il vaso non è stato sigillato.

Una corretta privateapplicazione richiede il coordinamento tra i classloader, il verificatore di bytecode e la politica di sicurezza che può impedire l'accesso riflessivo ai privati.


Può essere usato per proteggere l'attacco di uno stato segreto di una classe?

Sì. La "decomposizione sicura" è possibile quando i programmatori possono collaborare preservando al contempo le proprietà di sicurezza dei loro moduli - Non devo fidarmi dell'autore di un altro modulo di codice per non violare le proprietà di sicurezza del mio modulo.

Linguaggi di funzionalità dell'oggetto come Joe-E utilizzano il nascondimento delle informazioni e altri mezzi per rendere possibile la decomposizione sicura:

Joe-E è un sottoinsieme del linguaggio di programmazione Java progettato per supportare la programmazione sicura in base alla disciplina della capacità dell'oggetto. Joe-E ha lo scopo di facilitare la costruzione di sistemi sicuri, nonché di facilitare le revisioni di sicurezza dei sistemi costruiti in Joe-E.

Il documento collegato da quella pagina fornisce un esempio di come l' privateapplicazione rende possibile la decomposizione sicura.

Fornire incapsulamento sicuro.

Figura 1. Una funzione di registrazione solo append.

public final class Log {
  private final StringBuilder content;
  public Log() {
    content = new StringBuilder();
  }
  public void write(String s) {
    content.append(s);
  }
}

Si consideri la Fig. 1, che illustra come si potrebbe costruire una funzione di log di sola aggiunta. A condizione che il resto del programma sia scritto in Joe-E, un revisore del codice può essere certo che le voci del registro possono essere solo aggiunte e non possono essere modificate o rimosse. Questa recensione è pratica perché richiede solo l'ispezione della Log classe e non richiede la revisione di nessun altro codice. Di conseguenza, la verifica di questa proprietà richiede solo un ragionamento locale sul codice di registrazione.


1

Nascondere le informazioni è una delle preoccupazioni principali di una buona progettazione del software. Dai un'occhiata ai documenti di Dave Parnas della fine degli anni '70. Fondamentalmente, se non puoi garantire che lo stato interno del tuo modulo sia coerente, non puoi garantire nulla sul suo comportamento. E l'unico modo per garantire il suo stato interno è mantenerlo privato e consentirne la modifica solo con i mezzi forniti.


1

Rendendo la protezione parte della lingua, ottieni qualcosa: ragionevole certezza.

Se faccio una variabile privata, ho una ragionevole garanzia che verrà toccata solo dal codice all'interno di quella classe o dichiarata esplicitamente amici di quella classe. L'ambito del codice che potrebbe ragionevolmente toccare quel valore è limitato ed esplicitamente definito.

Ora ci sono modi per aggirare la protezione sintattica? Assolutamente; la maggior parte delle lingue li ha. In C ++, puoi sempre trasmettere la classe a un altro tipo e cercare i suoi bit. In Java e C #, puoi rifletterti su di esso. E così via.

Tuttavia, farlo è difficile . È ovvio che stai facendo qualcosa che non dovresti fare. Non puoi farlo per caso (al di fuori delle scritture wild in C ++). Devi volentieri pensare: "Toccerò qualcosa che non mi è stato detto dal mio compilatore". Devi fare volontariamente qualcosa di irragionevole .

Senza la protezione sintattica, un programmatore può semplicemente rovinare accidentalmente le cose. Devi insegnare all'utente una convenzione e devono seguire quella convenzione ogni volta . In caso contrario, il mondo diventa molto pericoloso.

Senza protezione sintattica, l'onere è sulle persone sbagliate: le molte persone che usano la classe. Devono seguire la convenzione o si verificherà cattiveria non specificata. Scratch that: potrebbe verificarsi un male non specificato .

Non c'è niente di peggio di un'API in cui, se si fa la cosa sbagliata, tutto potrebbe funzionare comunque. Ciò fornisce una falsa rassicurazione all'utente che ha fatto la cosa giusta, che tutto va bene, ecc.

E che dire dei nuovi utenti in quella lingua? Non solo devono imparare e seguire la sintassi effettiva (imposta dal compilatore), ma ora devono seguire questa convenzione (applicata dai loro pari nella migliore delle ipotesi). E se non lo fanno, allora non può succedere niente di male. Cosa succede se un programmatore non capisce perché esiste la convenzione? Cosa succede quando dice "fanculo" e fa solo capolino ai tuoi privati? E cosa pensa se tutto continua a funzionare?

Pensa che la convenzione sia stupida. E non lo seguirà mai più. E dirà a tutti i suoi amici di non disturbare troppo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.