Estou escrevendo um aplicativo e cheguei a este ponto:
private void SomeMethod()
{
if (Settings.GiveApples)
{
GiveApples();
}
if (Settings.GiveBananas)
{
GiveBananas();
}
}
private void GiveApples()
{
...
}
private void GiveBananas()
{
...
}
Isso parece bem direto. Existem algumas condições e, se forem verdadeiras, os métodos estão sendo chamados. No entanto, eu estava pensando, é melhor fazer assim:
private void SomeMethod()
{
GiveApples();
GiveBananas();
}
private void GiveApples()
{
if (!Settings.GiveApples)
{
return;
}
...
}
private void GiveBananas()
{
if (!Settings.GiveBananas)
{
return;
}
...
}
No segundo caso, cada um dos métodos se protege, portanto, mesmo se algum desses métodos GiveApples
ou GiveBananas
for chamado de fora SomeMethod
, eles serão executados apenas se tiverem o sinalizador correto em Configurações.
Isso é algo que eu realmente deveria considerar um problema?
No meu contexto atual, é muito improvável que esses dois métodos sejam chamados de fora desse método, mas ninguém pode garantir isso.
design
conditions
Nikola
fonte
fonte
Respostas:
Penso nos guardas como algo que o método deve obedecer. No seu exemplo, o método não deve fornecer maçãs se Settings.GiveApples for false.
Se for esse o caso, o guarda definitivamente pertence ao método. Isso evita que você o chame acidentalmente de outro ponto do seu aplicativo sem verificar primeiro os guardas.
Por outro lado, se as configurações se aplicarem apenas ao método de chamada, e outro método em outro lugar no seu código puder GiveApples, independentemente da configuração, não é um resguardo e provavelmente deve estar no código de chamada.
fonte
Coloque a proteção dentro do próprio método. O consumidor
GiveApples()
ouGiveBananas()
não deve ser responsável por gerenciar os guardas deGiveApples()
.Do ponto de vista do design, você
SomeMethod()
deve saber apenas que precisa de frutas e não deve se preocupar com o que seu aplicativo precisa fazer para obtê-lo. A abstração da recuperação de frutas torna-se infiltrada seSomeMethod()
for responsável por saber que existe um cenário global que permite a recuperação de determinadas frutas. Isso ocorre em cascata, se o mecanismo de proteção mudar, como agora todos os métodos que precisamGetApples()
ouGetBananas()
precisam ser refatorados separadamente para implementar essa nova proteção. Também é muito fácil tentar obter frutas sem essa verificação enquanto você escreve código.O que você deve considerar nesse cenário é como o aplicativo deve reagir quando o Settings não permite que o aplicativo dê frutos.
fonte
Geralmente, geralmente é uma boa ideia separar as responsabilidades de testar algo como configurações fornecidas externamente e o "código principal de negócios"
GiveApples
. Por outro lado, ter funções que agrupem o que pertence, também é uma boa idéia. Você pode realizar os dois objetivos refatorando seu código da seguinte maneira:Isso oferece uma chance melhor de refatorar o código
GiveApples
e / ouGiveBananas
para um local separado sem nenhuma dependência daSettings
classe. Isso é obviamente benéfico quando você deseja chamar esses métodos em um teste de unidade que não se importa com nenhumSettings
.No entanto, se sempre estiver errado no seu programa, sob qualquer circunstância, mesmo em um contexto de teste, chamar algo como
GiveApples
fora de um contexto ondeSettings.GiveApples
é verificado primeiro e você tiver a impressão de que apenas fornecer uma função comoGiveApples
sem aSettings
verificação está sujeita a erros , mantenha-se na variante em que você testaSettings.GiveApples
dentroGiveApples
.fonte