2011-12-19 29 views
36

Tôi đang tìm cách bắt đầu sử dụng DBC trên một số lượng lớn các dự án dựa trên Python tại nơi làm việc và tôi tự hỏi những trải nghiệm mà những người khác đã có với nó. Cho đến nay nghiên cứu của tôi đã đưa ra những điều sau đây:Sử dụng thiết kế theo hợp đồng bằng Python

  • http://www.python.org/dev/peps/pep-0316/ - PEP 316 được cho là chuẩn hóa thiết kế theo hợp đồng cho Python đã được hoãn lại. PEP này gợi ý sử dụng docstrings.
  • http://www.wayforward.net/pycontract/ - Hợp đồng cho Python. Điều này có vẻ là một khuôn khổ hoàn chỉnh, nhưng không đơn thuần bằng cách sử dụng docstrings.
  • http://www.nongnu.org/pydbc/ - PyDBC triển khai hợp đồng sử dụng metaclasses. Ngoài ra không được duy trì trong một vài năm.

Câu hỏi của tôi là: bạn đã sử dụng DBC với Python cho mã sản xuất trưởng thành chưa? Làm thế nào nó đã làm việc/là nó có giá trị nỗ lực? Bạn sẽ giới thiệu công cụ nào?

+0

Lưu ý rằng bạn chỉ có thể kế thừa từ TestCase và bao gồm các bài kiểm tra đơn vị trong bất kỳ lớp nào. – Marcin

+3

Phải, nhưng DBC có một chút khác biệt ở chỗ nó sẽ chạy kiểm tra trong sản xuất và trên tất cả các đầu vào dữ liệu. Từ những gì tôi hiểu bài kiểm tra đơn vị là thời gian chạy khẳng định với một tập dữ liệu được xác định trước, trong khi DBC là một mức độ trên khẳng định với tất cả các đầu vào. Cụ thể, tôi nghĩ có thể sử dụng DBC trong trường hợp của tôi vì rất nhiều mã thực sự là trạng thái nặng và thường phải lấy trạng thái từ một DB bên ngoài với lược đồ thường xuyên thay đổi và các mối quan hệ khá phức tạp, rất lộn xộn để giả lập . – ipartola

+0

Thiết kế theo hợp đồng là nơi bạn chỉ định rõ ràng đặc điểm kỹ thuật mà từng đoạn mã phù hợp. Bạn không cần phải kiểm tra nó trong thời gian chạy đầy đủ. Đơn vị kiểm tra có thể được đặc điểm kỹ thuật đó cũng giống như bất cứ điều gì khác. TDD là một cách khác nhau của việc sử dụng các bài kiểm tra đơn vị, trong trường hợp đó để mô hình hóa một tập hợp các hành vi dự kiến. – Marcin

Trả lời

4

Tôi chưa sử dụng thiết kế theo hợp đồng trong python, vì vậy tôi không thể trả lời cho tất cả các câu hỏi của bạn. Tuy nhiên, tôi đã dành thời gian để xem thư viện contracts, phiên bản mới nhất đã được phát hành gần đây và có vẻ khá đẹp.

Đã có một số cuộc thảo luận về thư viện này trong reddit.

+1

Cái này trông đẹp, nhưng thiếu sự hỗ trợ cho một phần chính của DBC: bất biến lớp. Tôi sẽ giữ nó trong tâm trí mặc dù. – ipartola

15

PEP bạn tìm thấy chưa được chấp nhận, vì vậy không có cách thức chuẩn hoặc được chấp nhận để thực hiện việc này (tuy nhiên - bạn luôn có thể tự thực hiện PEP!). Tuy nhiên, có một vài cách tiếp cận khác nhau, như bạn đã tìm thấy.

Có lẽ trọng lượng nhẹ nhất chỉ đơn giản là sử dụng trang trí Python. Có một bộ trang trí cho trước/sau điều kiện trong các Python Decorator Library là khá thẳng về phía trước để sử dụng. Dưới đây là ví dụ từ trang đó:

>>> def in_ge20(inval): 
    ... assert inval >= 20, 'Input value < 20' 
    ... 
    >>> def out_lt30(retval, inval): 
    ... assert retval < 30, 'Return value >= 30' 
    ... 
    >>> @precondition(in_ge20) 
    ... @postcondition(out_lt30) 
    ... def inc(value): 
    ... return value + 1 
    ... 
    >>> inc(5) 
    Traceback (most recent call last): 
    ... 
    AssertionError: Input value < 20 

Bây giờ, bạn đề cập đến bất biến lớp. Đây là một chút khó khăn hơn, nhưng cách tôi sẽ đi về nó là để xác định một cuộc gọi để kiểm tra bất biến, sau đó có một cái gì đó giống như trang trí sau điều kiện kiểm tra rằng bất biến ở cuối mỗi cuộc gọi phương pháp. Như một lần cắt đầu tiên, bạn có thể chỉ sử dụng công cụ trang trí hậu kỳ như hiện tại.

+0

Cảm ơn bạn đã trả lời. Tôi hiểu cách thức này có thể được sử dụng để thực hiện DBC trong Python. Điều tôi đang băn khoăn là liệu có ai đã thành công với bất kỳ thư viện nào tôi đã đề cập hay bất kỳ thư viện nào khác. Câu hỏi đặt ra là "làm cách nào để triển khai DBC?" và nhiều hơn nữa của một "tôi nên bận tâm thực hiện DBC?". – ipartola

