เดี่ยวรับผิดชอบหลักการคือเพื่อนที่ดีที่สุดของคุณที่นี่
ก่อนอื่นให้ย้าย AllFromCache () ไปที่คลาสที่เก็บและเรียกมันว่า GetAll () ที่ดึงมาจากแคชเป็นรายละเอียดการใช้งานของพื้นที่เก็บข้อมูลและไม่ควรรู้โดยรหัสการโทร
สิ่งนี้ทำให้การทดสอบคลาสการกรองของคุณนั้นง่ายและสะดวก ไม่สนใจว่าคุณจะรับจากที่ใด
ประการที่สองห่อคลาสที่รับข้อมูลจากฐานข้อมูล (หรือที่ใดก็ได้) ใน wrapper แคช
AOPเป็นเทคนิคที่ดีสำหรับเรื่องนี้ เป็นหนึ่งในบางสิ่งที่ทำได้ดีมาก
การใช้เครื่องมือเช่นPostSharpคุณสามารถตั้งค่าเพื่อให้วิธีการใด ๆ ที่ทำเครื่องหมายด้วยแอตทริบิวต์ที่เลือกไว้จะถูกแคช อย่างไรก็ตามถ้านี่เป็นสิ่งเดียวที่คุณกำลังแคชคุณไม่จำเป็นต้องไปไกลเท่าที่มีกรอบ AOP เพียงแค่มี Repository และ Caching Wrapper ที่ใช้อินเทอร์เฟซเดียวกันและฉีดเข้าไปในคลาสที่เรียก
เช่น.
public class ProductManager
{
private IProductRepository ProductRepository { get; set; }
public ProductManager
{
ProductRepository = productRepository;
}
Product FetchById(guid id) { ... }
IList<Product> FilterByPropertry(int property) { ... }
}
public interface IProductRepository
{
IList<Product> GetAll();
}
public class SqlProductRepository : IProductRepository
{
public IList<Product> GetAll()
{
// DB Connection, fetch
}
}
public class CachedProductRepository : IProductRepository
{
private IProductRepository ProductRepository { get; set; }
public CachedProductRepository (IProductRepository productRepository)
{
ProductRepository = productRepository;
}
public IList<Product> GetAll()
{
// Check cache, if exists then return,
// if not then call GetAll() on inner repository
}
}
ดูว่าคุณได้ลบความรู้เกี่ยวกับการใช้พื้นที่เก็บข้อมูลออกจาก ProductManager ได้อย่างไร ดูว่าคุณได้ปฏิบัติตามหลักการความรับผิดชอบแบบเดี่ยวด้วยการมีคลาสที่จัดการการดึงข้อมูลคลาสที่จัดการการดึงข้อมูลและคลาสที่จัดการการแคชได้อย่างไร
ตอนนี้คุณสามารถยกตัวอย่าง ProductManager ด้วยที่เก็บอย่างใดอย่างหนึ่งเหล่านั้นและรับแคช ... หรือไม่ สิ่งนี้มีประโยชน์อย่างไม่น่าเชื่อในภายหลังเมื่อคุณได้รับบั๊กที่คุณสงสัยว่าเป็นผลมาจากแคช
productManager = new ProductManager(
new SqlProductRepository()
);
productManager = new ProductManager(
new CachedProductRepository(new SqlProductRepository())
);
(หากคุณใช้คอนเทนเนอร์ IOC ให้ดียิ่งขึ้นควรมีวิธีการปรับตัวที่ชัดเจน)
และในการทดสอบ ProductManager ของคุณ
IProductRepository repo = MockRepository.GenerateStrictMock<IProductRepository>();
ไม่จำเป็นต้องทดสอบแคชเลย
ตอนนี้คำถามกลายเป็น: ฉันควรทดสอบ CachedProductRepository หรือไม่ ฉันไม่แนะนำ แคชค่อนข้างไม่แน่นอน เฟรมเวิร์กทำสิ่งต่าง ๆ ที่อยู่นอกเหนือการควบคุมของคุณ เช่นเพียงแค่นำสิ่งต่าง ๆ ออกจากมันเมื่อมันเต็มเกินไปตัวอย่างเช่น คุณจะจบลงด้วยการทดสอบที่ล้มเหลวครั้งเดียวในดวงจันทร์สีน้ำเงินและคุณจะไม่เข้าใจว่าทำไม
และเมื่อทำการเปลี่ยนแปลงตามที่ฉันแนะนำไว้ข้างต้นมันไม่มีเหตุผลมากมายนักที่จะทำการทดสอบ การทดสอบที่สำคัญจริงๆวิธีการกรองจะอยู่ที่นั่นและแยกออกจากรายละเอียดของ GetAll () อย่างสมบูรณ์ GetAll () เพียงแค่ ... รับทั้งหมด จากที่ไหนสักแห่ง