Arka plan: Bir mesajlaşma çerçevesi geliştiriyorum. Bu çerçeve şunları sağlayacaktır:
- servis otobüsü üzerinden mesaj gönderme
- mesaj veri yolundaki kuyruklara abone olma
- mesaj veri yolundaki konulara abone olma
Şu anda RabbitMQ kullanıyoruz, ancak çok yakında Microsoft Hizmet Veri Yolu'na (Şirket İçi) taşınacağımızı biliyorum.
Bir dizi arabirim ve uygulama oluşturmayı planlıyorum, böylece ServiceBus'a taşındığımızda, istemci kodunda (yani yayıncılar veya aboneler) herhangi bir değişiklik yapmadan yeni bir uygulama sağlamam gerekiyor.
Buradaki sorun, RabbitMQ ve ServiceBus'un doğrudan çevrilebilir olmamasıdır. Örneğin, RabbitMQ Değişimler ve Konu Adlarına dayanırken, ServiceBus tamamen Ad Alanları ve Kuyruklarla ilgilidir. Ayrıca, ServiceBus istemcisi ile RabbitMQ istemcisi arasında ortak arabirimler yoktur (örneğin her ikisinde de bir IConnection olabilir, ancak arabirim farklıdır - ortak bir ad alanından değil).
Benim açımdan, aşağıdaki gibi bir arayüz oluşturabilirim:
public interface IMessageReceiver{
void AddSubscription(ISubscription subscriptionDetails)
}
İki teknolojinin çevrilemez özelliklerinden dolayı, yukarıdaki arabirimin ServiceBus ve RabbitMQ uygulamaları farklı gereksinimlere sahiptir. Yani IMessageReceiver benim RabbitMq uygulaması şöyle görünebilir:
public void AddSubscription(ISubscription subscriptionDetails){
if(!subscriptionDetails is RabbitMqSubscriptionDetails){
// I have a problem!
}
}
Bana göre, yukarıdaki çizgi Liskov'un ikame edilebilirlik kuralını ihlal ediyor.
Bir Abonelik bir IMessageConnection kabul eder, ancak yine de RabbitMq Abonelik bir RabbitMQMessageConnection belirli özellikleri gerektirir bu etrafında saygısız kabul.
Yani, sorularım:
- Bunun LSP'yi bozduğunu düzeltir miyim?
- Bazı durumlarda bunun kaçınılmaz olduğunu kabul ediyor muyuz, yoksa bir şey mi kaçırıyorum?
Umarım, bu açık ve konuyla ilgili!
interface IMessageReceiver<T extends ISubscription>{void AddSubscription(T subscriptionDetails); }
. Bir uygulama public class RabbitMqMessageReceiver implements IMessageReceiver<RabbitMqSubscriptionDetails> { public void AddSubscription(RabbitMqSubscriptionDetails subscriptionDetails){} }
(java'da) gibi görünebilir .
interface TestInterface<T extends ISubscription>
hangi türlerin kabul edildiğini ve uygulamalar arasında farklılıklar olduğunu açıkça bildirir.