Summary: After exploring why frameworks and why not frameworks, I dive into the design priorities I think a web framework should have.
I’ve been exploring the idea of web frameworks. Specifically, I’ve explored why we use web frameworks and why we don’t like them. With that behind me, I’m thinking a lot about what a Clojure web framework should look like. These are the design priorities that I think are most important.
1. Learnable process
First and foremost, there should be a process for going from idea to code. It doesn’t have to be the best process. It simply needs to be good enough and learnable. The entire framework should be built around this process and should support this process. A programmer should be able to identify some functionality or change that would be valuable to them and, while going through the process, should only have to focus on that functionality. Concerns that are orthogonal should be taken care of by the framework.
To support that proces, the programmer must trade control for ease.1 HTTP allows for a lot of control, for instance, but the framework should make it easy. There are a lot of choices for how to do user authentication, but the framework should make it easy.
There are really two different types of functionality that the framework needs to support. The first is the type of functionality that a programmer would expect to already exist since it solves a common problem. User authentication and sessions fall into this category. My preference for how to make these things easy is to use a plugin system. The framework will set up hooks that plugins can register for and a user can discover and choose plugins that solve their need.
The second type of functionality is the stuff that a programmer wouldn’t reasonably expect people to have solved before. This is stuff that makes their application unique. The process should be clear and learnable for how to analyze their feature and turn it into code. The process is considerably more challenging to design than a plugin system. It will require a lot of experimentation to make it work.
2. Forward progress
The framework should prioritize forward progress over understanding. This is a pragmatic choice that might ruffle some feathers in the programming community. The framework should help you get the job done even if you don’t understand how it works. People often deride this as magic. But if the magic is simple and straightforward under the hood, what’s the problem? I believe people have been burned by poorly implemented magic and have thrown the baby out with the bathwater.
However, if this framework is successful, there will be many beginners who gain some expertise in Clojure while working in the framework. Many of these people will start to want the control and understanding that the framework doesn’t allow. That’s great! There are two options. 1. You can revel in the help the framework gave you along the way and start to dig into the magic for understanding. 2. You can ditch the framework and use your new knowledge to compose libraries the old-fashioned way. Both of these will be considered a success.
3. Limited scope
The framework should work for and prioritize the "80%" of cases. This really just means that the framework does its best to handle common cases but has an out when people try to apply it where it won’t work well. It cannot work well everywhere, so some "20%" of cases are traded for working well in the other 80. That 80% should scale well in all reasonable dimensions: code size, team size, number of features, and request load.
Over time, I hope that we can make it clear what the framework is good for, so people don’t choose it by mistake and get burned. I also believe we could provide workarounds outside of the framework for some of the remaining 20%.
The framework should use idiomatic Clojure and make use of Clojure’s strengths. There’s no reason to recreate Rails in Clojure. Rails already exists and is good at what it does. But Clojure does have a lot of strengths that would be interesting to have in a framework. Clojure’s values will definitely make it unique. The framework could be an introduction to the Clojure way of doing things.
There are a bunch of things that fall out of these four priorities. Backwards compatibility is important for supporting a healthy plugin ecosystem. The development experience should be good out of the box. You shouldn’t have to restart the JVM, even when including new libraries. The system should deploy out of the box.
I’m not sure a Clojure web framework needs to exist. I don’t know if it will help the Clojure community grow. But many, many people ask for one. They want it! The most common response is that Clojure prefers libraries that you compose yourself. This is a lot to ask of a beginner to Clojure. Having a framework does not invalidate that philosophy. In fact, I believe that a framework can help introduce people to the values of Clojure in a gentle way and be something unique.
This is different from the simple vs easy tradeoff we often see in the Clojure community.↩