2013-03-29 8 views
13

Pamiętam, że przeczytałem artykuł o tym, jak Ruby naprawdę nie potrzebuje ramek DI lub DI, ponieważ zajęcia są otwarte. W rezultacie można po prostu przepisać konstruktor zależności, aby zwracał fałszywy obiekt.Czy iniekcja zależności clojure potrzebujesz, aby kod był bardziej sprawdzalny?

Jestem bardzo nowy w Clojure i programowaniu funkcjonalnym. Zastanawiam się, czy Clojure potrzebuje zastrzyku zależności, czy może zrezygnować z podobnych/innych powodów. Oto konkretny przykład, na którym warto pracować (nie krępuj się, jak wskazać, że mój projekt nie jest idiomatyczny dla Clojure):

Wyobraź sobie, że tworzysz robota/pająka. Musi przejść przez pobraną stronę internetową. To jest akcja z efektami ubocznymi. Strona internetowa może się zmienić przy każdym zapytaniu, może zostać przerwane połączenie internetowe itp. Znajduje wszystkie odnośniki na stronie, odwiedza każdą z nich, a następnie przemierza ją w ten sam sposób.

Teraz chcesz napisać test, który wyśmiewa klienta HTTP, więc zamiast tego zwraca ciąg znaków. W jaki sposób wywołujesz program -main w teście i uniemożliwiasz mu korzystanie z klienta http rzeczywistych?

+0

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

Odpowiedz

15

Makro with-redefs w clojure.core jest bardzo użyteczne w przypadku niedokładnych funkcji.

Oto krótka sesja REPL wykazać to:

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" 

Ponieważ program Clojure składa się (w większości) funkcji, a nie obiektów, dynamiczny ponownego wiązania funkcji zastępuje sporo co ramy DI zrobi do celów testowych.

10

W Clojure zazwyczaj uzyskać odpowiednik wstrzykiwania zależności z alternatywnych metod:

  • dynamicznego wiązania - np przydatna do przekierowywania standardowe wyjściowe w funkcji testowych, wykonując (binding [*out* some-writer-object] ...)
  • funkcja wyższego rzędu - można stosować w celu uzyskania postaci iniekcji zależnościami mijaniu innych funkcji takich parametrów
  • konfiguracji z danymi - to jest dość idiomatycznym w Clojure przekazywać mapy zawierające parametry konfiguracyjne (lub nawet funkcje do konfigurowania niestandardowego zachowania).

Wszystkie one są integralne z samym językiem. Więc zdecydowanie nie potrzebujesz czegoś takiego jak "framework DI". IMHO, potrzebujące ram dla DI, naprawdę rekompensuje brak wystarczających cech w samym języku.

2

Wyobraź sobie, że tworzysz robota sieciowego/pająka. Musi przejść przez pobraną stronę internetową . To jest akcja z efektami ubocznymi. Strona internetowa może się zmienić przy każdym zapytaniu, Twoje połączenie internetowe może zostać wycięte, itp. Wyszukuje wszystkie linki na stronie, odwiedza każdą z nich, , a następnie przechodzi w ten sam sposób.

Nie widzę tutaj potrzeby wykonania wstrzyknięcia zależności.Oto, jak sądzę, że poradzę sobie z tym problemem, zachowując testowalność: oddzielenie implementacji na co najmniej dwie funkcje. Jedna funkcja pobiera i zwraca stronę, a druga analizuje odpowiedź. W swojej głównej funkcji masz coś w rodzaju (-> "http://google.com" fetch parse).

Następnie, aby przetestować parse, można po prostu ominąć metodę fetch i podać fałszywe dane strony bezpośrednio do metody parse.

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

Tak długo, jak jesteś ostrożny uszkodzi problemy w jasnych funkcji, nie sądzę, trzeba coś wyrafinowanego jak DI przetestować.

Jestem nowy w Clojure, więc nie znam makr i technik wymienionych przez innych tutaj, ale powyższa metodologia sprawdziła się do tej pory dobrze.

+1

To dobra rada i myślę, że to coś, co robię, ale myślę, że to więcej testu jednostkowego. Czasami potrzebujesz testu akceptacyjnego, który sprawdza więcej niż tylko część. –

Powiązane problemy