Compartilhar via


Práticas recomendadas do Padrão de Design do Observador

No .NET, o padrão de design do observador é implementado como um conjunto de interfaces. A System.IObservable<T> interface representa o provedor de dados, que também é responsável por fornecer uma IDisposable implementação que permite aos observadores cancelar a assinatura de notificações. A System.IObserver<T> interface representa o observador. Este tópico descreve as práticas recomendadas que os desenvolvedores devem seguir ao implementar o padrão de design do observador usando essas interfaces.

Encadeamento

Normalmente, um provedor implementa o IObservable<T>.Subscribe método adicionando um observador específico a uma lista de assinantes que é representada por algum objeto de coleção e implementa o IDisposable.Dispose método removendo um observador específico da lista de assinantes. Um observador pode chamar esses métodos a qualquer momento. Além disso, como o contrato de provedor/observador não especifica quem é responsável por cancelar a inscrição após o método de retorno de chamada IObserver<T>.OnCompleted, o provedor e o observador podem tentar remover o mesmo membro da lista. Devido a essa possibilidade, os métodos Subscribe e Dispose devem ser thread-safe. Normalmente, isso envolve o uso de uma coleção simultânea ou um bloqueio. As implementações que não são thread-safe devem documentar explicitamente esse fato.

Quaisquer garantias adicionais devem ser especificadas em uma camada sobre o contrato de provedor/observador. Os implementadores devem ressaltar claramente quando impõem requisitos adicionais para evitar confusão dos usuários sobre o contrato de observação.

Tratamento de exceções

Devido ao acoplamento flexível entre um provedor de dados e um observador, as exceções no padrão de design do observador devem ser informativas. Isso afeta como provedores e observadores lidam com exceções no padrão de design do observador.

O Provedor - Chamando o Método OnError

O OnError método destina-se como uma mensagem informativa aos observadores, assim como o IObserver<T>.OnNext método. No entanto, o OnNext método foi projetado para fornecer a um observador dados atuais ou atualizados, enquanto o OnError método foi projetado para indicar que o provedor não pode fornecer dados válidos.

O provedor deve seguir estas práticas recomendadas ao lidar com exceções e chamar o OnError método:

  • O provedor deve lidar com suas próprias exceções se tiver requisitos específicos.

  • O provedor não deve esperar ou exigir que os observadores lidem com exceções de qualquer maneira específica.

  • O provedor deve chamar o OnError método quando trata de uma exceção que compromete sua capacidade de fornecer atualizações. Informações sobre essas exceções podem ser passadas ao observador. Em outros casos, não é necessário notificar observadores de uma exceção.

Uma vez que o provedor chame o método OnError ou IObserver<T>.OnCompleted, não deverá haver nenhuma notificação adicional e o provedor poderá cancelar a assinatura de seus observadores. No entanto, os observadores também podem cancelar a assinatura a qualquer momento, incluindo antes e depois de receberem uma notificação OnError ou IObserver<T>.OnCompleted. O padrão de design do observador não determina se o provedor ou o observador é responsável por cancelar a inscrição; portanto, há uma possibilidade de que ambos tentem cancelar a inscrição. Normalmente, quando os observadores cancelam a assinatura, eles são removidos de uma coleção de assinantes. Em um aplicativo de thread único, a implementação IDisposable.Dispose deve garantir que uma referência de objeto seja válida e que o objeto seja um membro da coleção de assinantes antes de tentar removê-lo. Em um aplicativo com multithread, deve-se usar um objeto de coleção thread-safe, tal como um objeto System.Collections.Concurrent.BlockingCollection<T>.

O Observador – Implementando o método OnError

Quando um observador recebe uma notificação de erro de um provedor, o observador deve tratar o erro como informativo e não precisa executar nenhuma ação específica.

O observador deve seguir estas práticas recomendadas ao responder a uma OnError chamada de método de um provedor:

  • O observador não deve lançar exceções de suas implementações de interface, tais como OnNext ou OnError. No entanto, se o observador lançar exceções, deverá esperar que essas exceções não sejam tratadas.

  • Para preservar a pilha de chamadas, um observador que deseja gerar um objeto Exception, que foi passado para o seu método OnError, deveria encapsular a exceção antes de lançá-la. Um objeto de exceção padrão deve ser usado para essa finalidade.

Práticas recomendadas adicionais

A tentativa de cancelar o registro no IObservable<T>.Subscribe método pode resultar em uma referência nula. Portanto, recomendamos que você evite essa prática.

Embora seja possível anexar um observador a vários provedores, o padrão recomendado é anexar uma IObserver<T> instância a apenas uma IObservable<T> instância.

Consulte também