La noción de invariante está fuertemente relacionada con los "efectos secundarios". Creo que fue promovido por el enfoque 'Design by Contract (DbC)' de Bertrand Meyer para el diseño de software.
DbC enriquece los tipos de datos abstractos (columna vertebral de clases) con 3 nociones importantes, condiciones previas, condiciones posteriores, invariantes . Se explica fácilmente cuando se hace referencia a los procedimientos, por lo que intentaré explicarlo en referencia con él:
Una condición previa representa la condición que los datos de entrada para un procedimiento deben respetar para poder llamar a ese procedimiento. Esta condición previa debe ser respetada y aplicada por el cliente de ese procedimiento en particular. Sin embargo, el diseñador del procedimiento puede defenderse de los clientes que no respetan la condición previa al afirmar esa condición como primeras líneas del procedimiento. Por ejemplo, tener un método double divide(double dividend, double divisor)
puede ser una condición previa divisor != 0
.
A postcondition representa la condición A en los datos de salida después del procedimiento retorna; el diseñador del procedimiento es totalmente responsable de respetar esta condición posterior siempre que se respete la condición previa; en un estilo de programación de defensa antes de regresar, se puede afirmar la condición posterior.
Una invariante puede considerarse como una precondición y una condición posterior, pero con una comprensión diferente de la condición previa y posterior a los conceptos anteriores. Un invariante básicamente dice que si la entrada tiene una condición particular cumplida antes de que se llame al procedimiento, entonces esa condición particular es válida después de que se llama al procedimiento. Por ejemplo, un invariante válido para un procedimiento boolean search(int term, int array[])
podría decir que el estado de array
antes de la llamada es el mismo que después de la llamada.
Hacer cumplir invariantes en los procedimientos (y no solo en los procedimientos) es una gran cosa, ya que reduce los efectos secundarios ; Esto es útil ya que los efectos secundarios son un gran mal en la programación. Un procedimiento particular podría cambiar el estado de los argumentos de entrada, o cambiar el estado de algunas variables globales, o depender de algunas variables globales; Esto puede conducir a situaciones desagradables en las que dos llamadas idénticas en el mismo procedimiento (con la misma entrada) pueden producir salidas diferentes. Esto lleva a conocer el historial de las llamadas y es muy difícil de depurar, especialmente en un contexto de subprocesos múltiples.