¿Qué es una clase invariante?

En la programación y el diseño de computadoras orientadas a objetos, una clase invariante es un conjunto de reglas que se pueden usar para definir si una instancia de objeto existe en un estado válido. Desde una perspectiva de diseño, es un conjunto de límites entre los cuales los datos dentro de un objeto deben caer para ser considerados en un estado funcional adecuado. Se puede definir en la documentación de diseño o en los comentarios del código fuente o, en algunos lenguajes de programación, se puede implementar directamente en un código informático procesable. Un programa que utiliza invariantes codificados y aserciones puede hacer que el programa deje de ejecutarse o arroje varios errores cuando no se cumplen las condiciones invariantes. A diferencia de la verificación de errores estándar, los invariantes de clase generalmente se usan solo con el propósito de garantizar que la implementación interna de una clase esté funcionando y, por lo general, no se enumeran en la documentación pública o en las interfaces de programación.

Desde un nivel muy básico, una clase invariante es esencialmente una colección de afirmaciones para una clase. Una aserción, nuevamente en términos simples, es una declaración que verifica una parte del estado de la clase y debe evaluarse como verdadera para que continúe la ejecución del programa. Un ejemplo de una aserción es una declaración que asegura que un entero dado esté siempre entre 1 y 10. Cuando se usa un invariante de clase, las aserciones se evalúan para todas las partes relevantes de los datos que posee el objeto, esencialmente validando que todos los datos en el objeto están dentro de los rangos definidos.

En muchos casos, el uso de una clase invariante se parece mucho a la verificación de errores estándar, en la que las variables se miden para garantizar que estén dentro de los límites utilizables o que no sean nulas. Sin embargo, la diferencia entre el uso de invariantes de clase y la verificación de errores estándar es que los invariantes y las afirmaciones se usan predominantemente para capturar errores que no deberían ocurrir a menos que exista una falla intrínseca en el código. Otra diferencia es que la verificación de errores estándar tiende a involucrar recuperación y cambios en el flujo de control del programa, mientras que el resultado de una falla invariante debería ser la terminación del programa. La razón por la que la mayoría de los programas terminan cuando falla una verificación invariante de clase es porque el objeto está en un estado comprometido y no puede, desde el punto de vista del diseño, cumplir con sus precondiciones y poscondiciones necesarias para adherirse a su contrato de diseño.

Una de las propiedades de una clase invariante en los lenguajes de programación orientados a objetos en los que están implícitamente definidos es que la invariante es un mecanismo heredado por cualquier subclases. Esto evita que una subclase anule las comprobaciones invariantes que se realizan en la clase principal. En última instancia, esto significa que una subclase no puede romper el contrato de diseño establecido por la superclase, lo que podría causar resultados impredecibles o errores de programa difíciles de encontrar.