Pergunta

Aqui é um problema que eu tenho lutado com desde que eu comecei a aprender programação orientada a objetos: como se deve implementar um logger em código OOP "adequada"

Por isso, quero dizer um objeto que tem um método que queremos todos os outros objetos no código para ser capaz de acesso; este método seria a saída para console / arquivo / whatever, que usaríamos para registro -., portanto, este objeto seria o objeto logger

Nós não queremos estabelecer o objeto logger como uma variável global, porque as variáveis ??globais são ruins, certo? Mas também não quero ter a passar o objeto logger nos parâmetros de cada método único que chamamos em cada objeto.

Na faculdade, quando eu trouxe este tema com o professor, ele não poderia realmente me dar uma resposta. Eu percebo que há realmente pacotes (por exemplo, Java) que pode implementar essa funcionalidade. O que estou em última análise, procurando, porém, é o conhecimento de como fazer corretamente e da forma OOP implementar isso mesmo.

Foi útil?

Solução

Você do queremos estabelecer o logger como uma variável global, porque as variáveis ??globais são não ruim. Pelo menos, eles não são inerentemente mau. Um logger é um grande exemplo da boa utilização de um objeto globalmente acessível. Leia sobre o padrão de design Singleton se você quiser obter mais informações.

Outras dicas

Existem algumas soluções muito bem pensado. Alguns envolvem ignorando OO e usando outro mecanismo (AOP).

Logging realmente não se presta muito bem para OO (que é bom, nem tudo faz). Se você tem que implementá-lo, sugiro apenas instanciar "Log" no topo de cada classe:

log final privado = new Log (this);

e todas as suas chamadas de registro são, então trivial: log.print ( "Hey");

O que o torna muito mais fácil de usar do que um singleton.

Tenha sua figura logger o que classe que você está passando e usar isso para anotar o log. Desde então você tem uma instância de log, você pode fazer coisas como:

log.addTag ( "Bill");

E log pode adicionar a conta tag para cada entrada para que você possa implementar melhor filtragem para sua exibição.

log4j e motosserra são uma saída perfeita da solução caixa embora - se você não está apenas sendo acadêmico, use aqueles

.

Um logger globalmente acessível é uma dor para testes. Se você precisa de um recurso de registro "centralizado" criá-lo na inicialização programa e injetá-lo nas classes / métodos que logging necessidade. Como você testar métodos que usar algo como isto:

public class MyLogger 
{
    public static void Log(String Message) {}
}

Como você substituí-lo com um mock?

Melhor:

public interface ILog 
{
    void Log(String message);
}

public class MyLog : ILog 
{
    public void Log(String message) {}
}

Eu sempre usei o padrão Singleton para implementar um objeto de registro.

Você pode olhar para o padrão Singleton.

Criar a logger como uma classe Singleton e depois acessá-lo usando um método estático.

Eu acho que você deve usar AOP (programação orientada a aspectos) para isso, em vez de OOP.

Na prática um método singleton / global funciona bem, na minha opinião. De preferência, a coisa global é apenas um quadro para o qual você pode conectar diferentes ouvintes (observador padrão), por exemplo, um para a saída do console, um para a saída de banco de dados, um para a saída do Windows EventLog, etc.

Tenha cuidado para que superdimensionar, acho que, na prática uma única classe com apenas métodos globais podem trabalhar muito bem.

Ou você pode usar a infra-estrutura do quadro especial que você trabalhar em ofertas.

O Enterprise Library Logging Application Block que vem de padrão da Microsoft & grupo Práticas é um grande exemplo de implementação de uma estrutura de log em um ambiente OOP. Eles têm uma excelente documentação sobre como eles implementaram o seu bloco de aplicativo de registro e todo o código fonte está disponível para sua própria opinião ou modificação.

Existem outras implementações semelhantes: log4net, log4j, log4cxx

Eles maneira eles implementaram o Logging Biblioteca Enterprise Application Block é ter uma classe Logger estático com uma série de métodos diferentes que realmente executar a operação de log. Se você estivesse olhando para os padrões este seria provavelmente um dos melhores usos do padrão Singleton.

