Parece bastante básico, eu sei, mas recentemente um colega me disse que um método chamado startHttpServer
é muito complicado de entender porque só inicia o servidor se ele ainda não estiver em execução. Percebo que tenho problemas quando respondo: "Sério? Faço isso há décadas - é um padrão comum na programação". Mais frequentemente do que gostaria de admitir, ele volta com algumas evidências documentadas que mostram que toda a comunidade de programação está por trás de seu ponto de vista e acabo me sentindo tímido.
Pergunta : Existe um padrão de design documentado por trás do conceito de um método que não é operacional se a ação necessária já estiver em vigor? Ou, se não for um padrão, também tem um nome? E se não, existe alguma razão para pensar que é muito complicado considerar escrever um método dessa maneira?
fonte
startHttpServer
) e sim, o termo "idempotente" se aplica aqui bem.Respostas:
Como NickWilliams já disse : o conceito que o OP descreve é chamado de idempotente (substantivo Idempotência ). É de fato uma prática comum, especialmente em APIs de alto nível.
MAS: Renomeie a função.
Em vez de
startHttpServer
chamá-lomakeSureHttpServerIsRunning
ouensureHttpServerIsRunning
.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 maioria das vezes. Além disso, o nome com "start" sugere que, se eu quiser apenas um servidor em execução, precisarei 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. Suponho também que a função verifique se o servidor está realmente em execução (iniciar um servidor pode envolver algum tempo em que ainda não está em execução).fonte
Renomeie para
EnsureServerRunning
.Completamente inequívoco e é claro que garante que esteja em execução (se não estiver) sem implicar uma reinicialização, se estiver.
(Alternativa
StartServerIfNotRunning
:?)fonte
Não é realmente um padrão de design, mas eu chamaria seu método de idempotente . Geralmente, o termo é usado para se referir a chamadas remotas, mas a descrição parece corresponder ao que você está fazendo.
O efeito colateral do servidor aqui é que o servidor http é iniciado assim que o método é chamado. Não vejo nada de errado em um método fazer isso.
Se você precisar de um padrão de design, acho que você pode expor seu httpServer como um singleton que é iniciado quando inicializado.
fonte
Como aquele que implementa essa ferramenta ,
startHttpServer
você deve tentar torná-la a mais simples, suave e perfeita de usar ...A lógica da função
Tecnicamente, dividindo
startHttpServer
a lógica em 2 funções e chamando-as separadamente , tudo o que você faz é moverstartHttpServer
a idempotência para o código chamando as duas funções ... Além disso, a menos que você envolva a lógica em uma terceira função (que é o que fazstartHttpServer
em primeiro lugar), isso obriga a escrever código não-SECADO, duplicando-o exponencialmente em qualquer lugar que você precise chamarstartHttpServer
. Em suma,startHttpServer
tem que se chamar deisHttpServerRunning
função.Então, meu ponto é:
isHttpServerRunning
função porque isso pode ser necessário independentemente, de qualquer maneira ...startHttpServer
o usoisHttpServerRunning
para definir sua próxima ação de acordo ...Ainda assim, você pode
startHttpServer
retornar qualquer valor que o usuário dessa função possa precisar, por exemplo:0
=> falha na inicialização do servidor1
=> servidor iniciando com sucesso2
=> servidor já foi iniciadoA 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á problema pretendendo iniciar algo que já foi iniciado, também conhecido como AKA
1*1=1
. Então, pelo menos para mim, chamá-lo "ensureHttpServerIsRunning
" não parece ser criticamente necessário, eu me importaria mais com quanto tempo, natural e memorável é o nome da função.Agora, se você quiser saber como trabalhar em detalhes a função sob o capô, existe 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 a escreve várias vezes ...
Enfim, eu continuaria com o
startHttpServer
que é mais curto, mais simples e mais explícito do queensureHttpServerIsRunning
.fonte
Suponho que seu colega quis dizer que
startHttpServer
está fazendo muito: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 ainda não esteja sendo executado quando iniciado; haverá uma parte do código que manipula 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, em seguida, 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á em execução é muito complexa, pode ser necessária uma separação adicional em vários métodos.
fonte
startHttpServer
for chamado mais de um lugar no código? Várias linhas semelhantes devem ser copiadas e coladas em todos os lugares? Isso deve ser feito com todas as funções? Em breve, o programa será de tamanho infinito.startHttpServer
método será aproximadamenteif (isHttpServerRunning()){ return; }
. Você está afirmando uma regra de negócios que "não é válido iniciar o servidor http, se já estiver em execução", mas depois é responsabilidade de outra pessoa impor essa regra. Ad-hoc e repetidamente em todos os locais para onde eles possam ligarstartHttpServer
.Como você não especifica um idioma, em JavaScript, muitas bibliotecas têm uma função "única", por exemplo, Sublinhado . Portanto, se isso lhe for familiar, chame-o de "uma vez" e renomeie seu método.
Eu mesmo, vindo mais do Java, os termos "armazenamento em cache" ou "avaliação lenta" vêm à mente. "Idempotente" é tecnicamente correto e uma boa escolha, esp. se você tiver um fundo mais funcional.
fonte
restartHttpServer()
método raramente usado . Mas apenas parando - qual é o caso de uso aí? Você gosta de falhas esporádicas de conexão? :-)ensureRunning()
? :-) Quanto ao administrador pará-lo, ter esse outro código reiniciando constantemente enquanto o administrador está tentando modificar ou consertar algo seria incrivelmente irritante e errado. Deixe o administrador reiniciá-lo, não o código.Eu preferiria
startHttpServerIfNotIsRunning
.Dessa forma, a condição já está claramente mencionada no nome do método.
Ensure
oumakeSure
parece um pouco vago para mim, pois não é uma expressão técnica. Parece que não sabemos exatamente o que vai acontecer.fonte
Ensure
significa. Ainda não gosto desta palavra para uma expressão técnica.Ensure
é algo humano. Um sistema não pode garantir nada, apenas fará o que deve fazer.O que seu colega deveria ter lhe dito é que você não tem negócios escrevendo esse método. Já foi escrito muitas vezes e melhor do que você provavelmente escreverá. Por exemplo: http://docs.ansible.com/ansible/latest/systemd_module.html https://docs.saltstack.com/en/latest/ref/states/all/salt.states.service.html
De uma perspectiva arquitetônica, ter um pouco de código arbitrário gerenciando um servidor Web é coisa de pesadelo. A menos que gerenciar serviços seja exclusivamente o que seu código faz. Mas acho que você não escreveu monit (ou kubernetes ou ...).
fonte
startServer
função ou similar é algo incomum . Isso não significa que você escreverá os detalhes de baixo nível.