You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[IntelliJ IDEA / Cursive Run Configuration](#intellij-idea--cursive-run-configuration)
22
-
-[Unit Testing](#unit-testing)
23
-
-[Building Fat Jar and Running It](#building-fat-jar-and-running-it)
24
-
-[Next Steps for Myself](#next-steps-for-myself)
25
-
-[For a Clojure Learner](#for-a-clojure-learner)
8
+
-[Manual State Management](#manual-state-management)
9
+
-[State Management Using Integrant](#state-management-using-integrant)
10
+
-[Comparison](#comparison)
11
+
-[Personal Experiences](#personal-experiences)
26
12
27
13
28
14
# Introduction
@@ -47,8 +33,44 @@ Simple Server is implemented using [Clojure](https://clojure.org/) and [Ring](ht
47
33
48
34
# Application State Management
49
35
50
-
So, in this third Simple Server version I wanted to compare the workflow using no particular state management library (see: [simple-server](../simple-server)) and this new Simple Server version with the [Integrant library](https://github.com/weavejester/integrant). You can read my experiences without using any state management library in that previous exercise, see [README.md](../simple-server/README.md) in chapter "You Can Do It Without Application State Management Libraries". In this new README file in this chapter I focus on my experiences using Integrant.
36
+
So, in this third Simple Server version I wanted to compare the workflow using no particular state management library (see: [simple-server](../simple-server)) and this new Simple Server version with the [Integrant library](https://github.com/weavejester/integrant). You can read my experiences without using any state management library in that previous exercise, see [README.md](../simple-server/README.md) in chapter "You Can Do It Without Application State Management Libraries". In this new README file in this chapter I focus on my experiences using Integrant and comparing these two strategies.
51
37
52
-
TODO: Experiences.
38
+
## Manual State Management
39
+
40
+
In the code below you can see how I did state management manually in the previous exercise:
41
+
42
+

43
+
44
+
So, the core of the state management in this manual solution is the server atom which is just a map with three keys (in defonce since if we reload the namespace in REPL we don't want to lose the atom and the web server instance). The ```:server ``` key holds the actual server instance, as you can see in ```start-web-server``` function. The ```stop-web-server``` function stops the server instance and resets the atom value. The ```reset-web-server``` function just call these two functions. And we have a custom state management implemented without any state management libraries. You can easily reset the web server in REPL using the reset-web server function.
45
+
46
+
The above mentioned manual state management solution is just fine at least with smaller implementations that have just 1-2 states (e.g. just the web server - whether it is listening connections or not). But if you need a more complex state management, possibly with dependencies between different parts of the state, then you might benefit using a dedicated state management library.
47
+
48
+
## State Management Using Integrant
49
+
50
+
Let's see how the same thing could be implemented using Integrant. The first part of the solution is pretty much the same, we need to have methods for starting and stopping the web server:
51
+
52
+

53
+
54
+
But this time we don't need any atom to store the web server instance since we let Integrant to take care of state managent - therefore our ```start-web-server``` function starts the web server and just returns the created (and started) web server instance.
55
+
56
+
Then the Integrant specific part.
57
+
58
+

59
+
60
+
We first create a system configuration (function ```system-config```). Basically the only thing here that we really need is the ```::web-server``` part which has the initialization values for our web server. Then we have integrant hooks ```ig/init-key``` and ```ig/halt-key!```. These methods are called by Integrant when we reset the Integrant managed state of our application. As you can see, we just call the previous functions ```start-web-server``` and ```stop-web-server```.
61
+
62
+
In REPL driven development you can then use three ```integrant.repl``` namespace functions:
63
+
64
+
- go: start the system (in our case start the web server)
65
+
- halt: halt the system (in our case stop the web server)
66
+
- reset: reset the system
67
+
68
+
## Comparison
69
+
70
+
So, which one is better? I'm not sure. For smaller applications it might be feasible just to implement your custom state management - and one less dependency in your ```deps.edn``` file. But if you have a bigger application with a lot of states and dependencies between different parts of the states then you might benefit using a dedicated state management library. I actually ran a very informal gallup in Metosin Slack regarding whether Metosin programmers favor custom state management or use some state management library. Two developers favored custom state management, others some 8 guys (which clicked either emoji in Slack) favored state management, all of them Integrant. Considering that these guys are pretty seasoned Clojure programmers I would say that you won't miss your target if you choose Integrant.
0 commit comments