Phương pháp TDD có thể được áp dụng từ trên xuống không?


13

Tôi không rõ làm thế nào TDD, phương pháp luận, xử lý trường hợp sau đây. Giả sử tôi muốn thực hiện thuật toán sáp nhập, bằng Python. Tôi bắt đầu bằng cách viết

assert mergesort([]) === []

và thử nghiệm thất bại với

NameError: tên 'mergesort' không được xác định

Sau đó tôi thêm

def mergesort(a):
    return []

và bài kiểm tra của tôi vượt qua. Tiếp theo tôi thêm

assert mergesort[5] == 5

và bài kiểm tra của tôi thất bại với

Khẳng địnhError

mà tôi vượt qua

def mergesort(a):
    if not a:
        return []
    else:
        return a

Tiếp theo, tôi thêm

assert mergesort([10, 30, 20]) == [10, 20, 30]

và bây giờ tôi phải cố gắng vượt qua. Tôi "biết" thuật toán sáp nhập nên tôi viết:

def mergesort(a):
    if not a:
        return []
    else:
        left, right = a[:len(a)//2], a[len(a)//2:]
        return merge(mergesort(left)), mergesort(right))

Và điều này thất bại với

NameError: tên 'merge' không được xác định

Bây giờ đây là câu hỏi. Làm thế nào tôi có thể chạy đi và bắt đầu thực hiện mergebằng TDD? Có vẻ như tôi không thể bởi vì tôi đã "treo" chưa hoàn thành, thử nghiệm thất bại mergesort, sẽ không vượt qua cho đến khi mergekết thúc! Nếu bài kiểm tra này bị treo, tôi không bao giờ thực sự có thể làm TDD vì tôi sẽ không "xanh" trong quá trình xây dựng lặp TDD của mình merge.

Có vẻ như tôi bị mắc kẹt với ba kịch bản xấu xí sau đây, và muốn biết (1) cộng đồng TDD thích cái nào trong số này, hoặc (2) có cách tiếp cận nào khác mà tôi đang thiếu không? Tôi đã xem một số hướng dẫn của Bác Bob TDD và không nhớ đã thấy một trường hợp như thế này trước đây!

Dưới đây là 3 trường hợp:

  1. Thực hiện hợp nhất trong một thư mục khác với một bộ kiểm tra khác.
  2. Đừng lo lắng về việc có màu xanh khi phát triển chức năng của trình trợ giúp, chỉ cần theo dõi thủ công các thử nghiệm mà bạn thực sự muốn vượt qua.
  3. Nhận xét (GASP!) Hoặc xóa các dòng trong mergesortcuộc gọi đó merge; sau khi đi mergelàm, đặt chúng trở lại.

Tất cả đều trông ngớ ngẩn với tôi (hoặc tôi đang nhìn sai điều này?). Có ai biết cách tiếp cận ưa thích?


2
Một phần của mục tiêu của TDD là giúp bạn tạo ra một thiết kế phần mềm. Một phần của quá trình thiết kế đó là khám phá những gì cần thiết để tạo ra kết quả mong muốn. Trong trường hợp mergesort, vì nó đã là một thuật toán được xác định rõ ràng, quá trình khám phá này là không bắt buộc, và sau đó nó trở thành vấn đề ánh xạ những gì bạn đã biết là thiết kế cho một loạt các bài kiểm tra đơn vị. Có lẽ, bài kiểm tra cấp cao nhất của bạn khẳng định rằng phương pháp của bạn trong bài kiểm tra chấp nhận một bộ sưu tập chưa được sắp xếp và trả về một bộ đã được sắp xếp ...
Robert Harvey

1
... Các bài kiểm tra đơn vị tiếp theo sẽ dần dần đào sâu vào các cơ chế thực tế của a mergesort. Nếu bạn đang tìm kiếm cách "đúng" để làm điều này, thì không có cách nào khác ngoài việc chính xác về việc ánh xạ mergesortthuật toán của bạn sang một loạt các bài kiểm tra đơn vị; tức là họ nên phản ánh những gì mergesortthực sự làm.
Robert Harvey

