Suponha que temos um método foo(String bar)
que opera apenas em strings que atendem a determinados critérios; por exemplo, ele deve estar em minúsculas, não deve estar vazio ou ter apenas espaço em branco e deve corresponder ao padrão [a-z0-9-_./@]+
. A documentação para o método afirma esses critérios.
O método deve rejeitar todo e qualquer desvio deste critério ou deve ser mais tolerante com alguns critérios? Por exemplo, se o método inicial for
public void foo(String bar) {
if (bar == null) {
throw new IllegalArgumentException("bar must not be null");
}
if (!bar.matches(BAR_PATTERN_STRING)) {
throw new IllegalArgumentException("bar must match pattern: " + BAR_PATTERN_STRING);
}
this.bar = bar;
}
E o segundo método de perdão é
public void foo(String bar) {
if (bar == null) {
throw new IllegalArgumentException("bar must not be null");
}
if (!bar.matches(BAR_PATTERN_STRING)) {
bar = bar.toLowerCase().trim().replaceAll(" ", "_");
if (!bar.matches(BAR_PATTERN_STRING) {
throw new IllegalArgumentException("bar must match pattern: " + BAR_PATTERN_STRING);
}
}
this.bar = bar;
}
A documentação deve ser alterada para indicar que será transformada e configurada com o valor transformado, se possível, ou o método deve ser o mais simples possível e rejeitar todos e quaisquer desvios? Nesse caso, bar
pode ser definido pelo usuário de um aplicativo.
O principal caso de uso para isso seria usuários acessando objetos de um repositório por um identificador de cadeia específico. Cada objeto no repositório deve ter uma sequência única para identificá-lo. Esses repositórios podiam armazenar os objetos de várias maneiras (servidor sql, json, xml, binário etc.) e, portanto, tentei identificar o menor denominador comum que corresponderia à maioria das convenções de nomenclatura.
foo
função estrita, rigorosa nos argumentos que aceita, e ter uma segunda função auxiliar que possa tentar "limpar" um argumento a ser usado foo
. Dessa forma, cada método tem menos a fazer por conta própria e eles podem ser gerenciados e integrados de maneira mais limpa. Se seguir esse caminho, provavelmente também seria útil afastar-se de um design pesado de exceção; você pode usar algo como isso Optional
e, em seguida, ter as funções que consomem foo
lançam exceções, se necessário.