Termo (ou “padrão”?) para “Fazer algo se ainda não foi feito” [fechado]

53

Parece bem básico, eu sei, mas recentemente um colega me disse que um método chamado startHttpServer é muito complicado de entender, porque ele só inicia o servidor se ainda não estiver em execução. Eu acho que tenho problemas quando respondo: "Sério? Eu venho fazendo isso há décadas - é um padrão comum na programação." Mais frequentemente do que eu gostaria de admitir, ele volta com alguma evidência documentada que mostra que toda a comunidade de programação está por trás de seu ponto de vista e eu acabo me sentindo envergonhada.

Pergunta : Existe um padrão de design documentado por trás do conceito de um método que é um não operacional se a ação necessária já estiver em vigor? Ou, se não for um padrão, tem um nome? E se não, há alguma razão para pensar que é muito complicado considerar escrever um método dessa maneira?

    
por John Calcote 27.08.2017 / 08:10
fonte

8 respostas

126

Como NickWilliams já disse : o conceito que o OP descreve é chamado idempotent (substantivo Idempotency ). É de fato uma prática comum, especialmente em APIs de alto nível.

MAS: Renomeie a função.

Em vez de startHttpServer , chame-o de makeSureHttpServerIsRunning ou ensureHttpServerIsRunning .

Quando uma função é chamada startHttpServer , os leitores esperam que ela inicie um servidor HTTP; quando chamado dez vezes seguidas, terei dez servidores em execução. Sua função não faz isso na maior parte do tempo. Além disso, o nome com "start" sugere que, se eu quiser apenas um servidor em execução, terei que acompanhar se a função já foi chamada ou não.

Quando uma função é chamada makeSureHttpServerIsRunning , presumo que ela fará as coisas necessárias para garantir que um servidor HTTP esteja em execução, provavelmente verificando se já está em execução e iniciando-o de outra forma. Eu também suponho que a função garante que o servidor esteja realmente em execução (iniciar um servidor pode envolver algum tempo em que ele ainda não esteja funcionando).

    
por 27.08.2017 / 09:45
fonte
32

Renomeie para EnsureServerRunning .

Completamente não ambíguo e claro que ele garante que esteja em execução (se não for) sem implicar em uma reinicialização, se for.

(Alternativa: StartServerIfNotRunning ?)

    
por 27.08.2017 / 13:26
fonte
28

Não é realmente um padrão de design, mas eu chamaria seu método idempotent . Há termo geralmente é usado para se referir a chamadas remotas, mas a descrição parece coincidir com o que você está fazendo.

Idempotent Methods. Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. (From W3.org)

O efeito colateral do servidor é que o servidor http é iniciado quando o método é chamado. Não vejo nada de errado com um método fazendo isso.

Se você precisar de um padrão de design, eu acho que você poderia expor o seu httpServer como um singleton que é iniciado quando inicializado.

    
por 27.08.2017 / 09:12
fonte
7

Como quem implementa essa ferramenta , startHttpServer , você deve tentar torná-la a mais simples, suave e perfeita para usar ...

A lógica da função

Tecnicamente, dividindo a lógica de startHttpServer em duas funções e chamando-as separadamente , tudo o que você faz é mover startHttpServer de idempotency no código chamando ambas as funções ... Além disso, a menos que você envolva a lógica em uma terceira função ( qual é o que faz startHttpServer em primeiro lugar), isso obriga você a escrever código não-relacionado, duplicando-o exponencialmente em todos os lugares em que você teria que chamar startHttpServer . Em suma, startHttpServer tem que chamar a função isHttpServerRunning .

Então, meu ponto é:

  • Implemente a função isHttpServerRunning porque isso pode ser necessário independentemente de qualquer maneira ...
  • Implemente startHttpServer fazendo com que use isHttpServerRunning para definir sua próxima ação de acordo ...

Ainda assim, você pode fazer com que startHttpServer retorne qualquer valor que o usuário desta função possa precisar, por exemplo:

  • 0 = > falha inicial do servidor
  • 1 = > sucesso inicial do servidor
  • 2 = > servidor foi iniciado já

A nomeação da função

Primeiro de tudo, qual é o objetivo principal do usuário? Para iniciar o servidor HTTP , certo?

Fundamentalmente, não há nenhum problema com a intenção de iniciar algo que já tenha sido iniciado, AKA 1*1=1 . Então, pelo menos para mim, chamá-lo de " ensureHttpServerIsRunning " parece não ser criticamente necessário, eu me importo mais com quanto tempo é natural e memorável o nome da função.

Agora, se você quiser saber como trabalhar detalhadamente a função sob a capa, há a documentação ou a fonte de código para isso, quero dizer, como para qualquer outra função da biblioteca / framework / API / etc ...

Você aprende a função uma vez enquanto escreve várias vezes ...

De qualquer forma, eu ficaria com startHttpServer , que é mais curto, mais simples e mais explícito que ensureHttpServerIsRunning .

    
por 27.08.2017 / 14:26
fonte
2

Suponho que seu colega quis dizer que startHttpServer está fazendo muito:

  • Verificando se o servidor já está em execução,
  • Iniciando o servidor, se necessário.

Essas são duas partes não relacionadas do código. Por exemplo, existe uma situação semelhante quando um aplicativo de desktop deve garantir que ele não esteja em execução quando iniciado; haverá uma parte do código que lida com instâncias de aplicativos (por exemplo, usando um mutex) e o código que iniciará o loop de mensagens do aplicativo.

Isso significa que você precisa ter não um, mas pelo menos dois métodos :

  • isHttpServerRunning: boolean
  • startHttpServer

O ponto de entrada do aplicativo chamará o primeiro método e o segundo, se o valor de retorno for false . Agora, todo método está fazendo uma coisa e é fácil de entender.

¹ Se a lógica necessária para saber se o servidor já está sendo executado é muito complexa, pode exigir separação adicional em vários métodos.

    
por 27.08.2017 / 08:53
fonte
2

Como você não especifica um idioma, em JavaScript, muitas bibliotecas têm uma função "uma vez" por exemplo Sublinhado . Então, se isso for familiar para você, chame-o de padrão "uma vez" e possivelmente renomeie seu método.

Eu mesmo, vindo mais de Java, os termos "cache" ou "avaliação preguiçosa" vêm à mente. "Idempotent" é tecnicamente correto e uma boa escolha, esp. se você tem um background mais funcional.

    
por 28.08.2017 / 18:02
fonte
-2

Eu prefiro startHttpServerIfNotIsRunning .

Desta forma, a condição já está claramente mencionada no nome do método. Ensure ou makeSure parece um pouco vago para mim, pois não é uma expressão técnica. Parece que não sabemos exatamente o que vai acontecer.

    
por 28.08.2017 / 10:24
fonte
-3

O que seu colega deveria ter dito é que você não tem nenhum negócio escrevendo esse método. Já foi escrito muitas vezes e escrito melhor do que você provavelmente vai escrever. Por exemplo: link link

Do ponto de vista da arquitetura, ter um pouco de código arbitrário gerenciando um servidor da Web é o resultado de pesadelos. A menos que o gerenciamento de serviços seja exclusivamente o que seu código faz. Mas eu estou supondo que você não escreveu monit (ou kubernetes ou ...).

    
por 28.08.2017 / 18:10
fonte