แน่นอนหนึ่งสามารถเรียกใช้กฎหมายของ abstractions รั่วแต่นั่นไม่น่าสนใจโดยเฉพาะอย่างยิ่งเพราะมัน posits ว่า abstractions ทั้งหมดมีการรั่วไหล หนึ่งสามารถยืนยันและต่อต้านการคาดเดาว่า แต่มันก็ไม่ได้ช่วยถ้าเราไม่แบ่งปันความเข้าใจในสิ่งที่เราหมายถึงโดยที่เป็นนามธรรมและสิ่งที่เราหมายถึงโดยรั่ว ดังนั้นก่อนอื่นฉันจะพยายามอธิบายวิธีที่ฉันดูแต่ละคำเหล่านี้:
นามธรรม
คำนิยามที่ชื่นชอบของabstractionsมาจากAPPPของ Robert C. Martin :
"สิ่งที่เป็นนามธรรมคือการขยายความสำคัญและการกำจัดสิ่งที่ไม่เกี่ยวข้อง"
ดังนั้นการเชื่อมต่อไม่ได้ในตัวเองนามธรรม พวกเขาเป็นเพียงนามธรรมถ้าพวกเขานำสิ่งที่สำคัญและซ่อนส่วนที่เหลือ
รั่ว
หนังสือหลักการการพึ่งพาการพึ่งพารูปแบบและวิธีปฏิบัติในการกำหนดคำศัพท์ที่เป็นนามธรรมรั่วในบริบทของการพึ่งพาการฉีด (DI) ความแตกต่างและหลักการ SOLID มีบทบาทสำคัญในบริบทนี้
จากหลักการผกผันอ้างอิง (DIP) หลักการดังต่อไปนี้อ้าง APPP อีกครั้งว่า:
"ลูกค้า [... ] เป็นเจ้าของอินเทอร์เฟซแบบนามธรรม"
สิ่งนี้หมายถึงว่าลูกค้า (รหัสโทร) กำหนด abstractions ที่พวกเขาต้องการแล้วคุณไปและใช้นามธรรมที่
นามธรรมรั่วในมุมมองของฉันเป็นนามธรรมที่ละเมิดทรัพย์สินทางปัญญาโดยการอย่างใดรวมทั้งฟังก์ชั่นบางอย่างที่ลูกค้าไม่ได้เป็นความจำเป็น
การพึ่งพาแบบซิงโครนัส
ไคลเอนต์ที่ใช้ส่วนของตรรกะทางธุรกิจโดยทั่วไปจะใช้ DI เพื่อแยกตัวเองออกจากรายละเอียดการใช้งานบางอย่างเช่นฐานข้อมูลทั่วไป
พิจารณาวัตถุโดเมนที่จัดการคำขอจองร้านอาหาร:
public class MaîtreD : IMaîtreD
{
public MaîtreD(int capacity, IReservationsRepository repository)
{
Capacity = capacity;
Repository = repository;
}
public int Capacity { get; }
public IReservationsRepository Repository { get; }
public int? TryAccept(Reservation reservation)
{
var reservations = Repository.ReadReservations(reservation.Date);
int reservedSeats = reservations.Sum(r => r.Quantity);
if (Capacity < reservedSeats + reservation.Quantity)
return null;
reservation.IsAccepted = true;
return Repository.Create(reservation);
}
}
นี่IReservationsRepository
พึ่งพาจะถูกกำหนดโดยเฉพาะโดยลูกค้าที่MaîtreD
ระดับ:
public interface IReservationsRepository
{
Reservation[] ReadReservations(DateTimeOffset date);
int Create(Reservation reservation);
}
อินเทอร์เฟซนี้จะซิงโครนัสทั้งหมดเนื่องจากMaîtreD
คลาสไม่ต้องการให้เป็นแบบอะซิงโครนัส
การพึ่งพาแบบอะซิงโครนัส
คุณสามารถเปลี่ยนอินเตอร์เฟสเป็นแบบอะซิงโครนัสได้อย่างง่ายดาย:
public interface IReservationsRepository
{
Task<Reservation[]> ReadReservations(DateTimeOffset date);
Task<int> Create(Reservation reservation);
}
อย่างไรก็ตามMaîtreD
คลาสไม่ต้องการวิธีการเหล่านั้นแบบอะซิงโครนัสดังนั้นตอนนี้กรมทรัพย์สินทางปัญญาถูกละเมิด ฉันถือว่าสิ่งนี้เป็นนามธรรมที่ไม่น่าเชื่อเพราะรายละเอียดการใช้งานบังคับให้ลูกค้าเปลี่ยน TryAccept
วิธีการในขณะนี้นอกจากนี้ยังมีที่จะกลายเป็นไม่ตรงกัน:
public async Task<int?> TryAccept(Reservation reservation)
{
var reservations =
await Repository.ReadReservations(reservation.Date);
int reservedSeats = reservations.Sum(r => r.Quantity);
if (Capacity < reservedSeats + reservation.Quantity)
return null;
reservation.IsAccepted = true;
return await Repository.Create(reservation);
}
ไม่มีเหตุผลโดยธรรมชาติสำหรับตรรกะโดเมนที่จะไม่ตรงกัน แต่เพื่อสนับสนุนการไม่ตรงกันของการดำเนินการนี้จำเป็นต้องใช้ในขณะนี้
ตัวเลือกที่ดีกว่า
ที่ NDC Sydney 2018 ฉันได้พูดคุยในหัวข้อนี้ ในนั้นฉันยังร่างทางเลือกที่ไม่รั่วไหล ฉันจะให้พูดคุยในที่ประชุมในหลาย 2019 เช่นกัน แต่ตอนนี้แบรนที่มีชื่อใหม่ของการฉีด Async
ฉันวางแผนที่จะเผยแพร่โพสต์ในบล็อกหลายชุดเพื่อติดตามการพูดคุยด้วย บทความเหล่านี้เขียนแล้วและนั่งอยู่ในคิวบทความของฉันรอการเผยแพร่ดังนั้นคอยติดตาม