Eu tenho alguns dados brutos que preciso fazer muitas coisas para (mudar, girar, escalar ao longo de determinado eixo, girar para uma posição final) e não tenho certeza de qual a melhor maneira de fazer isso para manter a legibilidade do código. Por um lado, posso criar um método único com muitos parâmetros (10 ou mais) para fazer o que preciso, mas esse é um pesadelo de leitura de código. Por outro lado, eu poderia criar vários métodos com 1 a 3 parâmetros cada, mas esses métodos precisariam ser chamados em uma ordem muito específica para obter o resultado correto. Eu li que é melhor que os métodos façam uma coisa e façam bem, mas parece que existem muitos métodos que precisam ser chamados para abrir o código para erros difíceis de encontrar.
Existe um paradigma de programação que eu poderia usar para minimizar erros e facilitar a leitura do código?
fonte
Respostas:
Cuidado com o acoplamento temporal . No entanto, isso nem sempre é um problema.
Se você deve executar as etapas em ordem, segue-se que a etapa 1 produz algum objeto necessário para a etapa 2 (por exemplo, um fluxo de arquivos ou outra estrutura de dados). Isso por si só exige que a segunda função deve ser chamado após a primeira, nem sequer é possível chamá-los na ordem errada acidentalmente.
Ao dividir sua funcionalidade em pedaços pequenos, cada parte fica mais fácil de entender e definitivamente mais fácil de testar isoladamente. Se você tem uma enorme função de 100 linhas e algo no meio do intervalo, como o seu teste falho diz o que está errado? Se um dos seus métodos de cinco linhas for interrompido, seu teste de unidade com falha o direciona imediatamente para o único código que precisa de atenção.
É assim que o código complexo deve parecer:
A qualquer momento durante o processo de conversão de dados brutos em um widget finalizado, cada função retorna algo exigido pela próxima etapa do processo. Não se pode formar uma liga a partir de escória, deve-se fundi-la (purificá-la) primeiro. Não se pode criar um widget sem a permissão adequada (por exemplo, aço) como entrada.
Os detalhes específicos de cada etapa estão contidos em funções individuais que podem ser testadas: em vez de testar a unidade todo o processo de mineração de rochas e criar widgets, teste cada etapa específica. Agora você tem uma maneira fácil de garantir que, se o processo "criar widget" falhar, você poderá restringir o motivo específico.
Além dos benefícios de testar e provar a correção, escrever código dessa maneira é muito mais fácil de ler. Ninguém pode entender uma lista enorme de parâmetros . Divida-o em pedaços pequenos e mostre o que cada pedacinho significa: isso é ótimo .
fonte
O argumento "deve ser executado em ordem" é discutível, já que praticamente todo o seu código deve ser executado na ordem correta. Afinal, você não pode gravar em um arquivo, abri-lo e fechá-lo, pode?
Você deve se concentrar no que torna seu código o mais sustentável. Isso geralmente significa funções de escrita pequenas e fáceis de entender. Cada função deve ter um único objetivo e não ter efeitos colaterais imprevistos.
fonte
Eu criaria um » ImageProcesssor « (ou qualquer outro nome adequado ao seu projeto) e um objeto de configuração ProcessConfiguration , que contém todos os parâmetros necessários.
Dentro do processador de imagem, você encapsula todo o processo por trás de um método
process()
Este método chama os métodos de transformação na ordem correta
shift()
,rotate()
. Cada método obtém parâmetros apropriados do ProcessConfiguration passado .Eu usei interfaces fluidas
que permite a inicialização bacana (como visto acima).
A vantagem óbvia, encapsulando os parâmetros necessários em um objeto. Suas assinaturas de método ficam legíveis:
private void shift(Image i, ProcessConfiguration c)
Trata-se de mudar uma imagem e os parâmetros detalhados são de alguma forma configurados .
Como alternativa, você pode criar um ProcessingPipeline :
Uma chamada de método para um método
processImage
instanciaria esse pipeline e tornaria transparente o que e em que ordem é feita: shift , rotatefonte
Você já pensou em usar algum tipo de curry ? Imagine que você tem uma classe
Processee
e uma classeProcessor
:Agora você pode substituir a classe
Processor
por duas classesProcessor1
eProcessor2
:Você pode chamar as operações na ordem correta usando:
Você pode aplicar esse padrão várias vezes se tiver mais de dois parâmetros. Você também pode agrupar os argumentos como quiser, ou seja, não é necessário que cada
process
método use exatamente um argumento.fonte