Những trở ngại sẽ gặp phải khi triển khai TDD (Phần 2)
Bài viết sau dịch từ 1 blog trên trang http://qiita.com/ TDDを行った時にぶつかった7つの壁 Bài dịch này là phần 2 cũng là phần cuối của bài. Bạn có thể đọc phần 1 tại đây Mặc dù nếu là người review code thì sẽ hiểu mã kiểm thử, tuy nhiên cùng một đoạn mã kiểm thử, những thành viên khác nhau sẽ có những ...
Bài viết sau dịch từ 1 blog trên trang http://qiita.com/
TDDを行った時にぶつかった7つの壁
Bài dịch này là phần 2 cũng là phần cuối của bài. Bạn có thể đọc phần 1 tại đây
Mặc dù nếu là người review code thì sẽ hiểu mã kiểm thử, tuy nhiên cùng một đoạn mã kiểm thử, những thành viên khác nhau sẽ có những cách hiểu khác nhau, gây ra sự lẫn lộn trong cách hiểu. Cụ thể sẽ xuất hiện người viết kiểm thử chi tiết nghĩ rằng:” chỗ này không cần xem xét cũng được” và người viết kiểm thử sơ sài thì cho rằng: “chỗ này có rất nhiều sai sót”. Vì ngay từ đầu đã gặp vấn đề, và với trường hợp này, sẽ phải vừa sửa vừa phải làm chi tiết, cuối cùng mức độ chi tiết của tổng thể vẫn không đạt được. (Mặc dù việc này được thực hiện đồng bộ sau khi review nhưng chi tiết từ các thành viên mỗi lần thực hiện đều bị lệch) Có thể hiểu biết trước khi viết business của chương trình trong khi thực hiện xem xét kỹ lưỡng từng phần là một lợi thế lớn. Mặc khác, việc review mã kiểm thử mất khá nhiều thời gian hay không vẫn là một vấn đề còn tồn tại mà đến cuối cùng vẫn chưa giải quyết được.
Cần nhiều thời gian để viết những đoạn mà kiểm thử mà kết quả xử lý thay đổi tuỳ theo trạng thái, tình huống. Có thể do tôi còn quá thiếu kinh nghiệm, nên mặc dù chỉ kiểm thử chương trình đơn giản, khi viết kịch bản kiểm thử, tôi đã phải viết rất nhiều mẫu kiểm thử cũng như những dòng code. Ngoài ra, khi làm việc với các thành phần của UI hoặc các mô-đun của bên thứ 3 (thirt party), ngay từ đầu đã làm việc với mock không có kiểm thử, nên công việc kiểm tra chúng trở nên khó khăn và không đạt hiệu quả như mong muốn. Cuối cùng UI sẽ được giải quyết bởi selenium nhưng độ chính xác tương đối thấp. Ngoài ra, việc chuẩn bị mã kiểm thử cho mỗi pattern của mock khá khó để kiểm tra trong thực tế.
Vì không thể phá bỏ trở ngại này nên cuối cùng tôi đã từ bỏ TDD. Đó là tình huống mà hệ thống không thể theo kịp sự thay đổi của business. Nói một cách phóng đại thì ta sẽ không có thời gian để thực hiện TDD khi mà chúng ta bắt buộc phải chấp nhận sự thay đổi là SPEC ngày hôm qua vừa nói, ngày hôm nay đã thay đổi
Giống như khi bắt đầu nói về TDD, chúng ta không thể thoát khỏi vấn đề nhức nhối về performance. Ở đây vì sản phẩm được tạo thành là sản phẩm của (Bto/BtoC), nên phát sinh vấn đề phải cải thiện tốc độ ở nơi thực hiện do không đủ tốc độ để xử lý theo yêu cầu của khách hàng. Để mã kiểm thử có thể sử dụng cho TDD và tuyệt đối không để việc đảm bảo chất lượng có thể bị giảm nên đã tránh sử dụng KVS và memory cache. Khi điều đó xảy ra, do request tạo ra lúc trước đã được cache lại và sử dụng lại ở request sau, cho nên về mặt kết quả, sẽ có những bài test không thể pass được. Một điều cũng rất quan trọng đó là việc update từ Rails 2 lên Rails 3. Rails2 vs Rails3 có những thay đổi rất lớn nên cuối cùng đã phải bỏ hầu hết những mã kiểm thử không hoạt động. Vậy là rất nhiều tài sản đã khó khăn để tạo thành đã bị bỏ hết vào thời điểm đó (mặc dù đây không phải vấn đề của TDD)
Mặc dù thực hiện thì có thể tốt, nhưng không nên thực hiện
Khi thực hiện TDD, xem xét việc gì đầu tiên là tốt, làm sao để member hiểu là một thành quả lớn có thể thấy trong toàn thể team. Ngoài ra, việc có ý thức viết mã kiểm thử cho business của chương trình cũng khiến việc viết mã code đẹp dễ dàng hơn. Việc học được điều đó cũng là một tài sản lớn. Vì vậy, những gì tôi thu được khi thực hiện TDD là vô cùng lớn. Tuy nhiên, dự án mà lần này tôi đảm nhiệm khá quy mô nên việc điều chỉnh trong thực tế là rất khó. Vì vậy, tôi nghĩ rằng thực hiện TDD cho tới lúc kiểm tra mã kiểm thử là đủ. Vì để quản lý được dự án này, kỹ năng của tôi phải ở mức cao nhất nên việc chia thời gian cho review code là rất khó khăn.
Vậy việc thay đổi thì sao
Tôi cảm thấy như những gì đã nói, vì thực hiện TDD, cần thông báo cho member những gì nên làm là một điều quan trọng để thúc đẩy dự án. Vì vậy, sau khi người chịu trách nhiệm giải thích SPEC quyết định xong, thực tế có thể thay đổi một phần của TDD nếu như phát sinh những câu hỏi “làm gì” từ phía các member. Cụ thể là sau khi họp về những việc cần làm vào buổi sáng, nếu xác nhận được các chính sách, phương pháp nhất định của chúng thì sẽ rất tốt. Điều quan trọng là những việc tự mình làm phải được dùng ngôn từ của mình để diễn đạt. Và còn 1 điều nữa, Đó là việc tạo ra các phase hướng dẫn kiểm thử những cái mình tạo ra do những thành viên phát triển khác thực hiện. Tôi đang nói tới hình thức test cặp, 2 người 1 cặp sẽ thực hiện test cho nhau. Có thể dựa trên việc thực hiện đó tại thời điểm này để tìm ra những tiến trình không theo quy tắc và xem xét lại flow của SPEC, khi người thực hiện test có thể hiểu SPEC theo một hướng khác cũng là một lợi thế. Hơn nữa, trong một thời gian ngắn có thể thực hiện kiểm thử là lợi thế lớn nhất. Vì sử dụng phương pháp viết mã kiểm thử cho những bug phát sinh tại đó nên performance được cải thiện khá nhiều (Mặc dù chất lượng bị giảm đi ít nhiều…) Gần đây, tôi đã có cơ hội áp dụng thực hiện kiểm thử nhanh chóng (test first- không phải TDD) tại website. Ở đó, tất cả các mã kiểm thử đều được commit mà không cần ai review. Lợi ích của việc kiểm thử tự động là mỗi phần đều có mức độ riêng, môi trường kiểm thử đó có rất nhiều sai sót nên đã phát sinh rất nhiều bug (Khi các commit pass qua kiểm thử tự động, không ai kiểm tra lại nên điều đó là đương nhiên). Như tôi đã nói ở trên, member có hiểu được SPEC hay không? Lợi ích thu được từ việc suy nghĩ trước khi thực hiện là rất quan trọng. Nếu bỏ qua điều đó, thì việc viết mã kiểm thử trước hay sau hiệu quả cũng không thay đổi mấy. Vì vậy, tôi nghĩ rằng với TDD khi viết white test code trong white test first nên thực hiện review đối với nó.
Tôi đang làm việc ở TonwnSoft. Ở đó, tôi sử dụng rails trong công việc, mặc dù cung cấp dịch vụ nhưng tôi hoàn toàn không phải viết mã kiểm thử. Tuy là không viết mã kiểm thử nhưng chất lượng sản phẩm lại không hề kém chút nào, nói một cách khác là không hề có bug. Mặc dù có còn khó khăn khi lên đến một quy mô nhất định, nói ngược lại khi đến một quy mô nhất định kỹ thuật có thể đảm bảo hoàn toàn mà không cần đến mã kiểm thử (Thay vào đó, tôi cố gắng giảm số dòng code trong các hàm càng nhiều càng tốt, và cố gắng comment vào đó. Cộng việc này không những làm tăng chất lượng sản phẩm, mà khi có những yêu cầu về chỉnh sửa, nó cũng giúp đỡ tôi rất nhiều.) Kết quả là, những kỹ năng programming nâng cao mã kiểm thử của tôi khi thực hiện TDD không còn cần thiết nữa.
Kết cục là tôi đã thất bại trong việc thực hiện TDD. Mặc dù, có lẽ kỹ năng cần thiết của tôi không đủ, nhưng ngoài ra cũng có rất nhiều vấn đề khác nữa. Ví dụ như, trong dự án người có kinh nghiệm lại kém hơn những người mới. Những người mới viết mã kiểm thử đẹp và những người cũ viết code cẩu thả đã sinh ra tình huống không rõ ràng, có nên tạo ra các luật để kiểm tra chi tiết ở đây? Vì vậy, tôi đi đến kết luận rằng TDD là một công cụ kết hợp các thành viên với môi trường làm việc. Tôi cho rằng với những thành viên đang dần chán nản với công việc, nếu chúng ta làm rõ quy trình review code, thì việc không áp dụng TDD có thể đem đến hiệu quả cao hơn. Thêm vào đó, cảm giác về tốc độ tốt như vậy mới là những điều mà công việc ngày nay yêu cầu. (Thực ra thì nó không đơn giản như vậy...)
TDD đã chết!
Có thể là do ảnh hưởng của phát ngôn đó của DHH, cha đẻ của Rails, mà ngày càng có nhiều bài viết với từ khoá này được công bố trên mạng? Tôi viết bài này với suy nghĩ đó.