A origem de "um método deve retornar um valor ou ter efeitos colaterais, mas não ambos"


12

Li uma vez que um método deveria ter um valor de retorno (e ser referencialmente transparente) ou ter efeitos colaterais, mas não ambos. Não consigo encontrar referências a esta regra, mas quero aprender mais sobre ela.

Qual é a origem deste conselho? De que pessoa ou comunidade surgiu?

Crédito extra: qual é o benefício reivindicado de seguir este conselho?


1
@gnat Sim, é principalmente sobre história. Eu temia que a parte extra do crédito fosse subjetiva demais para ser independente e que a história tivesse uma chance maior de escapar do fechamento. Vou adicionar a tag.
Wayne Conrad

algumas das respostas que me fazem pensar me perguntam sobre o benefício reivindicado por um autor deste conselho ou uma lista de todos os benefícios possíveis de reivindicar?
Gnat

@gnat Eu pergunto sobre o benefício reivindicado pelo autor (mais uma vez, temendo o fechamento), mas com certeza não me importo com os motivos da pilha - eles estão respondendo à pergunta que eu realmente queria fazer. Se eu removesse "reivindicado" da minha pergunta, colocando as respostas acumuladas no tópico, isso levaria a pergunta muito longe no subjetivo?
Wayne Conrad

É provável que as "razões de empilhamento" levem a questão a ser encerrada como muito ampla . Se você preferir "ficar do lado aberto", eu acho que seria mais seguro para reduzi-lo a benefício que foi reivindicado pelo autor
mosquito

Um benefício é que, se você é pago por volume de código, isso produz extra. "doSomething; GetResultOfSomething; HandleErrorsFromSomething;"
ღ uі

Respostas:


13

Segundo Greg Young, essa idéia se originou da separação de Bertrand Meyer : Command-Query .

Ele afirma que todo método deve ser um comando que executa uma ação ou uma consulta que retorna dados ao chamador, mas não os dois. Em outras palavras, fazer uma pergunta não deve alterar a resposta . 1 Mais formalmente, os métodos devem retornar um valor apenas se forem referencialmente transparentes e, portanto, não apresentarem efeitos colaterais.

1: Eiffel: um idioma para a engenharia de software slide 43-48

No Design Orientado a Domínio, isso é semelhante à Separação / Segregação de Leitura de Comando-Consulta (CQRS), conforme nomeado por Greg Young.

Greg Young levou a idéia do CQS de Bertrand para nomear o CQRS, como mencionado por Martin Fowler neste artigo do CQRS

Benefícios

  • A parte Read (Query) pode ser dimensionada / aprimorada de forma diferente da parte Write (comando). Separar os dois impediria que se atrapalhassem quando a otimização / desempenho fosse essencial.

Leia o artigo no link Martin Fowler para obter mais informações.


1
Naturalmente, em muitas situações, gerar um resultado útil e fazer algumas modificações ao mesmo tempo não é mais caro do que fazer o mais difícil dos dois separadamente.
Deduplicator

1
@Duplicador Um exemplo clichê sendo InterlockedCompareExchange?
ღ uі

1
Porém, esse conselho obviamente não se aplica quando o retorno é sobre algumas informações sobre o que foi feito no comando - um método para remover linhas de um conjunto de dados pode praticamente mudar o estado do conjunto de dados, removendo as linhas indicadas de acordo com um determinado critério e em seguida, retorne o número de linhas removidas ou mesmo uma lista com as referidas linhas.
T. Sar

4

Não sei de onde vem, mas é um bom conselho e é bastante simples de entender.

Qualquer programa elaborado com cuidado será dividido em várias partes, combinadas e compostas de várias maneiras. Quanto mais difícil for o raciocínio sobre o que qualquer parte em particular faz, mais difícil será garantir que seu programa reaja de maneira previsível.

Isolar as partes que produzem efeitos colaterais facilita o raciocínio, o teste e a depuração do restante. Reduzir o número de efeitos colaterais em cada parte que gera um efeito colateral facilitará o trabalho da parte da mesma maneira.

Se você decompô-lo ainda mais, um valor de retorno é um efeito. Efeitos colaterais são um efeito. Uma função deve produzir apenas 1 efeito (se possível) porque, quanto maior o número de entradas e efeitos que uma função tiver, maior será a dificuldade de raciocinar sobre o que realmente faz.


este doen't mesmo tentar resolver a pergunta, consulte Como responder
mosquito

@gnat minha pergunta veio em duas partes: A questão principal ( "quem"), eo crédito extra ( "por que) não este endereço a parte extra de crédito.?
Wayne Conrad

de acordo com minha leitura (" benefício reivindicado "), espera-se que parte da proposta seja proposta pelo autor da citação. A pergunta não parece estar solicitando uma lista de todos os benefícios possíveis #
4410

2
@gnat Entendi a pergunta como uma tentativa de entender esse conselho, tanto a razão por trás dele quanto o contexto em que ele foi dado. Não creio que seja inapropriado abordar apenas parte da questão.
Morgen

1

Crédito extra: Qual é o benefício originalmente reivindicado de seguir este conselho?

Um dos benefícios de separar o valor de retorno dos efeitos colaterais é que ele remove um problema em potencial que pode ser causado pela avaliação de curto-circuito .

bool FooWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

bool BarWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

void BadShortCircuitEvaluation()
{
    // the programmer's intent is to have side effects of both functions
    if (FooWithSideEffect() && BarWithSideEffect() ) {
        // do something
    }

    // in case FooWithSideEffect() returns true, 
    // then BarWithSideEffect() is not called at all
    // because of short-circuit evaluation
}

este é um benefício reivindicado pelo autor do conselho ?
Gnat

@gnat Misturei histórico e prático, receio.
Nick Alexeev

1
o comentário e o código não coincidem, BarWithSideEffects não é chamado se FooWithSideEffects retornar false
jk.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.