As soluções gerais para este problema são o tipo de segurança (para que os valores sejam válidos por construção) e o encapsulamento (para que os valores não possam ser invalidados após a construção). Se suas entradas e saídas tiverem tipos significativos, os construtores desses tipos poderão impor as propriedades desejadas. Se a validação for centralizada, você não precisará repeti-la.
Vamos falar em pseudocódigo por um momento. Como um exemplo planejado, considere uma função area(w, h)
que calcula a área de um retângulo. Se você digitar a função como:
int area(int w, int h)
Então não há garantia de que qualquer uma das invariantes seja válida:
-
w
eh
são comprimentos -
Sendo comprimentos, eles devem ser não negativos
-
O resultado é uma área
Para impor restrições de entrada, você sempre pode adicionar validação ao corpo da função:
int area(int w, int h) {
assert(w >= 0);
assert(h >= 0);
return w * h;
}
Isso não é apenas complicado, mas continua sendo responsabilidade do chamador validar o resultado. Se usarmos tipos que representam nossas unidades:
Area area(Length w, Length h) {
return w * h;
}
Então, ninguém pode nos dar um Volume
quando esperávamos um Length
e, como um comprimento não pode ser negativo, não precisamos verificar isso.
O PHP não impõe os tipos estaticamente, mas você pode impedir a construção de objetos inválidos lançando exceções de construtores que recebem entradas inválidas e usando objetos ou acessos imutáveis para evitar invalidação posterior.