4
Thiết kế không tự phát triển từ các bài kiểm tra đơn vị; nếu bạn đang mong đợi một mergesortthiết kế xuất hiện tự nhiên từ bộ tái cấu trúc màu đỏ-xanh, điều đó sẽ không xảy ra trừ khi bạn hướng dẫn quy trình dựa trên kiến ​​thức hiện có của bạn mergesort.
Robert Harvey


1
Trong TDD mergephải được phát minh chỉ trong giai đoạn "tái cấu trúc". Nếu bạn thấy mergephương pháp đó có thể được giới thiệu để vượt qua bài kiểm tra của mergesortbạn, trước tiên hãy thực hiện bài kiểm tra của bạn mà không có mergephương pháp. Sau đó, cấu trúc lại việc thực hiện của bạn bằng cách giới thiệu mergephương pháp.
Fabio

Câu trả lời:


13

Dưới đây là một số cách khác để xem xét các lựa chọn của bạn. Nhưng trước tiên, các quy tắc của TDD, từ chú Bob với sự nhấn mạnh của tôi:

  1. Bạn không được phép viết bất kỳ mã sản xuất nào trừ khi nó không vượt qua bài kiểm tra đơn vị.
  2. Bạn không được phép viết thêm bất kỳ bài kiểm tra đơn vị nào là đủ để thất bại; và thất bại biên dịch là thất bại.
  3. Bạn không được phép viết thêm bất kỳ mã sản xuất nào đủ để vượt qua bài kiểm tra đơn vị thất bại.

Vì vậy, một cách để đọc quy tắc số 3 là bạn cần mergehàm để vượt qua bài kiểm tra, do đó bạn có thể thực hiện nó - nhưng chỉ ở dạng cơ bản nhất.

Hoặc, thay vào đó, bạn bắt đầu bằng cách viết nội tuyến hoạt động hợp nhất, sau đó cấu trúc lại nó thành một hàm sau khi làm cho bài kiểm tra hoạt động.

Một cách giải thích khác là bạn đang viết sáp nhập, bạn biết rằng bạn sẽ cần một mergethao tác (nghĩa là đó không phải là YAGNI, đó là điều mà quy tắc "đủ" cố gắng hạn chế). Do đó, bạn nên bắt đầu với các thử nghiệm để hợp nhất và chỉ sau đó mới tiến hành thử nghiệm cho loại tổng thể.


Đây là những quan sát thực sự tốt. Tôi đã nghĩ đến việc tìm hiểu nội tuyến trước đó, nhưng mergethật bất ngờ, lộn xộn, tình huống cạnh tranh (cũng như hữu ích như một độc lập) ý tưởng thực hiện nó như một chức năng riêng biệt có ý nghĩa hơn. Tuy nhiên, phong cách thực hiện nội tuyến ở dạng cơ bản và sau đó phát hiện ra nó ở giai đoạn mũ xanh thực sự có vẻ đúng và rất nhiều những gì tôi đang tìm kiếm.
Ray Toal

@RayToal - Tôi thực sự nghiêng về cách tiếp cận kiểm tra đầy đủ mergehoạt động trước khi thực hiện sắp xếp (cũng như kiểm tra riêng partitionhoạt động). Tôi nghĩ rằng các lợi ích được yêu cầu thiết kế nổi lên đến từ việc làm việc chậm chạp hướng tới một mục tiêu đã biết. Trong trường hợp sáp nhập, tôi không nghĩ mục tiêu nói chung là sắp xếp (vì sau đó bạn sẽ kết thúc với sắp xếp bong bóng). Bạn biết các hoạt động cơ bản, vì vậy bạn làm việc đối với các hoạt động đó; sắp xếp chủ yếu là một suy nghĩ lại.
kdgregory

1
Có một lựa chọn thứ tư. Truyền mergechức năng vào mergesortvà chế nhạo hành vi của nó. Sau đó quay lại và thực hiện mergekiểm tra đầu tiên. Các đại biểu là tuyệt vời ™.
RubberDuck

@RubberDuck Việc nhại một phần không thể thiếu của miền lõi có thể dẫn đến một số rắc rối, cụ thể hơn là khi bạn chạy chương trình và chức năng giả và hợp nhất khác nhau ở chi tiết nhỏ nhất. Một cách tiếp cận như vậy nên được để lại cho các trường hợp bạn đang làm việc với các tài nguyên bên ngoài như từ danh sách sắp xếp đến từ đâu.
cllamach
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.