Recentemente, encontrei a seguinte situação.
class A{
public:
void calculate(T inputs);
}
Em primeiro lugar, A
representa um objeto no mundo físico, que é um forte argumento para não dividir a classe. Agora, calculate()
acaba por ser uma função bastante longa e complicada. Eu percebo três estruturas possíveis para isso:
- escreva como uma parede de texto - vantagens - todas as informações estão em um só lugar
- escrever
private
funções utilitárias na classe e usá-las nocalculate
corpo da pessoa - desvantagens - o resto da classe não conhece / se importa / entende sobre esses métodos escreva
calculate
da seguinte maneira:void A::calculate(T inputs){ auto lambda1 = () [] {}; auto lambda2 = () [] {}; auto lambda3 = () [] {}; lambda1(inputs.first_logical_chunk); lambda2(inputs.second_logical_chunk); lambda3(inputs.third_logical_chunk); }
Isso pode ser considerado uma boa ou má prática? Essa abordagem revela algum problema? Em suma, devo considerar isso uma boa abordagem quando me encontrar novamente com a mesma situação?
EDITAR:
class A{
...
public:
// Reconfiguration of the algorithm.
void set_colour(double colour);
void set_density(double density);
void set_predelay(unsigned long microseconds);
void set_reverb_time(double reverb_time, double room_size);
void set_drywet(double left, double right);
void set_room_size(double value);;
private:
// Sub-model objects.
...
}
Todos esses métodos:
- obter um valor
- calcular alguns outros valores, sem usar state
- chame alguns dos "objetos de submodelo" para alterar seu estado.
Acontece que, exceto set_room_size()
, esses métodos simplesmente passam o valor solicitado para subobjetos. set_room_size()
, por outro lado, faz algumas telas de fórmulas obscuras e (2) faz meia tela de chamada de setters de subobjetos para aplicar os vários resultados obtidos. Portanto, eu separei a função em duas lambdas e as chamo no final da função. Se eu fosse capaz de dividi-lo em pedaços mais lógicos, eu teria isolado mais lambdas.
Independentemente disso, o objetivo da pergunta atual é determinar se esse modo de pensar deve persistir ou, na melhor das hipóteses, não agrega valor (legibilidade, capacidade de manutenção, capacidade de depuração etc.).
Firstly, A represents an object in the physical world, which is a strong argument for not splitting the class up.
CertamenteA
representa dados sobre um objeto que poderia existir no mundo físico. Você pode ter uma instânciaA
sem o objeto real e um objeto real sem uma instância deA
, portanto, tratá-los como se fossem um e o mesmo não faça sentido.calculate()
saberá sobre essas sub-funções.A
, isso levará um pouco ao extremo.A
representa um objeto no mundo físico, que é um forte argumento para não dividir a classe." Infelizmente, me disseram isso quando comecei a programar. Levei anos para perceber que é um monte de hóquei em cavalos. É uma terrível razão para agrupar as coisas. Não consigo articular quais são as boas razões para agrupar as coisas (pelo menos para minha satisfação), mas essa é uma que você deve descartar agora. No fim das contas, todo o "código bom" é que ele funciona corretamente, é relativamente fácil de entender e é relativamente fácil de mudar (ou seja, mudanças não têm efeitos colaterais estranhos).Respostas:
Não, esse geralmente não é um bom padrão
O que você está fazendo é dividir uma função em funções menores usando lambda. No entanto, existe uma ferramenta muito melhor para dividir funções: funções.
Os lambdas funcionam, como você viu, mas significam muito muito muito muito mais do que simplesmente dividir uma função em bits locais. Lambdas do:
No instante em que você introduz lambdas no mix, o próximo desenvolvedor a examinar o código deve carregar imediatamente todas essas regras mentalmente, preparando-se para ver como seu código funciona. Eles não sabem que você não vai usar toda essa funcionalidade. Isso é muito caro, comparado às alternativas.
É como usar uma enxada para fazer sua jardinagem. Você sabe que só o está usando para cavar pequenos orifícios para as flores deste ano, mas os vizinhos ficam nervosos.
Considere que tudo o que você está fazendo é agrupar seu código-fonte visualmente. O compilador realmente não se importa que você tenha curry coisas com lambdas. Na verdade, espero que o otimizador desfaça imediatamente tudo o que você fez quando compila. Você está puramente atendendo ao próximo leitor (obrigado por fazer isso, mesmo se discordarmos da metodologia! O código é lido com muito mais frequência do que está escrito!). Tudo o que você está fazendo é agrupar a funcionalidade.
// ------------------
entre cada parte.EDIT: Ao ver sua edição com código de exemplo, inclino-me para que a notação de comentário seja a mais limpa, com colchetes para impor os limites sugeridos pelos comentários. No entanto, se alguma funcionalidade foi reutilizável em outras funções, eu recomendaria o uso de funções.
fonte
count++
)calculate()
em{}
blocos e declarando dados compartilhados nocalculate()
escopo. Eu pensei que, vendo que as lambdas não capturam, um leitor não seria sobrecarregado pelo poder das lambdas.lambda
é injusta ou se você está forçando rudemente as pessoas a seguirem a estrita denotação, não é uma pergunta fácil de responder. De fato, pode ser totalmente aceitável você usarlambda
dessa maneira na sua empresa e totalmente inaceitável na minha empresa, e nenhum deles realmente precisa estar errado!lambda
, como afor_each
função. Consequentemente, quando vejo umlambda
que não se encaixa em um desses casos de problemas fáceis de detectar, a primeira suposição a que chego é que ele provavelmente será usado para programação funcional, porque não era necessário de outra forma. Para muitos desenvolvedores, a programação funcional é uma mentalidade completamente diferente da programação procedural ou OO.Eu acho que você fez uma suposição ruim:
Eu discordo disso. Por exemplo, se eu tivesse uma classe que representa um carro, eu definitivamente gostaria de dividi-la, porque certamente quero uma classe menor para representar os pneus.
Você deve dividir essa função em funções privadas menores. Se realmente parecer separado da outra parte da classe, isso pode ser um sinal de que a classe deve ser separada. Claro que é difícil dizer sem um exemplo explícito.
Eu realmente não vejo a vantagem de usar funções lambda nesse caso, porque realmente não torna o código mais limpo. Eles foram criados para ajudar na programação de estilos funcionais, mas não é isso.
O que você escreveu se assemelha um pouco aos objetos de função aninhada no estilo Javascript. O que é novamente um sinal de que eles pertencem firmemente juntos. Tem certeza de que não deve fazer uma aula separada para eles?
Para resumir, não acho que esse seja um bom padrão.
ATUALIZAR
Se você não encontrar nenhuma maneira de encapsular essa funcionalidade em uma classe significativa, poderá criar funções auxiliares com escopo no arquivo, que não são membros da sua classe. Afinal, este é C ++, o design do OO não é obrigatório.
fonte
A
(talvez até functor com todos os outros métodos privados)? Classe declarada e definida por dentrocalculate()
(isso se parece muito com o meu exemplo lambda). Como esclarecimento,calculate()
é um de uma família de métodos (calculate_1(), calculate_2()
etc.) dos quais todos são simples, apenas este é 2 telas de fórmulas.calculate()
muito mais longo que todos os outros métodos?