No momento, estou lutando com esse conceito de DRY (não se repita) na minha codificação. Estou criando essa função na qual temo que esteja se tornando muito complexo, mas estou tentando seguir o princípio DRY.
createTrajectoryFromPoint(A a,B b,C c,boolean doesSomething,boolean doesSomething2)
Eu disse que esta função usa 3 parâmetros de entrada e, em seguida, a função fará algo ligeiramente diferente, dadas as combinações booleanas doesSomething
e doesSomething2
. No entanto, o problema que estou tendo é que essa função está crescendo muito em complexidade a cada novo parâmetro booleano adicionado.
Portanto, minha pergunta é: é melhor ter várias funções diferentes que compartilham muito da mesma lógica (portanto, violando o princípio DRY) ou uma função que se comporta de maneira ligeiramente diferente, considerando vários parâmetros, mas tornando-a muito mais complexa (mas preservando SECO)?
createTrajectory...
funções públicas chamam?boolean
como um parâmetro suspeito na melhor das hipóteses.Respostas:
argumentos booleanos para acionar diferentes caminhos de código em uma única função / método é um terrível cheiro de código .
O que você está fazendo viola os princípios de acoplamento solto e alta coesão e responsabilidade única , que são muito mais importantes que o DRY em precedência.
Isso significa que as coisas devem depender de outras coisas somente quando for necessário ( acoplamento ) e que devem fazer uma coisa e apenas uma coisa (muito bem) ( coesão ).
Por sua própria omissão, isso é muito acoplado (todos os sinalizadores booleanos são um tipo de dependência de estado, que é uma das piores!) E possui muitas responsabilidades individuais misturadas (excessivamente complexas).
O que você está fazendo não está no espírito de DRY de qualquer maneira. DRY é mais sobre repetição (o que
R
significaREPEAT
). Evitar copiar e colar é sua forma mais básica. O que você está fazendo não está relacionado à repetição.Seu problema é que a decomposição do seu código não está no nível correto. Se você acha que terá código duplicado, essa deve ser sua própria função / método parametrizado apropriado, não copiar e colar, e os outros devem ser nomeados descritivamente e delegados à função / método principal.
fonte
O fato de você estar passando booleanos para fazer a função fazer coisas diferentes é uma violação do Princípio da Responsabilidade Única. Uma função deve fazer uma coisa. Deve fazer apenas uma coisa e deve fazê-lo bem.
Parece que você precisa dividi-lo em várias funções menores com nomes descritivos, separando os caminhos de código correspondentes aos valores desses booleanos.
Depois de fazer isso, você deve procurar por código comum nas funções resultantes e fatorá-lo em suas próprias funções. Dependendo de quão complexa é essa coisa, você pode até considerar uma classe ou duas.
Obviamente, isso pressupõe que você esteja usando um sistema de controle de versão e que tenha um bom conjunto de testes, para poder refatorar sem medo de quebrar alguma coisa.
fonte
Por que você não cria outra função contendo toda a lógica de sua função antes de decidir fazer algo ou algo2 e, em seguida, possui três funções como:
E agora, passando três tipos de parâmetros iguais para três funções diferentes, você se repetirá novamente, portanto, você deve definir uma estrutura ou classe contendo A, B, C.
Como alternativa, você pode criar uma classe contendo os parâmetros A, B, C e uma lista de operações a serem realizadas. Adicione quais operações (algo, algo2) você deseja que aconteça com esses parâmetros (A, B, C) registrando operações com o objeto. Então, tenha um método para chamar todas as operações registradas no seu objeto.
fonte
O DRY pode ser levado longe demais, é melhor usar o princípio de responsabilidade única (SRP) em conjunto com o DRY. Adicionar sinalizadores bool a uma função para fazer com que versões ligeiramente diferentes do mesmo código possam ser um sinal de que você está fazendo muito com uma função. Nesse caso, eu sugeriria a criação de uma função separada para cada caso que seus sinalizadores representem; quando você escrever cada função, será bastante aparente se houver uma seção comum que possa ser movida para uma função privada sem passar todos os sinalizadores. , se não houver uma seção aparente do código, você realmente não está se repetindo, você tem vários casos diferentes, mas semelhantes.
fonte
Geralmente, passo por várias etapas com esse problema, parando quando não consigo descobrir como ir além.
Primeiro, faça o que você fez. Vá duro com o DRY. Se você não acabar com uma grande bagunça peluda, estará pronto. Se, como no seu caso, você não tiver um código duplicado, mas cada valor booleano tiver seu valor verificado em 20 locais diferentes, vá para a próxima etapa.
Segundo, divida o código em blocos. Os booleanos são referenciados apenas uma vez (bem, talvez duas vezes) para direcionar a execução para o bloco correto. Com dois booleanos, você acaba com quatro blocos. Cada bloco é quase idêntico. DRY se foi. Não faça de cada bloco um método separado. Isso seria mais elegante, mas colocar todo o código em um método torna mais fácil, ou até possível, para qualquer pessoa que faz manutenção, ver que precisa fazer cada alteração em quatro locais. Com código bem organizado e um monitor alto, as diferenças e os erros serão quase óbvios. Agora você tem código de manutenção e ele será executado mais rapidamente do que a bagunça emaranhada original.
Terceiro, tente pegar linhas de código duplicadas de cada bloco e transformá-las em métodos simples e agradáveis. Às vezes você não pode fazer nada. Às vezes você não pode fazer muito. Mas tudo que você faz leva você de volta ao DRY e torna o código um pouco mais fácil de seguir e mais seguro de manter. Idealmente, seu método original pode acabar sem código duplicado. Nesse ponto, você pode dividi-lo em vários métodos sem os parâmetros booleanos ou não. A conveniência do código de chamada é agora a principal preocupação.
Eu adicionei minha resposta ao grande número já aqui por causa do segundo passo. Eu odeio código duplicado, mas se é a única maneira inteligível de resolver um problema, faça-o de forma que alguém saiba rapidamente o que você está fazendo. Use vários blocos e apenas um método. Torne os blocos o mais idênticos possíveis em nomes, espaçamento, alinhamentos, ... tudo. As diferenças devem saltar para o leitor. Pode tornar óbvio como reescrevê-lo de uma maneira SECA e, se não, mantê-lo será razoavelmente simples.
fonte
Uma abordagem alternativa é substituir os parâmetros booleanos pelos parâmetros da interface, pelo código para manipular os diferentes valores booleanos refatorados nas implementações da interface. Então você teria
onde você tem implementações de IX e IY que representam os diferentes valores para os booleanos. No corpo da função, onde quer que você tenha
você substitui-o por uma chamada para um método definido no IX, pelas implementações que contêm os blocos de código omitidos.
fonte