Eu chamaria a prática de "outra coisa explícita" a que você se refere como anti-padrão, pois obscurece o fato de que não há código de caso especial como outra coisa para o seu if.
A legibilidade / manutenção geralmente é aprimorada quando você não possui nada além de construções de fluxo de código necessárias e você as minimiza. Isso significa erros redundantes e ifs que adicionarão um escopo a uma função inteira dificultam o acompanhamento e a manutenção.
Digamos, por exemplo, que você tenha esta função:
public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
if (_validColors.Contains(oblogonToConfigure.Color))
{
oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
}
else
{
oblogonToConfigure.Color = _validColors[0];
oblogonToConfigure.ColorIndex = 0;
}
}
Agora, existe o requisito de que, durante a configuração, você também deve especificar o índice de tipo / tipo do oblogon, existem vários escopos nos quais alguém pode colocar esse código e obter um código inválido, ou seja,
public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
if (!_validOblogons.Contains(oblogonToConfigure.Type))
{
oblogonToConfigure.Type = _validOblogons[0];
oblogonToConfigure.TypeIndex = 0;
if (_validColors.Contains(oblogonToConfigure.Color))
{
oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
}
else
{
oblogonToConfigure.Color = _validColors[0];
oblogonToConfigure.ColorIndex = 0;
}
}
else
{
oblogonToConfigure.TypeIndex = _validOblogons.IndexOf(oblogonToConfigure.Type);
}
}
Compare isso se o código original foi escrito com construções mínimas de fluxo de controle necessárias e minimizadas.
public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
if (!_validColors.Contains(oblogonToConfigure.Color))
{
oblogonToConfigure.Color = _validColors[0];
}
oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
}
Agora seria muito mais difícil colocar acidentalmente algo no escopo errado ou acabar inchando os escopos, causando duplicação no crescimento e manutenção a longo prazo dessa função. Além disso, é óbvio quais são os possíveis fluxos através dessa função para que a legibilidade seja aprimorada.
Eu sei, o exemplo é um pouco artificial, mas eu já vi muitas vezes
SomeFunction()
{
if (isvalid)
{
/* ENTIRE FUNCTION */
}
/* Nothing should go here but something does on accident, and an invalid scenario is created. */
}
Então, formalizando essas regras sobre construções de controle-fluxo, acho que pode ajudar as pessoas a desenvolver a intuição necessária para sentir o cheiro de algo quando começarem a escrever código assim. Então eles vão começar a escrever ..
SomeFunction()
{
if (!isvalid)
{
/* Nothing should go here, and it's so small no one will likely accidentally put something here */
return;
}
/* ENTIRE FUNCTION */
}
else
parece falsa. Muitas vezes, simplesmente não há nada para colocar noelse
bloco, a menos que você se incline para trás.