+0

@ipartola vì PEP 316 đã được "hoãn lại", nó không chủ động được nhưng vẫn chưa bị từ chối. Vì vậy, nếu bạn muốn đưa nó về phía trước, thực hiện một số cải tiến trên PyContract có lẽ sẽ là một con đường tốt. Tôi nghĩ rằng bạn có thể giả định công việc trên PyContract đã bị đình trệ ngay bây giờ. Vì vậy, câu trả lời cho "tôi nên bận tâm thực hiện DBC" là "có" theo ý kiến ​​của tôi, nó sẽ là một bổ sung rất hữu ích, nhưng đó có thể chủ quan như DBC chưa được sử dụng rộng rãi trong hệ sinh thái Python. – snim2

+1

Cũng là thư viện Giao ước (https://bitbucket.org/kisielk/covenant/) từ liên kết mà @jcollado đề cập có bất biến. – snim2

3

Mặc dù không chính xác được thiết kế theo hợp đồng, một số khung kiểm tra cho phép tiếp cận thử nghiệm thuộc tính rất gần khái niệm.

thử nghiệm ngẫu nhiên vì nếu sản phẩm nhất định giữ trong thời gian chạy cho phép dễ dàng kiểm tra:

  • bất biến
  • lĩnh vực đầu vào và đầu ra giá trị
  • khác trước và postconditions

Đối với Python có một số khung kiểm tra kiểu QuickCheck:

9

Theo kinh nghiệm của tôi thiết kế theo hợp đồng là giá trị thực hiện, thậm chí không có hỗ trợ ngôn ngữ.Đối với các phương thức không phải là xác nhận ghi đè, cùng với tài liệu là đủ cho cả trước và sau điều kiện. Đối với các phương thức được ghi đè, chúng tôi chia phương thức thành hai: phương thức công khai kiểm tra trước và sau điều kiện và phương thức được bảo vệ cung cấp triển khai và có thể bị ghi đè bởi các lớp con. Dưới đây là một ví dụ về sau:

class Math: 
    def square_root(self, number) 
     """ 
     Calculate the square-root of C{number} 

     @precondition: C{number >= 0} 

     @postcondition: C{abs(result * result - number) < 0.01} 
     """ 
     assert number >= 0 
     result = self._square_root(number) 
     assert abs(result * result - number) < 0.01 
     return result 

    def _square_root(self, number): 
     """ 
     Abstract method for implementing L{square_root()} 
     """ 
     raise NotImplementedError() 

Tôi có căn bậc hai là một ví dụ chung của thiết kế theo hợp đồng từ một tập phim về thiết kế theo hợp đồng trên đài phát thanh phần mềm kỹ thuật (http://www.se-radio.net/2007/03/episode-51-design-by-contract/). Họ cũng đề cập đến nhu cầu hỗ trợ ngôn ngữ bởi vì các xác nhận không hữu ích trong việc đảm bảo nguyên tắc thay thế Liskov, mặc dù ví dụ trên của tôi nhằm mục đích chứng minh khác. Tôi cũng nên đề cập đến thành ngữ C++ pimpl (tư nhân thực hiện) như một nguồn cảm hứng, mặc dù có một mục đích hoàn toàn khác.

Trong công việc của mình, gần đây tôi đã tái cấu trúc loại kiểm tra hợp đồng này thành một hệ thống phân cấp lớp học lớn hơn (hợp đồng đã được ghi nhận nhưng không được kiểm tra một cách hệ thống). Các bài kiểm tra đơn vị hiện tại đã tiết lộ rằng các hợp đồng đã bị vi phạm nhiều lần. Tôi chỉ có thể kết luận điều này nên đã được thực hiện một thời gian dài trước đây, và bảo hiểm đơn vị thử nghiệm trả hết ngay cả khi thiết kế theo hợp đồng được áp dụng. Tôi hy vọng bất kỳ ai cố gắng kết hợp các kỹ thuật này để thực hiện các quan sát giống nhau.

Hỗ trợ công cụ tốt hơn có thể cung cấp cho chúng tôi nhiều quyền lực hơn trong tương lai, tôi hoan nghênh điều đó.

+0

Giai thoại tuyệt vời thực sự trả lời câu hỏi. – doughgle

+0

Đúng nếu tôi sai, nhưng điều này dường như không tốt với những bất biến của lớp học. Bạn có thể bao gồm chúng trong mỗi pre- và postcondition, nhưng điều đó sẽ trả về false positive khi phương thức (1) phá vỡ bất biến (2) gọi một phương thức khác để kiểm tra bất biến (3) khôi phục bất biến (được cho phép). Bạn có thể áp dụng kỷ luật không bao giờ tự gọi các phương thức công khai, chỉ gọi những người trợ giúp riêng tư, nhưng sau đó các điều kiện trước và sau sẽ không được kiểm tra cho các cuộc gọi đó. – johncip

+0

Nó cũng yêu cầu bạn ghi đè phương pháp công khai nếu thực hiện riêng tư cập nhật trước hoặc sau điều kiện, nhưng tôi cho rằng trong thực tế đó không phải là một vấn đề lớn và công bằng tôi không biết rằng các triển khai khác đã đề cập xử lý các vấn đề này tốt hơn. – johncip

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