背景:私はメッセージングフレームワークを開発しています。このフレームワークでは次が可能になります。
- サービスバスを介したメッセージの送信
- メッセージバス上のキューにサブスクライブする
- メッセージバスのトピックを購読する
現在RabbitMQを使用していますが、近い将来にMicrosoft Service Bus(オンプレミス)に移行することを知っています。
インターフェイスと実装のセットを作成して、ServiceBusに移行するときに、クライアントコード(パブリッシャーまたはサブスクライバー)を修正せずに新しい実装を提供するだけでよいようにします。
ここでの問題は、RabbitMQとServiceBusが直接翻訳できないことです。たとえば、RabbitMQはExchangeとトピック名に依存していますが、ServiceBusは名前空間とキューに関するものです。また、ServiceBusクライアントとRabbitMQクライアントの間に共通のインターフェイスはありません(たとえば、両方にIConnectionがある場合がありますが、インターフェイスは異なります-共通の名前空間からではありません)。
そのため、次のようにインターフェイスを作成できます。
public interface IMessageReceiver{
void AddSubscription(ISubscription subscriptionDetails)
}
2つのテクノロジーの翻訳不可能な特性により、上記のインターフェースのServiceBusとRabbitMQの実装には異なる要件があります。したがって、IMessageReceiverのRabbitMq実装は次のようになります。
public void AddSubscription(ISubscription subscriptionDetails){
if(!subscriptionDetails is RabbitMqSubscriptionDetails){
// I have a problem!
}
}
私にとって、上記の行は、リスコフの代替可能性の規則を破ります。
SubscriptionがIMessageConnectionを受け入れるように、これを反転させることを検討しましたが、RabbitMq SubscriptionにはRabbitMQMessageConnectionの特定のプロパティが必要になります。
だから、私の質問は:
- これがLSPに違反することを修正できますか?
- 場合によっては避けられないこと、または何かが足りないことに同意しますか?
うまくいけば、これは明確で話題になっています!
interface IMessageReceiver<T extends ISubscription>{void AddSubscription(T subscriptionDetails); }
。実装はpublic class RabbitMqMessageReceiver implements IMessageReceiver<RabbitMqSubscriptionDetails> { public void AddSubscription(RabbitMqSubscriptionDetails subscriptionDetails){} }
(javaの)ようになります。
interface TestInterface<T extends ISubscription>
どのタイプが受け入れられるか、実装間に違いがあることを明確に伝えることができます。