2009-02-07 33 views
14

Tôi đã thấy rất nhiều ví dụ về tải chậm - lựa chọn của bạn là gì?Tải trọng lười biếng - cách tiếp cận tốt nhất là gì?

Cho một lớp mô hình ví dụ:

public class Person 
{ 
    private IList<Child> _children; 
    public IList<Child> Children 
    { 
     get { 
      if (_children == null) 
       LoadChildren(); 
      return _children; 
     } 
    } 
} 

Lớp Person không nên biết gì về nó như thế nào dành cho trẻ em được nạp .... hoặc nên nó? Chắc chắn nó nên kiểm soát khi tài sản được dân cư, hay không?

Bạn có một kho chứa cặp người cùng với bộ sưu tập con hay bạn sử dụng cách tiếp cận khác, chẳng hạn như sử dụng lớp lazyload - thậm chí sau đó, tôi không muốn lớp lười biếng làm mờ trong kiến ​​trúc mô hình của mình.

Bạn sẽ xử lý hiệu suất như thế nào nếu trước tiên yêu cầu một Người và sau đó là Trẻ em (ví dụ: không tải chậm trong trường hợp này) hoặc bằng cách nào đó tải chậm.

Tất cả điều này có phù hợp với lựa chọn cá nhân không?

+0

Sự cố - đây thường là ví dụ điển hình về tối ưu hóa địa phương với chi phí tối ưu hóa toàn cầu. – dkretz

Trả lời

14

Tải lười biếng tốt nhất là tránh nó;) An toàn chủ đề là vấn đề ngay lập tức bạn sẽ phải xử lý. Tôi không tính mức độ thường xuyên tôi thấy các hệ thống sản xuất với 8 lõi CPU chạy tải gấp 8 lần cho mỗi mẫu tải lười biếng đơn lẻ được sử dụng. Ít nhất là trên máy chủ khởi động tất cả các lõi máy chủ có xu hướng kết thúc ở cùng một nơi.

Hãy để khung DI xây dựng nó cho bạn thay vào đó, nếu bạn có thể. Và nếu bạn không thể, tôi vẫn thích xây dựng rõ ràng hơn. Vì vậy, tất cả các loại ma thuật AOP chỉ đơn giản là không cắt nó với tôi, đi cho xây dựng rõ ràng bên ngoài lớp học. Đừng đặt nó bên trong lớp người, chỉ cần tạo một dịch vụ để xây dựng các đối tượng theo đúng cách.

Giới thiệu các lớp "ma thuật" nhiều hay ít minh bạch làm những việc này dường như là như một ý tưởng hay, nhưng tôi chưa bắt gặp các triển khai không có hậu quả khó hiểu và có vấn đề.

+0

Cảm ơn bạn đã dành thời gian, bạn có thể xây dựng bằng cách sử dụng khung DI và xây dựng rõ ràng không? –

+0

Tôi nghĩ rằng anh ta đã nói rằng việc có lớp Person rõ ràng tạo ra các trẻ em (với LoadChildren() có lẽ) trong quá trình khởi tạo riêng của nó không nghi ngờ gì về trạng thái của _children. Và Dependency Injection, cũng có nhiều chủ đề ở đây tốt hơn tôi trong một bình luận. – JMD

+0

Ngoài ra - bạn mất nguyên tử của truy vấn. Và thường xuyên hơn chiến lược tổng thể hiệu quả nhất là phát hành một truy vấn đơn lẻ (bên ngoài?) Tham gia cho các bản ghi con và nhận mọi thứ trong một giao dịch, thay vì trải rộng trên nhiều lần truy cập cơ sở dữ liệu. – dkretz

0

Tôi cho rằng đây là chính xác loại sự cố được xử lý tốt nhất bởi AOP (ví dụ: PostSharp). Có tải lười biếng của bạn như là một khía cạnh và sau đó sử dụng nó để trang trí bất cứ tài sản bạn muốn được tải lazily. Tuyên bố từ chối trách nhiệm: chưa thử; chỉ cần nghĩ rằng nó nên hoạt động.

1

tôi đã nói chuyện về một giải pháp tôi sử dụng để thực hiện tải lười biếng here

+0

Cảm ơn thời gian của bạn, đây không chỉ là một sự phụ thuộc khác? Tôi quan tâm đến cách tiếp cận mặc dù. –

1

Bạn có thể sử dụng mẫu Virtual Proxy, cùng với Observer pattern. Điều này sẽ cung cấp cho bạn tải chậm mà không có lớp Person có kiến ​​thức rõ ràng về cách Trẻ em được tải.

0

Tôi vừa hỏi một câu hỏi có liên quan here, nhưng nó nặng hơn trên Immutability & Thread Safety tack. Rất nhiều câu trả lời và nhận xét tốt. Bạn có thể thấy nó hữu ích.

0

Dưới đây là ví dụ triển khai tải chậm bằng cách sử dụng mẫu Proxy

Lớp người sẽ sống với các mô hình còn lại của bạn. Trẻ em được đánh dấu là ảo để nó có thể được ghi đè bên trong lớp PersonProxy.

public class Person { 
    public int Id; 
    public virtual IList<Child> Children { get; set; } 
} 

Lớp PersonRepository sẽ tồn tại với phần còn lại của kho lưu trữ của bạn. Tôi đã bao gồm phương thức để đưa các em vào lớp này nhưng bạn có thể có nó trong lớp ChildRepository nếu bạn muốn.

public class PersonRepository { 
    public Person FindById(int id) { 
     // Notice we are creating PersonProxy and not Person 
     Person person = new PersonProxy(); 

     // Set person properties based on data from the database 

     return person; 
    } 

    public IList<Child> GetChildrenForPerson(int personId) { 
     // Return your list of children from the database 
    } 
} 

Lớp PersonProxy sống với kho của bạn. Điều này được thừa kế từ Person và sẽ làm việc tải chậm. Bạn cũng có thể sử dụng boolean để kiểm tra nếu nó đã được nạp thay vì kiểm tra xem liệu Children == null.

public class PersonProxy : Person { 
    private PersonRepository _personRepository = new PersonRepository(); 

    public override IList<Child> Children { 
     get { 
      if (base.Children == null) 
       base.Children = _personRepository.GetChildrenForPerson(this.Id); 

      return base.Children; 
     } 
     set { base.Children = value; } 
    } 
} 

Bạn có thể sử dụng nó như vậy

Person person = new PersonRepository().FindById(1); 
Console.WriteLine(person.Children.Count); 

Tất nhiên bạn có thể có PersonProxy mất trong một giao diện cho PersonRepository và truy cập tất cả thông qua một dịch vụ nếu bạn không muốn gọi PersonRepository trực tiếp.

Các vấn đề liên quan