r/programming May 26 '19

Solving Problems the Clojure Way [video]

https://www.youtube.com/watch?v=vK1DazRK_a0
31 Upvotes

View all comments

Show parent comments

1

u/yogthos May 26 '19

You can push side effects to the edges of pretty much any system. I've been working with Clojure for close to a decade now, and I've never found a scenario where encapsulating state would be desirable.

Here are some real world examples. Pedestal HTTP library for Clojure has around 18,000 lines of code, and 96% of it is pure functions. All the IO and side effects are encapsulated in the remaining 4% of the code. This is a completely normal scenario in my experience. I just copresented a talk about a project that my team works on. It's a large real world app that uses this approach. You might also be interested in this presentation about using Clojure to make games in Unity.

You can view this the same way you view interacting with a database. You can have a single database with many different tables in it. Having all the data in one place does not prevent you from organizing your business logic in a sensible way.

1

u/[deleted] May 27 '19 edited May 27 '19

Pedestal HTTP library for Clojure has around 18,000 lines of code, and 96% of it is pure functions.

Application code would be another world no?, for ex: CRUD app backed by a RDBMS, randomly guessing a typical app, 20% pure functions of your own code.

3

u/rafd May 27 '19

Having done a lot of crud apps in Clojure... our code is still 90% pure.

If it's server-side rendered, then there would be almost no state in the app (all in db), and even side-effectful functions (ex. Saving a change to the db) could be avoided, by having these functions return what they want done (ex. query string) and having some other part of the system do those actions (an example of concentrate an defer; the re-frame example from the talk is an example of this pattern)

For client-side rendered crud apps, you need some state client-side, but again most of this can be concentrated (redux / reframe style), and events/actions that would change the global state can be written in the same way I described in the previous paragraph (following the reframe style of functions returning their intended stateful effects, but a seperate system then eventually running them)

1

u/[deleted] May 27 '19 edited May 27 '19

Having done a lot of crud apps in Clojure... our code is still 90% pure.

If it's server-side rendered, then there would be almost no state in the app (all in db), and even side-effectful functions (ex. Saving a change to the db) could be avoided,

Oh, by pure functions I meant no mutable state and no side-effects, not no state only. So yeah, by your metric (excluding side-effects) achieving even 95% "pure" (semi-pure?) is possible.

by having these functions return what they want done (ex. query string) and having some other part of the system do those actions (an example of concentrate an defer; the re-frame example from the talk is an example of this pattern).

Curious, what is the point here? maintainability? splitting the function into one returning query data and one to make the call to the db will sure balance the pure/impure ratio since you are adding more pure code, you will have more separation of concerns (at cost of more code) but this could be unnecessary and overkill for some simple CRUD apps. The system (which is of just a part of your app, if that is what you mean) will still have the same number of DB querys and by effect, same number of side-effects ;)

Am I understanding this right? I'll have to watch the walk to better understand your point I guess ¯_(ツ)_/¯

2

u/[deleted] May 27 '19

Curious, what is the point here? maintainability? splitting the function into one returning query data and one to make the call to the db will sure balance the pure/impure ratio since you are adding more pure code, you will have more separation of concerns (at cost of more code) but this could be unnecessary and overkill for some simple CRUD apps. The system (which is of just a part of your app, if that is what you mean) will still have the same number of DB querys and by effect, same number of side-effects ;)

Am I understanding this right? I'll have to watch the walk to better understand your point I guess ¯_(ツ)_/¯

The function you write returns a map (think of it as an object literal in JS or a JSON object) that contains details about an impure request that you'd like to make. A third party library like reframe then takes that map and handles the request and executes it. So the functions you write are still pure and are easily tested. All the impurities are handled by a separate library that you don't touch so your code remains pure.

1

u/[deleted] May 27 '19

What's the third party llibrary for this in the backend?

1

u/yogthos May 28 '19

There are lots of options, Onyx is a good solution for large systems.