Cela ne veut rien dire en particulier en référence à java.
Un invariant de classe est simplement une propriété qui s'applique à toutes les instances d'une classe, toujours, peu importe ce que fait un autre code.
Par exemple,
class X {
final Y y = new Y();
}
X a l'invariant de classe qu'il y a une y
propriété et ce n'est jamais null
et il a une valeur de type Y
.
class Counter {
private int x;
public int count() { return x++; }
}
ne parvient pas à maintenir deux invariants importants
- Cela
count
ne renvoie jamais une valeur négative en raison d'un éventuel dépassement inférieur.
- Ces appels
count
sont en augmentation strictement monotone.
La classe modifiée préserve ces deux invariants.
class Counter {
private int x;
public synchronized int count() {
if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); }
return x++;
}
}
mais ne parvient pas à conserver l'invariant qui appelle à count
toujours réussir normalement (absence de violations TCB † ) car il count
peut lever une exception ou bloquer si un thread bloqué possède le moniteur du compteur.
Chaque langage avec des classes facilite la gestion de certains invariants de classe mais pas d'autres. Java ne fait pas exception:
- Les classes Java ont systématiquement ou n'ont pas de propriétés et de méthodes, les invariants d'interface sont donc faciles à gérer.
- Les classes Java peuvent protéger leurs
private
champs, les invariants qui reposent sur des données privées sont donc faciles à gérer.
- Les classes Java peuvent être finales, donc les invariants qui reposent sur l'absence de code qui viole un invariant en créant une sous-classe malveillante peuvent être conservés.
- Java permet aux
null
valeurs de se faufiler de plusieurs façons, il est donc difficile de maintenir des invariants «a une valeur réelle».
- Java a des threads, ce qui signifie que les classes qui ne se synchronisent pas ont du mal à maintenir les invariants qui reposent sur des opérations séquentielles dans un thread se produisant ensemble.
- Java a des exceptions qui facilitent la gestion des invariants tels que «renvoie un résultat avec la propriété p ou ne retourne aucun résultat», mais il est plus difficile de maintenir des invariants tels que «renvoie toujours un résultat».
† - Une externalité ou une violation TCB est un événement dont un concepteur de systèmes suppose avec optimisme qu'il ne se produira pas.
En règle générale, nous sommes convaincus que le matériel de base fonctionne comme annoncé lorsque nous parlons des propriétés des langages de haut niveau construits sur eux, et nos arguments que les invariants tiennent ne prennent pas en compte la possibilité de:
- Un programmeur utilisant des hooks de débogage pour modifier les variables locales pendant qu'un programme s'exécute d'une manière que le code ne peut pas.
- Vos pairs n'utilisent pas la réflexion avec
setAccessible
pour modifier private
les tables de recherche.
- Loki modifie la physique, ce qui fait que votre processeur compare incorrectement deux nombres.
Pour certains systèmes, notre TCB peut n'inclure que des parties du système, nous ne pouvons donc pas supposer que
- Un administrateur ou un démon privilégié ne tuera pas notre processus JVM,
mais nous pourrions supposer que
- Nous pouvons vérifier un système de fichiers transactionnel fiable.
Plus un système est de niveau supérieur, plus son TCB est généralement grand, mais plus les choses que vous pouvez retirer de votre TCB sont peu fiables, plus vos invariants sont susceptibles de tenir et plus votre système sera fiable à long terme.