Ten problem lepiej ilustruje przykład. Użyję JavaScript (w rzeczywistości Coffeescript dla sake składni), ale tylko dlatego, że JavaScript jest po prostu inny SEPLENIENIE, dobrze?
Załóżmy więc, że piszę aplikację internetową, która ma (oczywiście) prośby ajaxowe. Wdrażam funkcję do obsługi tego:
ajaxRequest = (url, params, callback) ->
# implementation goes here
Teraz załóżmy, że mam siatkę, która pobiera dane z serwera. Gdzieś w moim kodzie muszę zrobić coś takiego:
userGrid.onMustFetch = ->
ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
# fill grid with data
Jaki jest dokładnie problem? Jeśli chcę przetestować wdrożenie onMustFetch, Nie będę w stanie tego zrobić, ponieważ w środku onMustFetch, wywoływana jest zależność, a środowisko testowe nie może kontrolować zależności.
Aby rozwiązać ten problem, wprowadzam zależność do funkcji, którą chcę przetestować. To oznacza zmianę onMustFetch do tego:
userGrid.onMustFetch = (ajaxRequest) ->
ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
# fill grid with data
Teraz kod testowy może przekazać fałszywy przykład ajaxRequest do onMustFetch i pomyślnie przetestować zachowanie.
Wunderbar, prawda? Źle! Teraz mam drugi problem, problem związany z właściwym wystąpieniem ajaxRequest na właściwy przykład onMustFetch.
W języku takim jak Java, mógłbym użyć Dependency Injection framework, aby zrobić to dla mnie, a mój kod wyglądałby tak:
class UserGrid {
private AjaxService ajaxService;
@Inject
public UserGrid(AjaxService ajaxService) {
this.ajaxService = ajaxService;
}
public void onMustFetch() {
HashMap<String, String> params = new HashMap<String, String>();
params.put("surname", "MacGyver");
ajaxService.request("/fetch/users", params, new AjaxCallback(data) {
// fill grid with data
});
}
}
Creepy, wiem ... ale w rzeczywistości struktura DI wykonuje całe okablowanie, więc przynajmniej ta część problemu jest łatwiejsza.
Wróćmy teraz do naszej aplikacji internetowej i do Javascript. Nawet jeśli uda mi się zawsze wywołać onMustFetch z prawą ajaxRequest odniesienie (w tym przypadku nie jest to takie trudne), musi istnieć łatwiejszy sposób. Kiedy mój kod rośnie, zwiększają się zależności. Mogę sobie wyobrazić przekazanie odniesienia ajaxRequest dookoła, ale co, kiedy mam securityService, a browserService, a eventBusServiceitp. itp.?
Teraz prawdziwe pytanie: w jaki sposób języki typu "lisp" rozwiązują ten problem zarządzania zależnościami? (Wydaje mi się, że zależności muszą być przekazywane w całej aplikacji, ale jestem pewien, że musi być lepszy sposób ...)