I see. So instead of using interfaces and implementations of these, I would simply use closures, one for mock and one for production? That was actually my first attempt, but I didn't like it back then.
Take this code for example - passing a function just to have it called
feels weird:
(defn load-page [provider name]
(provider name))
(load-page (make-mock-provider) "home")
In Java, this would probably look like this:
class PageLoader {
Provider provider;
PageLoader(Provider p) {
provider = p;
}
Page loadPage(String name) {
provider.loadPage(name);
}
}
PageLoader l = new PageLoader(new MockProvider());
l.loadPage("home");
Then again, it might just feel weird because I've gotten very used to
OOP. In my Java code, loading pages is a responsibility of the
PageLoader and it delegates it to the Provider. Objects have
responsibilities and send messages to each other to fulfill these,
that's OOP.
In functional programming, there's simply a function that has a certain
functionality, and everything it needs to fulfill it has to be provided
by the caller. That's at least how I understand it by now.
Maybe I should just call the function returned by (make-mock-provider)
directly? The interface in Java has the great benefit of ensuring type
safety (plus there's no closures yet, so it's the only way), but does
this make sense in a dynamic language? I mean, if I passed an
implementation of the wrong interface or a closure with the wrong number
of arguments, wouldn't both situations result in weird runtime errors?
On 12/10/10 22:34, Armando Blancas wrote:
>> Back to my question: Am I trying to do Java in Clojure? Is there a more
>> Lisp-y way to do this?
>
> You can hide the types so your client code is more lispy:
> (defn load-page [prov] (.loadPage prov))
> ;;test
> (def mp (make-mock-provider)) ... (load-page mp)
> ;;production
> (def prov (make-provider)) ... (load-page prov)
>
> Depending on your app the provider could be a singleton and need not
> be passed to each function. Another option is multimethods, in which
> case you'd be using mock functions with an argument that would
> indicate which version to dispatch to.
>
> As for the repl, I think it works just as well for bottom-up and top-
> down development. I use it for both all the time and to avoid throw-
> away tests I write them top-down, black-box for only what's visible to
> client/interop code first, then move down the layers as the code is
> more mature and stable. I'm not really into TDD but I depend on a test
> suite as complete as I can get it.
>
signature.asc
Description: OpenPGP digital signature
