2012-04-23 25 views
6

Tôi đang đối mặt với một vấn đề về cách kiến ​​trúc một phần cụ thể của phần mềm của tôi. Cho phép nói rằng, tôi có một chức năng được gọi là make-temp-dir (và nhiều tính năng khác) thực hiện một số phép màu tối tùy thuộc vào hệ điều hành hiện tại. Tôi muốn có thể đặt các triển khai của các phương thức này cho từng hệ điều hành trong một không gian tên riêng biệt.Công văn phụ thuộc vào môi trường của các giao thức/đa phương thức trong clojure

Thứ nhất, tôi tin rằng các giao thức (nếu có thể) hoặc đa phương thức là giải pháp cho điều này. Tuy nhiên, tôi chưa bao giờ thấy một ví dụ về việc sử dụng chúng với việc triển khai trải rộng trên nhiều không gian tên. Và tôi không thể tìm ra cách làm việc này như thế nào .

Thứ hai, nếu tôi sử dụng các giao thức cho việc này, tôi sẽ phải gọi các phương pháp điều như

(make-temp-dir current-os arg-1 arg-2) 

Bằng cách nào đó, đi qua các os như là đối số đầu tiên tất cả các thời gian không nhìn quá tốt với tôi. Vì lợi ích ngữ nghĩa, tôi muốn các yêu cầu thông minh tùy thuộc vào hệ điều hành. Chắc chắn tôi có thể sử dụng một số macro và làm điều gì đó như

(doto current-os 
    (make-temp-dir arg-1 arg2)) 

nhưng điều đó cảm thấy sai.

Việc này nên được thực hiện như thế nào? Hay tôi đang đi sai đường? Bất kỳ trợ giúp nào được đánh giá cao.

Chỉnh sửa: Được rồi, cảm ơn một tấn đến @kotarak, tôi đã xoay xở để làm việc gì đó. Đối với bất kỳ ai tình cờ gặp phải điều này, https://gist.github.com/2477120. Làm việc tốt, tôi nghĩ rằng tôi sẽ đi với điều đó. Cảm ơn mọi người.

Trả lời

7
(ns your.utils) 

(def current-os) 

(defmulti make-temp-dir 
    (fn [& _] current-os)) 

(ns your.utils.mac) 

(defmethod make-temp-dir :mac-os-x 
    [a b] 
    (...)) 

(ns your.utils.win) 

(defmethod make-temp-dir :windows 
    [a b] 
    (...)) 

Trong mã khởi động của bạn, bạn phải khởi tạo current-os với alter-var-root trước khi sử dụng bất kỳ chức năng tiện ích.

(let [os (find-os)] 
    (alter-var-root #'current-os (constantly os)) 
    (require (case os 
      :mac-os-x 'your.utils.mac 
      :windows 'your.utils.win))) 

Hy vọng bạn sẽ bắt đầu.

+0

Vì vậy, đoạn mã thứ hai cần phải nằm trong không gian tên 'your.utils' phải không? Ngoài ra, macro đọc '# '' là gì - xin lỗi, cũng không biết cách làm thế nào để google đó;) –

+0

'#'' được gọi là dấu * var *. Bạn có thể tìm thấy mô tả về dấu ngoặc kép var tại https://groups.google.com/forum/?fromgroups#!topic/clojure/jDBAJD4nWqs. – user100464

+0

@kotarak, Được rồi, giải pháp tuyệt vời. Đã khiến tôi mất nhiều thời gian để tiêu hóa nó nhưng tôi nghĩ tôi hiểu chuyện gì đang xảy ra. Tôi vẫn muốn một số đầu vào trên bình luận đầu tiên của tôi mặc dù. –

1

Tôi không thể nói chắc chắn, nhưng có vẻ như bạn có thể sẽ phát minh ra một bánh xe mà Java cung cấp cho bạn. Hãy thử https://github.com/Raynes/fs để có trình bao bọc thuận tiện trên một số thứ Java cung cấp ngoài các công cụ cơ bản trong clojure.java.io (http://clojuredocs.org/clojure_core/clojure.java.io).

Bạn cũng có thể tìm thấy https://github.com/drakerlabs/milieu hữu ích nếu câu hỏi của bạn mở rộng ngoài phân nhánh theo hệ điều hành cụ thể cho các giá trị cấu hình theo môi trường cụ thể. Tôi đã viết mã này như là một phần của các dự án độc quyền của chúng tôi ở đây tại Draker, và chúng tôi vừa mới phát hành nó dưới dạng phần mềm miễn phí. Chúng tôi vẫn chưa chính thức công bố nó cho cộng đồng, nhưng nó là trong Clojars và sẵn sàng để sử dụng. Phản hồi được đánh giá cao! Khái niệm thúc đẩy sự sáng tạo của nó là môi trường theo ý nghĩa của dev/test/staging/production etc, nhưng tôi không thấy lý do tại sao nó không thể được sử dụng để cấu hình các biến cho các môi trường hệ điều hành khác nhau.

+1

Cảm ơn bạn đã liên kết rplevy. Tôi nghĩ rằng các gói fs sẽ có ích cho tôi :) –

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