+1. I also challenge the starting condition that most code will be data
access - that was my assumption (when I migrated from Spring/Hibernate).
It doesn't take much rigour to ensure every side effecting fn
is _only_ concerned with the side effect leaving lots of
non-side-effecting code.

Also, do remember that clojure.jdbc works on plain Clojure maps so you
get half-way there simply by returning the rows to persist.

My advice would be to do the 'Clojure' thing and isolate every
side-effecting code (idiomatically post-fixed with the '!') and see how
it goes.

Although Mikera might have unintentionally put you off it, I would
highly recommend Prismatic Schema from day one :-).

Mikera writes:

> On Monday, 1 February 2016 05:19:17 UTC+8, John Krasnay wrote:
>>
>> Hi all,
>>
>> I'm migrating an application from Java/Spring to Clojure and I'm searching 
>> for a good, functional approach. The app exposes a REST interface using 
>> compojure-api and primarily interacts with a relational database and sends 
>> email.
>>
>> I think most people end up passing their database connection (and other 
>> stateful resources as required) around to non-pure functions that do the 
>> side-effectful work, while trying to push as much business logic into pure 
>> functions possible. My problem with this approach is that most of my app's 
>> functionality is in database interactions, so most of my functionality ends 
>> up being non-pure and difficult to test. For example, to unit test my 
>> functions it seems I'd have to mock my database connection.
>>
>> Instead of this, I'm considering an approach where my functions instead 
>> return a data structure containing a description of the side-effects to be 
>> performed (e.g. "insert these rows into this table", "send this email", 
>> ...), and having a single non-pure function that does all the 
>> side-effectful work described by the structure.
>>
>> From what I've read, it seems is sort of how Haskell does IO in a pure 
>> functional manner, using their IO monad.
>>
>> Has anyone tried this sort of approach? Are there any libraries that might 
>> help? Any pitfalls I might be setting myself up for?
>>
>
> I'm sure that you could get this approach to work, but it sets off some 
> alarm bells in my head.
>
> Problems you may face:
>
> a) You are effectively developing a programming language, where your 
> state-affecting code is represented in data. Clojure already does that.... 
> why reinvent the wheel? I'm reminded of Grrenspun's tenth rule of 
> programming: "Any sufficiently complicated C or Fortran program contains an 
> ad hoc, informally-specified, bug-ridden, slow implementation of half of 
> Common Lisp."
>
> b) Representing operations in code seems neat, but it gets tricky when you 
> have dependencies between them. What if one operation requires conditional 
> execution that depends on the result of a previous operation? You'll need 
> branching and control flow to handle this in a general way, which is 
> non-trivial. What if one set of side effects writes to places that are 
> subsequently "read" by later operations? You'll need to mock or model a 
> database engine if you want to test / simulate this directly.
>
> c) Clojure is an dynamically typed language (sadly, one of it's few 
> flaws....) . The lack of compiler support for type verification makes it 
> harder to keep track of exactly the type of data passing through your 
> deeply composed functions and data structures. Trying to represent graphs 
> of operations as data as well is only likely to make things worse. Yes 
> there are tools such as Schema, but they have their own cost in terms of 
> runtime performance (if you use them for validation) and runtime 
> complexity. It's possible to get right, but I would predict quite a lot of 
> pain along the way.
>
> I'd strongly suggest trying this the more conventional Clojure way first 
> (e.g. using Stuart Sierra's component approach). This can get pretty close 
> to being a nice functional style, and is very easy to test (you just need 
> to mock one or two components and you are usually good). You may ultimately 
> find some areas why you want to implement a DSL, but trying to write the 
> whole application in this fashion from the beginning seems to me like a bit 
> of a high risk strategy. 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to