Che cos'è un invariante di classe?
Nella programmazione e nella progettazione orientata agli oggetti, un invariante di classe è un insieme di regole che possono essere utilizzate per definire se un'istanza di oggetto esiste in uno stato valido. Dal punto di vista del design, un invariante di classe è un insieme di confini tra i quali i dati all'interno di un oggetto devono cadere per essere considerati in uno stato adeguato e funzionale. Un invariante di classe può essere definito nella documentazione di progettazione o nei commenti del codice sorgente o, in alcuni linguaggi di programmazione, può essere implementato direttamente in codice computerizzabile. Un programma che utilizza invarianti e asserzioni codificate può far cessare l'esecuzione del programma o generare vari errori quando le condizioni invarianti non sono soddisfatte. A differenza del controllo degli errori standard, gli invarianti di classe vengono generalmente utilizzati solo allo scopo di garantire il funzionamento dell'implementazione interna di una classe e di solito non sono elencati nella documentazione pubblica o nelle interfacce di programmazione.
Da un livello molto semplice, un invariante di classe è essenzialmente una raccolta di asserzioni per una classe. Un'affermazione, sempre in termini semplici, è un'affermazione che controlla una parte dello stato della classe e deve essere valutata come vera affinché l'esecuzione del programma continui. Un esempio di un'asserzione è un'istruzione che assicura che un dato intero sia sempre compreso tra 1 e 10. Quando viene utilizzato un invariante di classe, le asserzioni vengono valutate per tutte le parti pertinenti dei dati detenute dall'oggetto, essenzialmente convalidando che tutti i dati nel l'oggetto rientra negli intervalli definiti.
In molti casi, l'utilizzo di un invariante di classe assomiglia fortemente al controllo degli errori standard, in cui le variabili vengono misurate per garantire che siano entro i limiti utilizzabili o che non siano nulle. La differenza tra l'utilizzo di invarianti di classe e il controllo degli errori standard, tuttavia, è che gli invarianti e le asserzioni vengono utilizzati principalmente per acquisire errori che non dovrebbero verificarsi a meno che non vi sia un difetto intrinseco nel codice. Un'altra differenza è che il controllo degli errori standard tende a comportare il recupero e le modifiche nel flusso di controllo del programma, mentre il risultato di un errore invariante dovrebbe essere la chiusura del programma. Il motivo per cui la maggior parte dei programmi termina quando un controllo invariante di classe fallisce perché l'oggetto si trova in uno stato compromesso e non è in grado, dal punto di vista della progettazione, di soddisfare i suoi presupposti e le condizioni post necessarie per aderire al suo contratto di progettazione.
Una delle proprietà di una invariante di classe nei linguaggi di programmazione orientati agli oggetti in cui sono implicitamente definiti è che l'invariante è un meccanismo ereditato da qualsiasi sottoclasse. Ciò impedisce a una sottoclasse di sovrascrivere eventuali controlli invarianti eseguiti nella classe padre. In definitiva, ciò significa che una sottoclasse non è in grado di violare il contratto di progettazione stabilito dalla superclasse, il che potrebbe causare risultati imprevedibili o errori di programma difficili da trovare.