Existe algum propósito para declarar um init()
método para um tipo?
Não estou perguntando se devemos preferir init()
a um construtor ou como evitar a declaraçãoinit()
.
Estou perguntando se existe alguma justificativa por trás da declaração de um init()
método (ver quão comum é) ou se é um cheiro de código e deve ser evitado.
O init()
idioma é bastante comum, mas ainda não vi nenhum benefício real.
Estou falando de tipos que incentivam a inicialização por meio de um método:
class Demo {
public void init() {
//...
}
}
Quando isso será útil no código de produção?
Eu sinto que pode ser um cheiro de código, pois sugere que o construtor não inicializa totalmente o objeto, resultando em um objeto parcialmente criado. O objeto não deve existir se seu estado não estiver definido.
Isso me faz acreditar que pode fazer parte de algum tipo de técnica usada para acelerar a produção, no sentido de aplicativos corporativos. É a única razão lógica pela qual consigo pensar em ter esse idioma. Só não tenho certeza de como isso seria benéfico.
fonte
init()
classe derivada ou vice-versa?) Em caso afirmativo, é um exemplo de deixar a classe base executar um "pós-construtor" "que só pode ser executado após a construção da classe mais derivada. É um exemplo de inicialização multifásica.Respostas:
Sim, é um cheiro de código. Um cheiro de código não é algo que necessariamente sempre precise ser removido. É algo que faz você dar uma segunda olhada.
Aqui você tem um objeto em dois estados fundamentalmente diferentes: pré-inicialização e pós-inicialização. Esses estados têm responsabilidades diferentes, métodos diferentes que podem ser chamados e comportamento diferente. São efetivamente duas classes diferentes.
Se você criar fisicamente duas classes separadas, removerá estaticamente toda uma classe de possíveis bugs, ao custo de talvez fazer com que seu modelo não corresponda tanto ao "modelo do mundo real". Você costuma nomear o primeiro
Config
ouSetup
ou algo parecido.Portanto, da próxima vez, tente refatorar seus idiomas de construção-init em modelos de duas classes e veja como isso acontece para você.
fonte
this
o construtor é um cheiro de código e pode resultar em código sujeito a erros, e evitá-lo é recomendado, independentemente do domínio em que seu projeto se encaixa).Depende.
Um
init
método é um cheiro de código quando não é necessário separar a inicialização do objeto do construtor. Às vezes, há casos em que faz sentido separar essas etapas.Uma rápida pesquisa no Google me deu esse exemplo. Posso facilmente imaginar mais casos em que o código executado durante a alocação de objetos (o construtor) pode ser melhor separado da própria inicialização. Talvez você tenha um sistema nivelado e a alocação / construção ocorra no nível X, mas a inicialização apenas no nível Y, porque apenas Y pode fornecer os parâmetros necessários. Talvez o "init" seja caro e precise ser executado apenas para um subconjunto dos objetos alocados, e a determinação desse subconjunto só pode ser feita no nível Y. Ou você deseja substituir o método "init" (virtual) em um derivado classe que não pode ser feita com um construtor. Talvez o nível X forneça objetos alocados de uma árvore de herança, mas o nível Y não tenha conhecimento da derivação concreta, apenas sobre a interface comum (onde
init
talvez definido).Obviamente, para minha experiência, esses casos são apenas uma pequena porcentagem do caso padrão, onde toda inicialização pode ser feita diretamente no construtor e, sempre que você
init
vir um método separado , pode ser uma boa idéia questionar sua necessidade.fonte
init
método. No entanto, sempre que vir esse método, fique à vontade para questionar sua necessidade.init()
método, tenho certeza de que me beneficiaria de aprender sobre seu objetivo. Desculpem a minha ignorância, eu só estou surpreendido com o quão difícil de um tempo que estou tendo de encontrar um uso para ele, impedindo-me de considerá-la algo que deve ser evitadoMinha experiência se divide em dois grupos:
Na minha experiência pessoal, vi apenas algumas instâncias de (1), mas muitas outras instâncias de (2). Consequentemente, eu normalmente assumo que init () é um cheiro de código, mas nem sempre é esse o caso. Às vezes você simplesmente não consegue contornar isso.
Descobri que o uso do Padrão do Construtor geralmente pode ajudar a remover a necessidade / desejo de ter um init ().
fonte
init()
método a resolveria? Oinit()
método seria nem precisa parâmetros para aceitar as dependências, ou você teria que instanciar as dependências dentro doinit()
método, que você também poderia fazer com um construtor. Você poderia dar um exemplo?Um cenário típico quando um método Init é útil é quando você tem um arquivo de configuração que deseja alterar e que a alteração seja levada em consideração sem reiniciar o aplicativo. Obviamente, isso não significa que um método Init deva ser chamado separadamente de um construtor. Você pode chamar um método Init de um construtor e depois mais tarde quando / se os parâmetros de configuração mudarem.
Resumindo: quanto à maioria dos dilemas existentes, seja um cheiro de código ou não, depende da situação e das circunstâncias.
fonte
Config
?update
/reload
provavelmente seria mais descritivo para esse tipo de comportamento) para realmente registrar essas alterações . Nesse caso, essa notificação faria com que os valores da configuração fossem alterados internamente em seu aplicativo, o que eu acredito que poderia ser observado fazendo com que sua configuração fosse observável, notificando os observadores quando a configuração é solicitada a alterar um de seus valores. Ou estou entendendo mal o seu exemplo?Depende de como você os usa.
Eu uso esse padrão em linguagens de coleta de lixo como Java / C # quando não quero realocar um objeto na pilha (como quando estou criando um videogame e preciso manter o desempenho alto, os coletores de lixo diminuem o desempenho). Eu uso o construtor para fazer outras alocações de heap necessárias e
init
criar o estado útil básico antes de cada vez que eu quiser reutilizá-lo. Isso está relacionado ao conceito de conjuntos de objetos.Também é útil se você tiver vários construtores que compartilhem um subconjunto comum de instruções de inicialização, mas nesse caso
init
serão privados. Dessa forma, posso minimizar cada construtor o máximo possível, para que cada um contenha apenas instruções exclusivas e uma única chamadainit
para fazer o resto.Em geral, porém, é um cheiro de código.
fonte
reset()
método não seria mais descritivo para sua primeira declaração? Quanto ao segundo (muitos construtores), ter muitos construtores é um cheiro de código. Ele assume que o objeto tem vários propósitos / responsabilidades, sugerindo uma violação do SRP. Um objeto deve ter uma responsabilidade e o construtor deve definir as dependências necessárias para essa responsabilidade. Se você tiver vários construtores devido a valores opcionais, eles devem fazer o telescópio (que também é um cheiro de código, deve-se usar um construtor).string
lista de construtores de qualquer idioma , com várias opções. Para mim, geralmente são talvez três construtores no máximo, mas o subconjunto comum de instruções como inicialização faz sentido quando eles compartilham qualquer código, mas diferem de alguma forma.String
, isso pode ser resolvido dissociando a criação de strings. No final, aString
é aString
, e seu construtor deve aceitar apenas o necessário para que ele funcione conforme necessário. A maioria desses construtores é exposta para fins de conversão, que é o uso indevido de construtores. Os construtores não devem executar lógica, ou eles correm o risco de falha na inicialização, deixando você com um objeto inútil.init()
Os métodos podem fazer bastante sentido quando você possui objetos que precisam de recursos externos (como, por exemplo, uma conexão de rede) que são usados simultaneamente por outros objetos. Você pode não querer / precisar monopolizar o recurso durante a vida útil do objeto. Nessas situações, talvez você não queira alocar o recurso no construtor quando a alocação de recursos provavelmente falhar.Especialmente na programação incorporada, você deseja ter uma pegada de memória determinística, por isso é uma prática comum (boa?) Chamar seus construtores mais cedo, talvez até estáticos, e somente inicializar mais tarde quando certas condições forem atendidas.
Fora desses casos, acho que tudo deve entrar em um construtor.
fonte
init
Métodos totalmente condenadores é muito restritivo, IMHO.Geralmente, prefiro um construtor que recebe todos os argumentos necessários para uma instância funcional. Isso deixa claro todas as dependências desse objeto.
Por outro lado, uso uma estrutura de configuração simples que requer um construtor público sem parâmetros e interfaces para injetar dependências e valores de configuração. Depois disso, a estrutura de configuração chama o
init
método do objeto: agora você recebeu tudo o que tenho para você, execute as últimas etapas para se preparar para o trabalho. Mas observe: é a estrutura de configuração que chama automaticamente o método init, para que você não esqueça de chamá-lo.fonte
Não há cheiro de código se o método init () - é semanticamente incorporado no ciclo de vida do objeto.
Se você precisar chamar init () para colocar o objeto em um estado consistente, é um cheiro de código.
Existem várias razões técnicas para que essa estrutura exista:
fonte
O nome init às vezes pode ser opaco. Vamos pegar um carro e um motor. Para dar partida no carro (apenas ligar, ouvir rádio), você deseja verificar se todos os sistemas estão prontos para o uso.
Então você constrói um motor, uma porta, uma roda, etc. sua tela mostra motor = desligado.
Não há necessidade de começar a monitorar o motor etc., pois todos são caros. Então, quando você liga a chave para ligar, ligue para engine-> start. Começa a executar todos os processos caros.
Agora você vê engine = on. E o processo de ignição começa.
O carro não liga sem o motor disponível.
Você pode substituir o mecanismo pelo seu cálculo complexo. Como uma célula do Excel. Nem todas as células precisam estar ativas com todos os manipuladores de eventos o tempo todo. Quando você se concentra em uma célula, pode iniciá-la. Aumentando o desempenho dessa maneira.
fonte