2013-03-29 21 views
13

Tôi nhớ đọc một bài báo về cách Ruby không thực sự cần DI hoặc DI framework vì các lớp đang mở. Kết quả là, bạn chỉ có thể viết lại hàm tạo của một phụ thuộc để nó trả về một đối tượng giả.Clojure có cần tiêm phụ thuộc để làm cho mã dễ kiểm tra hơn không?

Tôi rất mới với Clojure và lập trình chức năng. Tôi tự hỏi nếu Clojure cần tiêm phụ thuộc hoặc nó có thể bỏ nó cho tương tự/lý do khác. Dưới đây là ví dụ cụ thể để làm việc với (cảm thấy tự do cách chỉ ra cách thiết kế của tôi không phải là thành ngữ của Clojure):

Hãy tưởng tượng bạn đang phát triển trình thu thập dữ liệu web/nhện. Nó cần phải đi qua một trang web bạn đã tải xuống. Đây là một hành động có tác dụng phụ. Trang web có thể thay đổi trên mọi truy vấn, kết nối internet của bạn có thể bị cắt, v.v. Nó tìm tất cả các liên kết trên trang web, truy cập từng trang web và sau đó duyệt qua nó theo cách tương tự.

Bây giờ, bạn muốn viết một bài kiểm tra nhằm loại bỏ ứng dụng khách http để nó trả về một phản hồi chuỗi mã hóa cứng thay thế. Làm cách nào để bạn gọi chương trình là -main trong một thử nghiệm và ngăn không cho sử dụng ứng dụng khách thực sự của http?

+0

Xem: http://stackoverflow.com/questions/13085370/what-is-the-clojure-equivalent-to-google-guice – noahlz

Trả lời

15

Các with-redefs macro trong clojure.core rất hữu ích cho việc phân tích chức năng.

Dưới đây là một phiên REPL ngắn để chứng minh điều này:

user=> (defn crawl [url] 
    #_=> ;; would now make http connection and download content 
    #_=> "data from the cloud") 
#'user/crawl 
user=> (defn -main [& args] 
    #_=> (crawl "http://www.google.com")) 
#'user/-main 
user=> (-main) 
"data from the cloud" 
user=> (with-redefs [crawl (fn [url] "fake data")] 
    #_=> (-main)) 
"fake data" 

Từ một chương trình Clojure gồm (chủ yếu) của các chức năng, không phải đối tượng, rebinding động của các chức năng thay thế một thỏa thuận tốt về những gì một khuôn khổ DI sẽ làm gì cho mục đích thử nghiệm.

10

Trong Clojure bạn thường đạt được tương đương với dependency injection với các phương pháp thay thế:

  • động ràng buộc - ví dụ hữu ích cho chuyển hướng đầu ra tiêu chuẩn trong các chức năng thử nghiệm bằng cách làm (binding [*out* some-writer-object] ...)
  • cao chức năng để - có thể được sử dụng để cung cấp một hình thức dependency injection bằng cách thông qua các chức năng khác như tham số
  • Cấu hình với dữ liệu - đó là khá thành ngữ trong Clojure để truyền xung quanh các bản đồ chứa các tham số cấu hình (hoặc thậm chí các chức năng để cấu hình hành vi tùy chỉnh).

Tất cả những điều này là không thể thiếu đối với chính ngôn ngữ đó. Vì vậy, bạn chắc chắn không cần bất cứ điều gì giống như một "DI framework". IMHO, cần một khuôn khổ cho DI thực sự chỉ là bù đắp cho một thiếu các tính năng đầy đủ trong ngôn ngữ chính nó.

2

Hãy tưởng tượng bạn đang phát triển trình thu thập dữ liệu web/nhện. Nó cần phải đi qua một trang web bạn đã tải xuống. Đây là một hành động có tác dụng phụ. Trang web có thể thay đổi trên mọi truy vấn, kết nối internet của bạn có thể cắt , v.v. Nó tìm tất cả các liên kết trên trang web, truy cập mỗi liên kết, và sau đó duyệt qua theo cùng một cách.

Tôi không thấy cần tiêm phụ thuộc tại đây.Đây là cách tôi nghĩ rằng tôi sẽ giải quyết vấn đề này trong khi duy trì khả năng thử nghiệm: tách riêng việc triển khai thành tối thiểu hai chức năng. Một hàm tìm nạp và trả về trang web, và hàm kia phân tích cú pháp phản hồi. Trong chức năng chính của bạn, bạn sẽ có một cái gì đó như (-> "http://google.com" fetch parse).

Sau đó, để kiểm tra parse, bạn có thể chỉ cần bỏ qua phương thức fetch và cấp dữ liệu trang web giả mạo trực tiếp vào phương thức parse.

(deftest test 
    (is (= {:something "blah"} (parse "<html><head><title>Fake webpage etc..</title></head></html>")))) 

Vì vậy, miễn là bạn cẩn thận khi chia nhỏ các vấn đề thành các chức năng rõ ràng, tôi không nghĩ bạn cần bất kỳ thứ gì phức tạp như DI để kiểm tra.

Tôi mới dùng Clojure, vì vậy tôi không quen thuộc với các macro và kỹ thuật được đề cập bởi những người khác ở đây, nhưng phương pháp trên đã phục vụ tôi tốt cho đến nay.

+1

Đó là lời khuyên tốt và tôi nghĩ rằng đó là điều tôi muốn làm, nhưng tôi nghĩ đó là nhiều hơn một bài kiểm tra Đơn vị. Đôi khi bạn cần một bài kiểm tra Chấp nhận kiểm tra nhiều hơn chỉ là một phần. –

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