ลองนึกภาพคุณต้องใช้รหัสของคนอื่นที่ได้รับการออกแบบดังแสดงด้านล่าง:
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) { /* ... */ }
}
ตอนนี้คิดว่าคุณพบว่ารหัสของคุณขึ้นอยู่กับว่ามันมีลักษณะดังต่อไปนี้:
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?
}
... และคุณต้องการทำให้การใช้งานง่ายขึ้นโดยเฉพาะเพื่อกำจัดการใช้งานซ้ำ ๆ ของพารามิเตอร์ที่ไม่จำเป็นสำหรับแอปพลิเคชันของคุณ
เอาล่ะคุณเริ่มสร้างเลเยอร์ต่อต้านการทุจริต
สิ่งแรกคือเพื่อให้แน่ใจว่า "รหัสหลัก" ของคุณไม่ได้อ้างถึงMessy
โดยตรง ตัวอย่างเช่นคุณจัดการการพึ่งพาในลักษณะที่พยายามเข้าถึงMessy
ล้มเหลวในการรวบรวม
ประการที่สองคุณสร้างโมดูล "เลเยอร์" โดยเฉพาะซึ่งเป็นหนึ่งเดียวที่เข้าถึงMessy
และเปิดเผยให้กับ "รหัสหลัก" ของคุณในวิธีที่เหมาะสมกับคุณมากขึ้น
รหัสเลเยอร์จะมีลักษณะดังต่อไปนี้:
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); }
}
ด้วยเหตุนี้ "รหัสหลัก" ของคุณจึงไม่ยุ่งMessy
ใช้Reasonable
แทนเกี่ยวกับดังนี้:
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");
}
โปรดทราบว่ายังคงมีความยุ่งเหยิงนิดหน่อยMessy
แต่ตอนนี้ซ่อนอยู่ข้างในพอสมควรReasonable
ทำให้ "รหัสหลัก" ของคุณสะอาดและมีเหตุผลโดยปราศจากความเสียหายที่จะเกิดขึ้นจากการใช้Messy
สิ่งต่าง ๆ โดยตรง
ตัวอย่างข้างต้นขึ้นอยู่กับวิธีอธิบายเลเยอร์ Anticorruptionที่ c2 wiki:
หากแอปพลิเคชันของคุณต้องการจัดการกับฐานข้อมูลหรือแอปพลิเคชันอื่นที่มีโมเดลที่ไม่พึงประสงค์หรือไม่เหมาะสมกับโมเดลที่คุณต้องการภายในแอปพลิเคชันของคุณเองให้ใช้ AnticorruptionLayer เพื่อแปลเป็น / จากโมเดลนั้นและของคุณ
ตัวอย่างของโน้ตนั้นถูกสร้างขึ้นมาอย่างเรียบง่ายและย่อเพื่อให้คำอธิบายสั้น ๆ
หากคุณมีระเบียบที่ใหญ่กว่า API เพื่อปกปิดเลเยอร์ต่อต้านการคอรัปชั่นให้ใช้วิธีการเดียวกัน: ก่อนอื่นตรวจสอบให้แน่ใจว่า "รหัสหลัก" ของคุณไม่สามารถเข้าถึงสิ่งที่เสียหายได้โดยตรงและในลำดับที่สอง สะดวกในบริบทการใช้งานของคุณ
เมื่อ "ขยาย" เลเยอร์ของคุณนอกเหนือจากตัวอย่างแบบง่ายด้านบนให้คำนึงถึงว่าการทำให้ API ของคุณสะดวกไม่จำเป็นต้องเป็นเรื่องเล็กน้อย ลงทุนความพยายามในการออกแบบเลเยอร์ของคุณอย่างถูกต้องตรวจสอบการใช้งานที่ต้องการด้วยการทดสอบหน่วยฯลฯ
กล่าวอีกนัยหนึ่งตรวจสอบให้แน่ใจว่า API ของคุณได้รับการปรับปรุงให้ดีขึ้นกว่าเดิมซ่อนอยู่ตรวจสอบให้แน่ใจว่าคุณไม่ได้แนะนำการทุจริตอีกชั้นหนึ่ง
เพื่อความครบถ้วนสมบูรณ์ให้เห็นความแตกต่างบอบบาง แต่ที่สำคัญระหว่างนี้และที่เกี่ยวข้องกับรูปแบบอะแดปเตอร์และซุ้ม ตามที่ระบุโดยชื่อชั้นต่อต้านการคอร์รัปชั่นถือว่าAPI พื้นฐานมีปัญหาด้านคุณภาพ (คือ "เสียหาย") และตั้งใจที่จะให้การป้องกันปัญหาที่กล่าวถึง
คุณสามารถคิดว่าวิธีนี้ถ้าคุณสามารถแสดงให้เห็นถึงว่านักออกแบบห้องสมุดจะดีกว่าการเปิดเผยการทำงานกับReasonable
แทนMessy
นี้จะหมายถึงคุณกำลังทำงานบนชั้นต่อต้านการทุจริตทำของพวกเขางานการแก้ไขของพวกเขาผิดพลาดการออกแบบ
เมื่อเทียบกับที่กล่าวว่าอะแดปเตอร์และซุ้มไม่ได้ตั้งสมมติฐานเกี่ยวกับคุณภาพของการออกแบบพื้นฐาน สิ่งเหล่านี้สามารถนำไปใช้กับ API ที่ได้รับการออกแบบมาเป็นอย่างดีโดยเริ่มต้นเพียงปรับให้เหมาะกับความต้องการเฉพาะของคุณ
ที่จริงแล้วมันอาจมีประสิทธิผลมากกว่าที่จะสมมติว่ารูปแบบเช่นAdapterและFacadeคาดว่าโค้ดพื้นฐานจะได้รับการออกแบบมาอย่างดี คุณสามารถคิดได้ด้วยวิธีนี้: โค้ดที่ออกแบบมาอย่างดีไม่ควรปรับแต่งยากเกินไปสำหรับกรณีการใช้งานเฉพาะ หากปรากฎว่าการออกแบบอะแดปเตอร์ของคุณใช้ความพยายามมากกว่าที่คาดหมายนี่อาจเป็นการระบุว่ารหัสอ้างอิงนั้นเป็นอย่างใด "เสียหาย" ในกรณีดังกล่าวคุณสามารถพิจารณาแบ่งงานออกเป็นขั้นตอนต่างๆดังนี้ขั้นแรกสร้างเลเยอร์การต่อต้านการคอรัปชั่นเพื่อแสดง API พื้นฐานในโครงสร้างที่เหมาะสมและถัดไปออกแบบอะแดปเตอร์ / ส่วนหน้าของเลเยอร์การป้องกันนั้น