Kiến trúc tiến hóa và thiết kế nổi dần: Thiết kế hướng theo kiểm thử, phần 2 Bàn luận thêm về việc cho phép dùng kiểm thử để định hướng và cải thiện thiết kế của bạn
Số trang: 18
Loại file: pdf
Dung lượng: 1.27 MB
Lượt xem: 12
Lượt tải: 0
Xem trước 2 trang đầu tiên của tài liệu này:
Thông tin tài liệu:
Neal Ford, Kiến trúc phần mềm, ThoughtWorks Tóm tắt: Kiểm thử chỉ là một tác dụng phụ của việc phát triển hướng theo kiểm thử (TDD - test-driven development); khi được thực hiện đúng cách, TDD sẽ cải thiện thiết kế tổng thể của mã của bạn. Phần thứ 2 này của bài viết Kiến trúc tiến hóa và thiết kế nổi dần sẽ hoàn tất các bước hướng dẫn về một ví dụ được mở rộng, cho thấy cách làm thế nào để thiết kế có thể xuất hiện dần từ các mối quan tâm nảy sinh trong quá...
Nội dung trích xuất từ tài liệu:
Kiến trúc tiến hóa và thiết kế nổi dần: Thiết kế hướng theo kiểm thử, phần 2 Bàn luận thêm về việc cho phép dùng kiểm thử để định hướng và cải thiện thiết kế của bạn Kiến trúc tiến hóa và thiết kế nổi dần: Thiết kế hướng theo kiểm thử, phần 2Bàn luận thêm về việc cho phép dùng kiểm thử để định hướng và cải thiện thiết kếcủa bạnNeal Ford, Kiến trúc phần mềm, ThoughtWorksTóm tắt: Kiểm thử chỉ là một tác dụng phụ của việc phát triển hướng theo kiểmthử (TDD - test-driven development); khi được thực hiện đúng cách, TDD sẽ cảithiện thiết kế tổng thể của mã của bạn. Phần thứ 2 này của bài viết Kiến trúc tiếnhóa và thiết kế nổi dần sẽ hoàn tất các bước hướng dẫn về một ví dụ được mởrộng, cho thấy cách làm thế nào để thiết kế có thể xuất hiện dần từ các mối quantâm nảy sinh trong quá trình kiểm thử.Đây là phần thứ hai của bài viết gồm hai phần, nghiên cứu cách sử dụng TDD nhưthế nào để cho phép làm nổi dần các bước thiết kế tốt hơn từ quá trình viết kiểmthử trước khi bạn viết mã. Tại phần 1, tôi đã viết một phiên bản của trình tìm sốhoàn hảo (perfect numbers), sử dụng cách phát triển kiểm thử sau (viết các phépkiểm thử sau khi viết mã). Sau đó, tôi đã viết một phiên bản sử dụng TDD (viếtcác phép kiểm thử trước khi viết mã, cho phép kiểm thử chi phối thiết kế mã lệnh).Ở cuối phần 1, tôi thấy rằng tôi đã mắc phải một lỗi cơ bản khi suy nghĩ về loạicấu trúc dữ liệu được sử dụng để lưu giữ danh sách các số hoàn hảo: bản năngmách bảo tôi bắt đầu bằng một danh sách mảng (ArrayList), nhưng tôi thấy rằngphép trừu tượng hóa thành kiểu tập hợp (Set). Tôi sẽ bắt đầu từ điểm này, mở rộngcác thảo luận theo cách mà bạn có thể cải thiện chất lượng của các phép kiểm thửcủa bạn và kiểm tra chất lượng của mã lệnh cuối cùng.Chất lượng kiểm thửPhép kiểm thử sử dụng cách trừu tượng hóa thành kiểu Set tốt hơn có trong liệt kê1:Liệt kê 1. Kiểm thử đơn vị với cách trừu tượng hóa thành Set tốt hơn@Test public void add_factors() { Set expected = new HashSet(Arrays.asList(1, 2, 3, 6)); Classifier4 c = new Classifier4(6); c.addFactor(2); c.addFactor(3); assertThat(c.getFactors(), is(expected));}Mã này kiểm thử một trong những phần quan trọng nhất trong miền b ài toán củatôi: lấy các ước số của một số. Tôi muốn kiểm tra hành vi đó một cách kỹ lưỡngbởi vì nó là phần phức tạp nhất của bài toán, dễ bị gặp lỗi nhất. Tuy nhiên, nó chứamột cấu trúc cồng kềnh, đó là: new HashSet (Arrays.asList (1, 2, 3, 6)). Ngay cảvới sự hỗ trợ của IDE hiện đại, cấu trúc này làm cho mã lệnh rắc rối: gõ nhập new,gõ nhập Has và để mã bên trong tiếp tục; gõ nhập HashSet (Arrays.asList (1, 2, 3, 6)) mới) là một ví dụ tuyệt vời về điều này bởi vìbạn sẽ muốn có rất nhiều biến thể của nó trong các phép kiểm thử khác nhau.(N.D: tác giả chơi chữ ở đây khi đưa ra nguyên tắc Moist. “Moist” – nghĩa là “ẩmướt” đối lập với DRY- nghĩa là “khô”).Quy tắc ngón tay cái TDD của tôi là các kiểm thử chỉ là ẩm (moist) chứ khôngphải là ướt sũng nước (drenched). Ý tôi muốn nói là một số trùng lắp trong cácphép kiểm thử có thể chấp nhận được (và không tránh khỏi), nhưng bạn không nênđi quá xa, tạo ra các cấu trúc cồng kềnh lặp đi lặp lại. Để đạt mục đích n ày, tôi sẽtái cấu trúc phép kiểm thử của mình để cung cấp một phương thức phụ trợ riêng tư(private) để giúp tôi xử lý cách viết hàm tạo phổ biến này, nó có trong liệt kê 2:Liệt kê 2. Phương thức phụ trợ để giữ cho phép thử của tôi ở mức “ẩm”private Set expectationSetWith(Integer... numbers) { return new HashSet(Arrays.asList(numbers));}Mã trong Liệt kê 2 làm cho tất cả các phép kiểm thử của tôi về các ước số trở nênsạch hơn nhiều, như đã thấy trong phép kiểm thử thể hiện trong Liệt kê 3, đượcviết lại từ liệt kê 1:Liệt kê 3. Phép kiểm thử “ẩm hơn” để kiểm tra các ước số của một số@Test public void factors_for_6() { Set expected = expectationSetWith(1, 2, 3, 6); Classifier4 c = new Classifier4(6); c.calculateFactors(); assertThat(c.getFactors(), is(expected));}Bởi vì bạn đang viết các phép kiểm thử không có nghĩa là bạn phải vứt bỏ đi cácnguyên tắc thiết kế tốt. Phép kiểm thử là các loại mã lệnh khác, nhưng các nguyêntắc tốt (mặc dù khác) cũng được áp dụng đối với chúng.Các điều kiện biênTDD khuyến khích các nhà phát triển phần mềm viết một phép kiểm thử khôngthực hiện được khi viết phép kiểm thử đầu tiên cho một chức năng mới nào đó.Điều này tránh việc phép kiểm thử vô tình chạy thông suốt trong mọi trường hợp,làm cho phép kiểm thử thực sự không kiểm tra bất cứ điều gì (phép kiểm thử thừa– tautology test). Các phép kiểm thử cũng có thể xác minh hành vi mà bạn nghĩrằng bạn là đúng nhưng chưa kiểm tra đủ để tự tin. Các phép kiểm thử này khôngnhất thiết phải là trước tiên thất bại (mặc dù thất bại khi bạn nghĩ rằng phép kiểmthử sẽ thông suốt là điều hoàn toàn tốt bởi vì bạn đã tìm ra một lỗi tiềm tàng). Suynghĩ về việc kiểm thử dẫn bạn đến xem xét ...
Nội dung trích xuất từ tài liệu:
Kiến trúc tiến hóa và thiết kế nổi dần: Thiết kế hướng theo kiểm thử, phần 2 Bàn luận thêm về việc cho phép dùng kiểm thử để định hướng và cải thiện thiết kế của bạn Kiến trúc tiến hóa và thiết kế nổi dần: Thiết kế hướng theo kiểm thử, phần 2Bàn luận thêm về việc cho phép dùng kiểm thử để định hướng và cải thiện thiết kếcủa bạnNeal Ford, Kiến trúc phần mềm, ThoughtWorksTóm tắt: Kiểm thử chỉ là một tác dụng phụ của việc phát triển hướng theo kiểmthử (TDD - test-driven development); khi được thực hiện đúng cách, TDD sẽ cảithiện thiết kế tổng thể của mã của bạn. Phần thứ 2 này của bài viết Kiến trúc tiếnhóa và thiết kế nổi dần sẽ hoàn tất các bước hướng dẫn về một ví dụ được mởrộng, cho thấy cách làm thế nào để thiết kế có thể xuất hiện dần từ các mối quantâm nảy sinh trong quá trình kiểm thử.Đây là phần thứ hai của bài viết gồm hai phần, nghiên cứu cách sử dụng TDD nhưthế nào để cho phép làm nổi dần các bước thiết kế tốt hơn từ quá trình viết kiểmthử trước khi bạn viết mã. Tại phần 1, tôi đã viết một phiên bản của trình tìm sốhoàn hảo (perfect numbers), sử dụng cách phát triển kiểm thử sau (viết các phépkiểm thử sau khi viết mã). Sau đó, tôi đã viết một phiên bản sử dụng TDD (viếtcác phép kiểm thử trước khi viết mã, cho phép kiểm thử chi phối thiết kế mã lệnh).Ở cuối phần 1, tôi thấy rằng tôi đã mắc phải một lỗi cơ bản khi suy nghĩ về loạicấu trúc dữ liệu được sử dụng để lưu giữ danh sách các số hoàn hảo: bản năngmách bảo tôi bắt đầu bằng một danh sách mảng (ArrayList), nhưng tôi thấy rằngphép trừu tượng hóa thành kiểu tập hợp (Set). Tôi sẽ bắt đầu từ điểm này, mở rộngcác thảo luận theo cách mà bạn có thể cải thiện chất lượng của các phép kiểm thửcủa bạn và kiểm tra chất lượng của mã lệnh cuối cùng.Chất lượng kiểm thửPhép kiểm thử sử dụng cách trừu tượng hóa thành kiểu Set tốt hơn có trong liệt kê1:Liệt kê 1. Kiểm thử đơn vị với cách trừu tượng hóa thành Set tốt hơn@Test public void add_factors() { Set expected = new HashSet(Arrays.asList(1, 2, 3, 6)); Classifier4 c = new Classifier4(6); c.addFactor(2); c.addFactor(3); assertThat(c.getFactors(), is(expected));}Mã này kiểm thử một trong những phần quan trọng nhất trong miền b ài toán củatôi: lấy các ước số của một số. Tôi muốn kiểm tra hành vi đó một cách kỹ lưỡngbởi vì nó là phần phức tạp nhất của bài toán, dễ bị gặp lỗi nhất. Tuy nhiên, nó chứamột cấu trúc cồng kềnh, đó là: new HashSet (Arrays.asList (1, 2, 3, 6)). Ngay cảvới sự hỗ trợ của IDE hiện đại, cấu trúc này làm cho mã lệnh rắc rối: gõ nhập new,gõ nhập Has và để mã bên trong tiếp tục; gõ nhập HashSet (Arrays.asList (1, 2, 3, 6)) mới) là một ví dụ tuyệt vời về điều này bởi vìbạn sẽ muốn có rất nhiều biến thể của nó trong các phép kiểm thử khác nhau.(N.D: tác giả chơi chữ ở đây khi đưa ra nguyên tắc Moist. “Moist” – nghĩa là “ẩmướt” đối lập với DRY- nghĩa là “khô”).Quy tắc ngón tay cái TDD của tôi là các kiểm thử chỉ là ẩm (moist) chứ khôngphải là ướt sũng nước (drenched). Ý tôi muốn nói là một số trùng lắp trong cácphép kiểm thử có thể chấp nhận được (và không tránh khỏi), nhưng bạn không nênđi quá xa, tạo ra các cấu trúc cồng kềnh lặp đi lặp lại. Để đạt mục đích n ày, tôi sẽtái cấu trúc phép kiểm thử của mình để cung cấp một phương thức phụ trợ riêng tư(private) để giúp tôi xử lý cách viết hàm tạo phổ biến này, nó có trong liệt kê 2:Liệt kê 2. Phương thức phụ trợ để giữ cho phép thử của tôi ở mức “ẩm”private Set expectationSetWith(Integer... numbers) { return new HashSet(Arrays.asList(numbers));}Mã trong Liệt kê 2 làm cho tất cả các phép kiểm thử của tôi về các ước số trở nênsạch hơn nhiều, như đã thấy trong phép kiểm thử thể hiện trong Liệt kê 3, đượcviết lại từ liệt kê 1:Liệt kê 3. Phép kiểm thử “ẩm hơn” để kiểm tra các ước số của một số@Test public void factors_for_6() { Set expected = expectationSetWith(1, 2, 3, 6); Classifier4 c = new Classifier4(6); c.calculateFactors(); assertThat(c.getFactors(), is(expected));}Bởi vì bạn đang viết các phép kiểm thử không có nghĩa là bạn phải vứt bỏ đi cácnguyên tắc thiết kế tốt. Phép kiểm thử là các loại mã lệnh khác, nhưng các nguyêntắc tốt (mặc dù khác) cũng được áp dụng đối với chúng.Các điều kiện biênTDD khuyến khích các nhà phát triển phần mềm viết một phép kiểm thử khôngthực hiện được khi viết phép kiểm thử đầu tiên cho một chức năng mới nào đó.Điều này tránh việc phép kiểm thử vô tình chạy thông suốt trong mọi trường hợp,làm cho phép kiểm thử thực sự không kiểm tra bất cứ điều gì (phép kiểm thử thừa– tautology test). Các phép kiểm thử cũng có thể xác minh hành vi mà bạn nghĩrằng bạn là đúng nhưng chưa kiểm tra đủ để tự tin. Các phép kiểm thử này khôngnhất thiết phải là trước tiên thất bại (mặc dù thất bại khi bạn nghĩ rằng phép kiểmthử sẽ thông suốt là điều hoàn toàn tốt bởi vì bạn đã tìm ra một lỗi tiềm tàng). Suynghĩ về việc kiểm thử dẫn bạn đến xem xét ...
Tìm kiếm theo từ khóa liên quan:
lập trình java công nghệ java phát triển với java lập mô hình dịch vụ web java ngôn ngữ lập trìnhGợi ý tài liệu liên quan:
-
Giáo trình Lập trình hướng đối tượng: Phần 2
154 trang 273 0 0 -
Bài thuyết trình Ngôn ngữ lập trình: Hệ điều hành Window Mobile
30 trang 264 0 0 -
Kỹ thuật lập trình trên Visual Basic 2005
148 trang 264 0 0 -
Giáo trình Lập trình cơ bản với C++: Phần 1
77 trang 232 0 0 -
Bài giảng Một số hướng nghiên cứu và ứng dụng - Lê Thanh Hương
13 trang 223 0 0 -
Giáo án Tin học lớp 11 (Trọn bộ cả năm)
125 trang 215 1 0 -
NGÂN HÀNG CÂU HỎI TRẮC NGHIỆM THIẾT KẾ WEB
8 trang 205 0 0 -
Bài tập lập trình Windows dùng C# - Bài thực hành
13 trang 180 0 0 -
Giáo trình Lập trình C căn bản: Phần 1
64 trang 169 0 0 -
Bài giảng Nhập môn về lập trình - Chương 1: Giới thiệu về máy tính và lập trình
30 trang 163 0 0