Latar Belakang: Saya sedang mengembangkan kerangka kerja pengiriman pesan. Kerangka kerja ini akan memungkinkan:
- pengiriman pesan melalui bus layanan
- berlangganan antrian di bus pesan
- berlangganan topik pada bus pesan
Kami saat ini menggunakan RabbitMQ, tapi saya tahu kami akan pindah ke Microsoft Service Bus (on Premise) dalam waktu dekat.
Saya berencana untuk membuat satu set antarmuka dan implementasi sehingga ketika kita pindah ke ServiceBus, saya hanya perlu memberikan implementasi baru tanpa mengubah salah satu kode klien (yaitu penerbit atau pelanggan).
Masalahnya di sini adalah bahwa RabbitMQ dan ServiceBus tidak langsung diterjemahkan. Misalnya, RabbitMQ bergantung pada Pertukaran dan Nama Topik, sedangkan ServiceBus adalah semua tentang Ruang nama dan Antrian. Juga, tidak ada antarmuka umum antara klien ServiceBus dan klien RabbitMQ (misalnya keduanya mungkin memiliki IConnection, tetapi antarmuka berbeda - bukan dari namespace yang umum).
Jadi menurut saya, saya bisa membuat antarmuka sebagai berikut:
public interface IMessageReceiver{
void AddSubscription(ISubscription subscriptionDetails)
}
Karena sifat-sifat yang tidak dapat diterjemahkan dari kedua teknologi tersebut, implementasi ServiceBus dan RabbitMQ dari antarmuka di atas memiliki persyaratan yang berbeda. Jadi implemetasi RabbitMq saya dari IMessageReceiver mungkin terlihat seperti ini:
public void AddSubscription(ISubscription subscriptionDetails){
if(!subscriptionDetails is RabbitMqSubscriptionDetails){
// I have a problem!
}
}
Bagi saya, baris di atas melanggar aturan substitusi Liskov.
Saya mempertimbangkan untuk membalik ini, sehingga Langganan menerima IMessageConnection, tetapi sekali lagi Langganan RabbitMq akan membutuhkan properti spesifik dari RabbitMQMessageConnection.
Jadi, pertanyaan saya adalah:
- Apakah saya benar bahwa ini memecah LSP?
- Apakah kita setuju bahwa dalam beberapa kasus itu tidak dapat dihindari, atau, apakah saya kehilangan sesuatu?
Semoga ini jelas dan sesuai topik!
interface IMessageReceiver<T extends ISubscription>{void AddSubscription(T subscriptionDetails); }
. Implementasi kemudian dapat terlihat seperti public class RabbitMqMessageReceiver implements IMessageReceiver<RabbitMqSubscriptionDetails> { public void AddSubscription(RabbitMqSubscriptionDetails subscriptionDetails){} }
(dalam java).
interface TestInterface<T extends ISubscription>
dengan jelas akan mengkomunikasikan tipe mana yang diterima, dan bahwa ada perbedaan antara implementasi.