web-dev-qa-db-fra.com

Monde réel - Principe de substitution de Liskov

Contexte: Je développe un cadre de messagerie. Ce cadre permettra:

  • envoi de messages sur un bus de service
  • s'abonner aux files d'attente sur le bus de message
  • s'abonner aux sujets sur un bus de message

Nous utilisons actuellement la Rabbitmq, mais je sais que nous allons passer à Microsoft Service Bus (sur Principe) dans un proche avenir.

Je prévois de créer un ensemble d'interfaces et d'implémentations de sorte que lorsque nous passons à ServiceBus, j'ai simplement besoin de fournir une nouvelle implémentation sans modifier l'un des indicatifs du client (I.E. Éditeurs ou abonnés).

Le problème ici est que Rabbitmq et Servicebus ne sont pas directement traduisables. Par exemple, Rabbitmq s'appuie sur des échanges et des noms de sujets, alors que ServiceBus est tout sur les espaces de noms et les files d'attente. En outre, il n'y a pas d'interfaces communes entre le client Servicebus et le client rabbbitmq (par exemple, peut avoir une iconnection, mais l'interface est différente - et non d'un espace de nom commun).

Donc, à mon point, je peux créer une interface comme suit:

public interface IMessageReceiver{
  void AddSubscription(ISubscription subscriptionDetails)
}

En raison des propriétés non traduisatrices des deux technologies, les implémentations Servicebus et RabbitMQ de l'interface ci-dessus ont des exigences différentes. Donc, ma rabbitmq implémentation d'Imessagereceur peut ressembler à ceci:

public void AddSubscription(ISubscription subscriptionDetails){
  if(!subscriptionDetails is RabbitMqSubscriptionDetails){
    // I have a problem!
  }
}

Pour moi, la ligne ci-dessus brise la règle de substituabilité de Liskov.

J'ai envisagé de passer cela autour de cela, de sorte qu'un abonnement accepte une imessageconnection, mais à nouveau, l'abonnement rabbbitmq nécessiterait des propriétés spécifiques d'une rabbbitmsmessageconnection.

Donc, mes questions sont:

  • Suis-je raison que cela brise le LSP?
  • Passons-nous que dans certains cas, il est inévitable, ou je manque quelque chose?

Espérons que cela est clair et sur le sujet!

14
GinjaNinja

Oui, votre code brise le LSP ici. Dans de tels cas, j'utiliserais la couche anti-corruption des modèles de conception DDD. Vous pouvez voir un exemple là-bas: http://www.markhneedham.com/blog/2009/07/07/domain-driven-design-anti-Corruption-layer/

L'idée est de réduire autant que possible la dépendance au sous-système en l'isolant explicitement afin de minimiser le refactoring lors de la modification

J'espère que ça aide !

2
Julien