Bayangkan Anda harus menggunakan kode orang lain yang dirancang seperti yang ditunjukkan di bawah ini:
class Messy {
String concat(String param, String str) { /* ... */ }
boolean contains(String param, String s) { /* ... */ }
boolean isEmpty(String param) { /* ... */ }
boolean matches(String param, String regex) { /* ... */ }
boolean startsWith(String param, String prefix) { /* ... */ }
}
Sekarang bayangkan Anda mengetahui bahwa kode Anda yang bergantung padanya terlihat seperti berikut:
String process(String param) {
Messy messy = new Messy();
if (messy.contains(param, "whatever")) {
return messy.concat(param, "-contains");
}
if (messy.isEmpty(param)) {
return messy.concat(param, "-empty");
}
if (messy.matches(param, "[whatever]")) {
return messy.concat(param, "-matches");
}
if (messy.startsWith(param, "whatever")) {
return messy.concat(param, "-startsWith");
}
return messy.concat(param, "-whatever");
// WTF do I really need to repeat bloody "param" 9 times above?
}
... dan Anda ingin membuatnya lebih mudah digunakan, khususnya, untuk menyingkirkan penggunaan parameter berulang yang hanya tidak diperlukan untuk aplikasi Anda.
Oke, jadi Anda mulai membangun lapisan anti korupsi.
Hal pertama adalah memastikan bahwa "kode utama" Anda tidak merujuk Messy
langsung. Misalnya, Anda mengatur manajemen ketergantungan sedemikian rupa sehingga mencoba mengakses Messy
gagal dikompilasi.
Kedua, Anda membuat modul "layer" khusus yang merupakan satu-satunya yang mengakses Messy
dan mengeksposnya ke "kode utama" Anda dengan cara yang lebih masuk akal bagi Anda.
Kode lapisan akan terlihat seperti berikut:
class Reasonable { // anti-corruption layer
String param;
Messy messy = new Messy();
Reasonable(String param) {
this.param = param;
}
String concat(String str) { return messy.concat(param, str); }
boolean contains(String s) { return messy.contains(param, s); }
boolean isEmpty() { return messy.isEmpty(param); }
boolean matches(String regex) { return messy.matches(param, regex); }
boolean startsWith(String prefix) { return messy.startsWith(param, prefix); }
}
Akibatnya, "kode utama" Anda tidak mengacaukan Messy
, dengan menggunakan Reasonable
, kira-kira sebagai berikut:
String process(String param) {
Reasonable reasonable = new Reasonable(param);
// single use of "param" above and voila, you're free
if (reasonable.contains("whatever")) {
return reasonable.concat("-contains");
}
if (reasonable.isEmpty()) {
return reasonable.concat("-empty");
}
if (reasonable.matches("[whatever]")) {
return reasonable.concat("-matches");
}
if (reasonable.startsWith("whatever")) {
return reasonable.concat("-startsWith");
}
return reasonable.concat("-whatever");
}
Perhatikan bahwa masih ada sedikit kekacauan, Messy
tetapi ini sekarang tersembunyi cukup dalam Reasonable
, membuat "kode utama" Anda cukup bersih dan bebas dari korupsi yang akan dibawa ke sana dengan penggunaan langsung Messy
barang - barang.
Contoh di atas didasarkan pada bagaimana Anticorruption Layer dijelaskan di c2 wiki:
Jika aplikasi Anda perlu berurusan dengan database atau aplikasi lain yang modelnya tidak diinginkan atau tidak dapat diterapkan pada model yang Anda inginkan dalam aplikasi Anda sendiri, gunakan AnticorruptionLayer untuk menerjemahkan ke / dari model itu dan model Anda.
Catatan contoh sengaja dibuat sederhana dan ringkas untuk membuat penjelasan singkat.
Jika Anda memiliki mess-of-API yang lebih besar untuk menutupi di balik lapisan anti-korupsi, pendekatan yang sama berlaku: pertama, pastikan "kode utama" Anda tidak mengakses hal-hal yang rusak secara langsung dan kedua, buka dengan cara yang lebih nyaman dalam konteks penggunaan Anda.
Saat "menskalakan" layer Anda di luar contoh yang disederhanakan di atas, pertimbangkan bahwa membuat API Anda nyaman tidak selalu merupakan tugas sepele. Investasikan upaya untuk merancang lapisan Anda dengan cara yang benar , verifikasi penggunaan yang dimaksudkan dengan uji unit dll.
Dengan kata lain, pastikan API Anda memang lebih baik daripada yang disembunyikannya, pastikan Anda tidak hanya memperkenalkan lapisan korupsi lainnya.
Demi kelengkapan, perhatikan perbedaan halus tapi penting antara ini dan pola terkait Adapter dan Fasad . Sebagaimana ditunjukkan oleh namanya, lapisan anti korupsi mengasumsikan bahwa API yang mendasarinya memiliki masalah kualitas ("rusak") dan bermaksud menawarkan perlindungan terhadap masalah yang disebutkan.
Anda dapat memikirkannya seperti ini: jika Anda dapat membenarkan bahwa perancang perpustakaan akan lebih baik mengekspos fungsinya dengan Reasonable
alih - alih Messy
, ini berarti Anda bekerja pada lapisan anti korupsi, melakukan pekerjaan mereka , memperbaiki kesalahan desain mereka .
Berbeda dengan itu, Adaptor dan Fasad tidak membuat asumsi pada kualitas desain yang mendasarinya. Ini dapat diterapkan pada API yang dirancang dengan baik untuk memulainya, hanya mengadaptasinya untuk kebutuhan spesifik Anda.
Sebenarnya, bahkan bisa lebih produktif untuk mengasumsikan bahwa pola-pola seperti Adapter dan Facade mengharapkan kode yang mendasarinya dirancang dengan baik. Anda dapat memikirkannya seperti ini: kode yang dirancang dengan baik seharusnya tidak terlalu sulit untuk disesuaikan untuk kasus penggunaan tertentu. Jika ternyata desain adaptor Anda membutuhkan upaya lebih dari yang diharapkan, ini dapat menunjukkan bahwa kode yang mendasarinya, baik, entah bagaimana "rusak". Dalam hal ini, Anda dapat mempertimbangkan membagi pekerjaan ke fase terpisah: pertama, buat layer anti korupsi untuk menyajikan API yang mendasarinya dengan cara yang terstruktur dengan baik dan selanjutnya, desain adaptor / fasad Anda di atas lapisan perlindungan.