2012-01-17 7 views
60

Ho cercato su Google l'argomento, ma oltre a Wikipedia non ho trovato ulteriore documentazione o articoli utili.Che cos'è un invariante di classe in java?

Qualcuno può spiegarmi in parole semplici cosa significa o mi fa riferimento ad una documentazione semplice e di facile comprensione?

+0

+1 per la domanda perché la pagina di Wikipedia ha un ottimo esempio di qualcosa che non sapevo di poter fare - ha anche degli esempi. La loro spiegazione è meglio di quanto potrei fare per te; è piuttosto semplice. – iandisme

+0

https://www.stanford.edu/~pgbovine/programming-with-rep-invariants.htm –

+0

Se sei interessato a invarianti w.r.t. Java, forse saresti interessato a [contratti per Java] (http://google-opensource.blogspot.com/2011/02/contracts-for-java.html). –

risposta

64

Non significa nulla in particolare in riferimento a java.

Un invariante di classe è semplicemente una proprietà che vale per tutte le istanze di una classe, sempre, non importa quale altro codice faccia.

Per esempio,

class X { 
    final Y y = new Y(); 
} 

X ha l'invariante di classe che ci sia una proprietà y e non è mai null ed ha un valore di tipo Y.

class Counter { 
    private int x; 

    public int count() { return x++; } 
} 

non riesce a mantenere due invarianti importanti

  1. Che count mai restituisce un valore negativo a causa di possibili underflow.
  2. Le chiamate a count aumentano in modo strettamente monotono.

La classe modificata conserva quei due invarianti.

class Counter { 
    private int x; 

    public synchronized int count() { 
    if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); } 
    return x++; 
    } 
} 

ma non riesce a conservare l'invariante che chiama count sempre riesce normalmente assenti (TCB violazioni ) perché count potrebbe un'eccezione o potrebbe bloccare se un thread stallo possiede monitor del contatore.

Ogni lingua con classi facilita il mantenimento di alcuni invarianti di classe ma non di altri. Java non fa eccezione:

  1. Le classi Java hanno o non hanno proprietà e metodi coerenti, quindi gli invarianti di interfaccia sono facili da mantenere.
  2. Le classi Java possono proteggere i loro campi private, quindi le invarianti che si basano su dati privati ​​sono facili da mantenere.
  3. Le classi Java possono essere definitive, quindi le invarianti che si basano sul fatto che non esiste un codice che violi un'invarianza creando una sottoclasse dannosa possono essere mantenute.
  4. Java consente di introdurre i valori null in molti modi, quindi è difficile mantenere invarianti "ha un valore reale".
  5. Java ha thread che significa che le classi che non si sincronizzano hanno problemi a mantenere invarianti che si basano su operazioni sequenziali in un thread che si verificano insieme.
  6. Java ha delle eccezioni che rendono facile mantenere invarianti come "restituisce un risultato con proprietà p o non restituisce alcun risultato" ma è più difficile mantenere invarianti come "restituisce sempre un risultato".

† - Un esternalità o TCB violazione è un evento che un progettista di sistemi assume ottimisticamente non accadrà.

In genere abbiamo appena fiducia che l'hardware di base funziona come pubblicizzato quando si parla di proprietà dei linguaggi di alto livello costruite su di loro, e le nostre argomentazioni che invarianti detengono non prendere in considerazione la possibilità di:

  • Un programmatore che utilizza i hook di debug per modificare le variabili locali mentre un programma viene eseguito in modi che il codice non può eseguire.
  • I colleghi non utilizzano la riflessione con setAccessible per modificare le tabelle di ricerca private.
  • Loki che modifica la fisica causando il confronto errato del processore tra due numeri.

Per alcuni sistemi nostro TCB potrebbe includere solo le parti del sistema, in modo da non potremmo supporre che

  • Un amministratore o un demone privilegiata non uccideranno il nostro processo di JVM,

ma possiamo supporre che

  • Possiamo controllare un file system transazionale affidabile.

Il più alto livello di un sistema, maggiore è la sua TCB è tipicamente, ma le cose più inaffidabili che si possono ottenere dalla vostra TCB, più è probabile che i vostri invarianti sono da tenere, e il più affidabile il sistema sarà a lungo termine.

+1

"quel' count' non restituisce mai lo stesso valore due volte "realmente considerato un invariante di classe ? – ruakh

+0

@ruakh, questa è una buona domanda. Non sono molto sicuro. Cose come la stabilità di hashCode (per ogni istanza i, i.hashCode() non cambia) sono spesso chiamate invarianti di classe che richiedono un ragionamento sui valori restituiti in precedenza, quindi sembra ragionevole affermare che "per ogni istanza i, i.count() non in (precedenti risultati di i.count()) "è un invariante di classe. –

+0

@ruakh Non è una cosa pura definizione? Se postulo una tale invarianza, perché no? Certamente può essere una garanzia interessante e importante (ad esempio per la generazione di ID univoci). Personalmente penso anche a qualcosa come "se solo il codice a thread singolo accede a questa classe, le seguenti proprietà rimarranno" è utile, ma non sono sicuro che sia possibile estendere la definizione in modo tale che debba essere mantenuta solo mentre alcuni le condizioni sono vere (E considerando la riflessione è praticamente impossibile garantire qualcosa di interessante altrimenti!) – Voo

8

Sono fatti che devono essere veri per una classe di istanza. Ad esempio, se una classe ha una proprietà X e una variabile invariante X deve essere maggiore di 0. Per mia conoscenza non esiste un metodo integrato per mantenere invarianti è necessario rendere private le proprietà e assicurarsi che i getter e setter applichino la proprietà di invarianza.

Sono disponibili annotazioni in grado di controllare le proprietà mediante la riflessione e gli intercettori. http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

7

Invariante significa qualcosa che dovrebbe attenersi alle sue condizioni, qualunque cosa cambi o chiunque la usi/la trasformi. Vale a dire, una proprietà di una classe soddisfa sempre o soddisfa alcune condizioni anche dopo aver attraversato trasformazioni utilizzando metodi pubblici. Quindi, il client o l'utente di questa classe è assicurato riguardo la classe e le sue proprietà.

Ad esempio,

  1. condizione in argomento della funzione è che, dovrebbe essere sempre> 0 (maggiore di zero) o non dovrebbe essere nullo.
  2. proprietà minimum_account_balance di uno stato di classe account, non può essere inferiore a 100. Quindi tutte le funzioni pubbliche devono rispettare questa condizione e garantire l'invarianza di classe.
  3. dipendenza basata su regole tra variabili, ovvero il valore di una variabile dipende da un altro, quindi se si cambia, utilizzando alcune regole di correzione, anche l'altro deve cambiare. Questa relazione tra 2 variabili deve essere preservata. In caso contrario, l'invariante viene violato.
Problemi correlati