2011-01-19 30 views
13

Tôi tạo một lớp có đối tượng được khởi tạo với một loạt mã XML. Lớp này có khả năng trích xuất các tham số khác nhau ra khỏi XML đó và lưu chúng vào bên trong các biến trạng thái của đối tượng. Số lượng tiềm năng của các tham số này lớn và có thể là hầu hết người dùng sẽ không cần hầu hết các thông số đó. Đó là lý do tại sao tôi đã quyết định thực hiện khởi tạo "lười biếng".Getter với hiệu ứng phụ

Trong trường hợp kiểm tra sau, thông số này là title. Khi người dùng cố gắng truy cập vào nó lần đầu tiên, hàm getter phân tích cú pháp XML, đúng cách khởi tạo các biến trạng thái và trở về giá trị của nó:

class MyClass(object):  
    def __init__(self, xml=None): 
     self.xml = xml 
     self.title = None 

    def get_title(self): 
     if self.__title is None: 
      self.__title = self.__title_from_xml() 
     return self.__title 

    def set_title(self, value): 
     self.__title = value 

    title = property(get_title, set_title, None, "Citation title") 

    def __title_from_xml(self): 
     #parse the XML and return the title 
     return title   

này trông đẹp và hoạt động tốt đối với tôi. Tuy nhiên, tôi bị quấy rầy một chút bởi thực tế là chức năng getter thực sự là một "setter" một trong những ý nghĩa rằng nó có một tác dụng phụ rất đáng kể về đối tượng. Đây có phải là mối quan tâm chính đáng không? Nếu vậy, làm thế nào tôi nên giải quyết nó?

+3

Bất kể câu trả lời thực tế cho câu hỏi là gì, bạn không nên sử dụng dấu gạch dưới kép hàng đầu. Họ bắt đầu mang tên mangling, tức là rất nhiều đau tiềm năng và không đạt được. Chỉ cần sử dụng một dấu gạch dưới hàng đầu. – delnan

+1

Tôi không hiểu tại sao đó là vấn đề. –

+1

Đề xuất tái cấu trúc nhỏ: không khởi tạo 'self._title' trong hàm tạo và thay thế điều kiện trong trình khởi động bằng' not hasrr (self, "_title") '. –

Trả lời

4

Trong khi bộ khởi động chắc chắn thực hiện một tác dụng phụ, đó không phải là truyền thống những gì người ta sẽ xem xét một tác dụng phụ xấu. Vì getter luôn trả về cùng một thứ (chặn bất kỳ thay đổi can thiệp nào trong trạng thái), nó không có tác dụng phụ có thể nhìn thấy được. Đây là cách sử dụng điển hình cho các thuộc tính, vì vậy không có gì phải lo lắng.

+0

Tôi cầu xin không đồng ý: trong trường hợp này, phân tích cú pháp xml có thể tăng ngoại lệ, và không ai mong đợi một truy cập thuộc tính để nâng cao một số ngoại lệ phân tích cú pháp xml. Tôi đã có một trường hợp rất giống nhau trong một dự án tôi đã tiếp quản và viết lại phần này của mã để phân tích cú pháp xảy ra tại instanciation vì vậy không có ngoại lệ xảy ra ở giai đoạn sau nếu xml bị hỏng theo bất kỳ cách nào. Một tài sản nhận được KHÔNG nên tăng bất kỳ ngoại lệ nào. Bạn có mong đợi một truy cập thuộc tính đơn giản để nâng cao bất cứ điều gì (giả sử thuộc tính tồn tại tất nhiên)? Thuộc tính được tính phải an toàn như một thuộc tính đơn giản. –

14

Mẫu thiết kế này được gọi là Lazy initialization và được sử dụng hợp pháp.

+0

cf bình luận của tôi về câu trả lời được chấp nhận - khởi tạo lười biếng là tốt, nhưng điều đó không có nghĩa là quyền truy cập tài sản nên được phép nâng cao bất cứ điều gì.Nếu lớp của bạn đang sử dụng khởi tạo lười biếng, hãy đảm bảo điều này sẽ không bao giờ ngụ ý bất kỳ ngoại lệ nào hoặc không thu hút người dùng nghĩ rằng anh ta đang truy cập thuộc tính an toàn thuần túy và làm cho phương thức của bạn trở nên rõ ràng. ngoại lệ đó. –

0

Khá nhiều năm sau đó nhưng tốt: trong khi khởi tạo lười biếng là tốt trong chính nó, tôi chắc chắn sẽ không trì hoãn xml phân tích vv cho đến khi ai đó truy cập của đối tượng title. Thuộc tính được tính toán được cho là hoạt động như các thuộc tính thuần túy và quyền truy cập thuộc tính thuần túy sẽ không bao giờ tăng (giả sử thuộc tính tồn tại tất nhiên).

FWIW Tôi đã có một trường hợp tương tự trong một số dự án tôi đã tiếp quản, với các lỗi phân tích cú pháp xml xảy ra ở những nơi bất ngờ nhất, do developper trước sử dụng thuộc tính giống như trong ví dụ OP và phải sửa nó bằng cách đặt phần phân tích cú pháp và xác thực vào thời điểm instanciation.

Vì vậy, sử dụng tài sản để khởi tạo lười biếng chỉ nếu và khi bạn biết truy cập đầu tiên sẽ bao giờ tăng. Trên thực tế, không bao giờ sử dụng một tài sản cho bất cứ điều gì mà có thể nâng cao (ít nhất là khi nhận được - thiết lập là một tình huống khác nhau). Khác, không sử dụng một tài sản, làm cho getter một phương pháp rõ ràng và tài liệu rõ ràng nó có thể nâng cao này hoặc đó.

NB: sử dụng thuộc tính để lưu trữ nội dung nào đó không phải là vấn đề ở đây, điều này cũng không sao.

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