Эта проблема лучше иллюстрируется примером. Я буду использовать Javascript (на самом деле Coffeescript для синтаксиса), но только потому, что Javascript - это еще один LISP, правильно?
Итак, предположим, что я пишу веб-приложение, которое делает (очевидно) ajax-запросы. Я реализую функцию для обработки этого:
ajaxRequest = (url, params, callback) ->
# implementation goes here
Теперь предположим, что у меня есть сетка, которая извлекает данные с сервера. Где-то в моем коде я должен сделать что-то вроде этого:
userGrid.onMustFetch = ->
ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
# fill grid with data
В чем конкретно проблема? Если я хочу протестировать реализацию onMustFetch, я не смогу этого сделать, потому что внутри onMustFetch вызывается зависимость, и тестовая среда не может контролировать зависимость.
Чтобы решить эту проблему, я ввожу зависимость в функцию, которую я хочу проверить. Это означает изменение onMustFetch:
userGrid.onMustFetch = (ajaxRequest) ->
ajaxRequest '/fetch/users', { surname: 'MacGyver' }, (data) ->
# fill grid with data
Теперь тестовый код может передать макет ajaxRequest на onMustFetch и успешно протестировать поведение.
Вундербар, не так ли? Неправильно! Теперь у меня есть вторая проблема: проблема привязки правильного экземпляра ajaxRequest к правильному экземпляру onMustFetch.
На языке, подобном Java, я мог бы использовать инфраструктуру Injection Dependency для этого, и мой код будет выглядеть следующим образом:
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
});
}
}
Жутко, я знаю... но на самом деле каркас DI выполняет всю проводку, поэтому, по крайней мере, эта часть проблемы проще.
Теперь вернемся к нашему веб-приложению и Javascript. Даже если мне удастся всегда вызывать onMustFetch с правильной ссылкой ajaxRequest (ведь в этом случае это не так сложно сделать), должен быть более простой способ. Когда мой код растет, зависимости увеличиваются. Я могу представить передачу ссылки ajaxRequest, но как насчет того, когда у меня есть securityService, browserService, eventBusService и т.д. И т.д. И т.д.?
Теперь реальный вопрос: как lisp как языки решают эту проблему управления зависимостями? (Мне кажется, что зависимости должны быть переданы по всему приложению, но я уверен, что должен быть лучший способ...)