web-dev-qa-db-fra.com

Qu'est-ce qu'un invariant de classe en Java?

J'ai googlé le sujet, mais à part Wikipedia je n'ai trouvé aucune autre documentation ou article utile.

Quelqu'un peut-il m'expliquer en termes simples ce que cela signifie ou me renvoyer à une documentation agréable et facile à comprendre?

82
Saurabh Kumar

Cela ne signifie rien en particulier en référence à Java.

Un invariant de classe est simplement une propriété qui est valable pour toutes les instances d'une classe, toujours, peu importe ce que fait le code.

Par exemple,

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

X a invariant de classe qu'il existe une propriété y et qu'elle n'est jamais null et qu'elle a une valeur de type Y.

class Counter {
  private int x;

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

ne parvient pas à maintenir deux invariants importants

  1. Ce count ne renvoie jamais une valeur négative en raison d'un possible débordement.
  2. Les appels à count augmentent strictement de façon monotone.

La classe modifiée conserve 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 à préserver l'invariant qui appelle à count toujours réussir normalement (violations TCB absentes) parce que count peut générer une exception ou se bloquer si un thread bloqué possède le moniteur du compteur.

Chaque langue avec des classes facilite le maintien de certains invariants de classe mais pas d'autres. Java ne fait pas exception:

  1. Les classes Java ont ou n'ont toujours pas de propriétés et de méthodes, ce qui facilite la maintenance des invariants d'interface.
  2. Les classes Java peuvent protéger leurs champs private. Les invariants qui reposent sur des données privées sont donc faciles à gérer.
  3. Les classes Java peuvent être finales, les invariants qui reposent sur l'absence de code violant un invariant en créant une sous-classe illicite peuvent être conservés.
  4. Java autorise null les valeurs à se faufiler de plusieurs façons. Il est donc difficile de conserver des invariants "a une valeur réelle".
  5. Java a des threads, ce qui signifie que les classes qui ne se synchronisent pas ont du mal à conserver les invariants qui reposent sur des opérations séquentielles dans un thread se déroulant simultanément.
  6. Java a des exceptions qui facilitent la maintenance d'invariants tels que "renvoie un résultat avec la propriété p ou ne renvoie aucun résultat", mais plus difficiles de conserver des invariants tels que "renvoie toujours un résultat".

† - Une externalité ou TCB violation est un événement qu'un concepteur de systèmes présume avec optimisme ne se produira pas.

En général, nous ne faisons que croire que le matériel de base fonctionne comme annoncé lorsque nous parlons de propriétés de langages de haut niveau construits sur ces langages. Nos arguments pris en charge par les invariants ne prennent pas en compte la possibilité de:

  • Un programmeur utilisant des points d'ancrage de débogage pour modifier des variables locales en tant que programme s'exécute de manière que le code ne peut pas.
  • Vos pairs n'utilisent pas la réflexion avec setAccessible pour modifier les tables de consultation private.
  • Loki modifie la physique, ce qui provoque la comparaison incorrecte de deux nombres entre votre processeur.

Pour certains systèmes, notre TCB peut ne comprendre que certaines parties du système. Par conséquent, nous ne pouvons pas supposer que

  • Un administrateur ou un démon privilégié ne tuera pas notre processus JVM,

mais on peut supposer que

  • Nous pouvons contrôler un système de fichiers transactionnel fiable.

Plus un système est de niveau supérieur, plus son TCB est grand, mais plus vous pouvez extraire d'éléments peu fiables de votre TCB, plus vos invariants sont susceptibles de tenir, et plus votre système sera fiable à long terme.

81
Mike Samuel

Invariant signifie quelque chose qui devrait rester fidèle à ses conditions, quels que soient les changements et ceux qui l'utilisent/le transforment. C'est-à-dire qu'une propriété d'une classe remplit ou satisfait toujours une condition même après avoir subi des transformations en utilisant des méthodes publiques. Ainsi, le client ou l'utilisateur de cette classe est assuré à propos de la classe et de sa propriété.

Par exemple,

  1. l'argument condition on function est que, il devrait toujours être> 0 (supérieur à zéro) ou ne devrait pas être null.
  2. la propriété minimum_account_balance d'une classe de compte déclare qu'elle ne peut pas être inférieure à 100. Toutes les fonctions publiques doivent donc respecter cette condition et garantir l'invariant de la classe.
  3. la dépendance basée sur des règles entre les variables, c'est-à-dire que la valeur d'une variable dépend d'une autre, donc si l'une d'elles change, certaines règles doivent être modifiées, l'autre doit également changer. Cette relation entre 2 variables doit être préservée. Si ce n'est pas le cas, l'invariant est violé.
16
aab10

Ce sont des faits qui doivent être vrais à propos d'une classe d'instance. Par exemple, si une classe a une propriété X et que l'invariant peut être X, il doit être supérieur à 0. À ma connaissance, il n'existe pas de méthode intégrée pour gérer les invariants. Vous devez donc rendre les propriétés privées et vous assurer que vos accesseurs appliquent la propriété d'invariance.

Des annotations sont disponibles pour vérifier les propriétés à l'aide de la réflexion et des intercepteurs. http://docs.Oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

9
Usman Ismail