Eu sou tudo para AOP juntamente com log4 *. Isso realmente nos ajudou. Google me deu este artigo por exemplo. Você pode tentar procurar mais sobre o assunto.

(IMHO) como 'logging' acontece não é parte de seu projeto de solução, é mais parte de qualquer ambiente acontecer de você estar em execução -. Como sistema e calendário em Java

A sua solução de 'bom' é aquele que é tão frouxamente acoplado a qualquer implementação de registro especial como possíveis para pensar interfaces. Eu confira a trilha aqui para um exemplo de como a Sun abordou-o como eles provavelmente veio com um design muito bom e colocou tudo para fora para você aprender!

usar uma classe estática, ela tem a menor sobrecarga e é acessível a partir de todos os tipos de projeto dentro de uma referência de montagem simples

Note que um Singleton é equivalente, mas envolve a alocação desnecessária

Se você estiver usando vários domínios de aplicação, cuidado que você pode precisar de um objeto proxy para acessar a classe estática de outros que o principal domínios

Além disso, se você tiver vários tópicos pode ser necessário travar em torno das funções de log para evitar o entrelaçamento a saída

logging IMHO si só é insuficiente, é por isso que eu escrevi CALMA

boa sorte!

Talvez a inserção de registro de forma transparente preferiria pertencem na linguagem de programação Orientada a Aspectos. Mas estamos falando de design OO aqui ...

O padrão Singleton pode ser o mais útil, na minha opinião:. Você pode acessar o serviço de registro de qualquer contexto através de um público, método estático de uma classe LoggingService

Embora isto possa parecer um pouco como uma variável global, não é: é devidamente encapsulado dentro da classe singleton, e nem todos têm acesso a ele. Isto permite-lhe mudar a forma de registro é tratado até mesmo em tempo de execução, mas protege a operação do logging de 'vilão' código.

No trabalho sistema I em, criamos uma série de Logging 'singletons', a fim de ser capaz de distinguir mensagens de diferentes subsistemas. Estes podem ser ligado / desligado em tempo de execução, os filtros podem ser definidos, escrevendo para arquivo é possível ... you name it.

Eu resolvi isso no passado, adicionando uma instância de uma classe de log para a classe base (es) (ou interface, se os suportes linguagem que) para as classes que precisam acessar o log. Quando você faz logon alguma coisa, os olhares madeireiro, na pilha de chamadas atual e determina o código de invocação disso, definindo os metadados adequada sobre a declaração de registro (método fonte, linha de código, se disponível, classe que registou, etc.) Desta forma, um mínimo número de classes têm registadores, e os registadores não precisa de ser especificamente configurado com os metadados que pode ser determinada automaticamente.

Este faz adicionar sobrecarga considerável, por isso não é necessariamente uma escolha sábia para registro de produção, mas os aspectos do logger pode ser desativado condicionalmente se você projetá-lo de tal forma a.

Na realidade, eu uso commons-logging maior parte do tempo (eu faço um monte de trabalho em java), mas há aspectos do projeto que eu descrevi acima que eu acho benéfico. Os benefícios de ter um sistema de registro robusto que alguém já passou significativa depuração tempo tem superado a necessidade de que poderia ser considerado um design mais limpo (que é, obviamente, subjetiva, especialmente tendo em conta a falta de detalhes neste post).

Eu tive problemas com loggers estáticos causando problemas de memória permgen (pelo menos, eu pensar isso é que é o problema), então eu provavelmente vou estar revisitando madeireiros em breve.

Para evitar variáveis ??globais, proponho para criar um registro global e registrar seus globals lá.

Para o log, eu prefiro a fornecer uma única classe ou uma classe que fornece alguns métodos estáticos para registro.

Na verdade, eu uso um dos quadros de registro existentes.

Uma outra solução possível é ter uma classe Log que encapsula o procedimento de registro / armazenado. Dessa forma, você pode simplesmente instanciar um new Log(); sempre que precisar, sem ter que usar um singleton.

Esta é a minha solução preferida, porque a única dependência que você precisa de injectar é o banco de dados se você está registrando através de banco de dados. Se você estiver usando arquivos potencialmente você não precisa injetar quaisquer dependências. Você também pode evitar totalmente uma classe de log / função global ou estático.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top