Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

data encapsulation using closures

Tags:

clojure

I wish to know what is the idiomatic way to achieve data encapsulation in Clojure. Below I describe my particular use case to motivate the example code I provide.

I have code in a dbaccess module that performs a complex database query to fetch some data from a database. I also have a number of functions that operate on the returned, raw, data. These functions then provide more processed, refined views of the data and are invoked numerous times with different arguments from other modules in the system. Let's call them "API functions".

The query is heavy and should execute only once at the beginning, the API functions will then operate on the raw-data from memory without having to perform another DB query.

Here's my approach using closures:

dbaccess module

(ns dbaccess)
    (let
        [raw-data (complex-database-query)]
      (defn create-client-names []
        (fn [some-args] raw-data))
      (defn create-client-portfolio []
        (fn [some-args] raw-data))
      (defn create-client-stocks []
        (fn [some-args] raw-data)))

some other client module

(def client-names (create-client-names))

(doall (map println (client-names "Baltimore")))

I dislike having to name the created functions that have captured the raw-data.

More importantly, the code above doesn't allow the client modules to configure aspects of the query before it executes (e.g. the database connection information).

If, on the other hand, closures are not used I will have to explicitly pass the raw-data back and forth between the dbaccess module and the other modules that need to invoke API functions. Is there a better way? Should I perhaps use mutable state in the dbaccess module?

like image 670
Marcus Junius Brutus Avatar asked Jan 19 '26 09:01

Marcus Junius Brutus


1 Answers

I will have to explicitly pass the raw-data back and forth between the dbaccess module and the other modules that need to invoke API functions

You should do this, pass the data the function need explicitly, because:

  • This will lead to loose coupling between how the data is created and how it is processed.
  • Functions will be more clear to understand while reading it.
  • Testing of the individual function will be easy as you can mock data easily.
like image 76
Ankur Avatar answered Jan 23 '26 12:01

Ankur