Fork me on GitHub
#aws
<
2020-04-09
>
kenny20:04:56

Curious how folks who use Cognitect's aws-api handle testing. We are currently using with-redefs on invoke while testing. This feels gross. I'm considering creating a protocol that has an invoke method. We'd then extend the Client type to use this protocol and use our own invoke method instead of the invoke function in aws-api. This would let us create mock clients during tests, removing the need for with-redefs.

thegeez20:04:56

(aws/invoke (aws/client {:api :dynamodb :http-client MY_MOCK_HTTP_CLIENT}) {:op :ListTables})
Something like that ^ ?

kenny20:04:07

I suppose. I'd prefer to work at the aws-api client level than the request level.

ghadi20:04:01

IMHO you should abstract in front of aws-api and let it be an impl detail

ghadi20:04:18

don't try to intercept individual ops, but make pluggable application level things

kenny20:04:16

Have you applied something similar to Datomic?

ghadi20:04:05

no, mostly because the API to datomic is already pretty generic data

ghadi20:04:50

small example of pluggable impls ^

kenny20:04:10

Hmm. That's an interesting pattern. Essentially all effects become protocols?

ghadi20:04:09

i'm not making prescriptions about all

ghadi20:04:37

but i do think that coupling to aws-api, or clj-http, or any X library, is a bad idea

ghadi20:04:39

program to abstractions, not concretions

kenny20:04:34

I could swear I've head this elsewhere 🙂 I quite like this train of thought. Is this from a talk or blog or simply a product of your own creation?

mruzekw22:04:49

Sounds like something Rich Hickey would say

jaihindhreddy11:04:40

It is something similar to what Rich Hickey said a lot of times. Clojure is an improvement on the classic Perlis quote "It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures." Clojure improves this by providing 100 fns on no data structure. The fns instead depend on abstractions like clojure.lang.IPersistentMap, clojure.lang.ISeq etc.

dchelimsky16:04:36

https://en.wikipedia.org/wiki/Dependency_inversion_principle (program to abstractions, not concretions). You can apply this principle to "abstraction" in this conversation, i.e. Clojure Protocols or Java Interfaces are implementation details of the abstract concept of "abstraction" 🙂

kenny20:04:22

@ Are there any other resources on that pattern that you know of that apply to functional programming and/or Clojure?

kenny20:04:45

Looking for things that help me think about what the abstractions are. A good point in the wiki is: > Implementing generic interfaces everywhere in a project makes it harder to understand and maintain. At each step the reader will ask themself what are the other implementations of this interface and the response is generally: only mocks.

jaihindhreddy05:04:04

I feel it's a bad abstraction if it's not self-explanatory and requires readers to ponder the possible implementations to understand the abstraction. Where and how to abstract is a very hard problem indeed. Zach Tellman gave an excellent talk on the topic: https://www.youtube.com/watch?v=x9pxbnFC4aQ Rich Hickey's talks have also help me a lot in thinking about these things. These in particular: Simple Made Easy: https://www.youtube.com/watch?v=kGlVcSMgtV4 Design, Composition, and Performance: https://www.youtube.com/watch?v=MCZ3YgeEUPg

ghadi20:04:39

actually I will make a prescription @kenny :

ghadi20:04:15

grep for with-redefs in your projects and parameterize those things you find