Hacker News new | past | comments | ask | show | jobs | submit login
Growing a Framework, Or, Clojure Made Easy (jacobobryant.com)
3 points by jacobobryant on June 12, 2019 | hide | past | favorite | 3 comments

> Also, “complect” means “make more complex.”

If you define complex the way Rich does, then I guess it does, but more generally, complect means intertwine and decomplect therefore means something like tease apart (ie tease different concerns apart), which is how the word is used in the Clojure community.

> The latter point is why we don’t like frameworks.

That... is not why I don't like frameworks. Libraries also don't handle all use cases and, in fact, I would say that libraries (just because they are smaller) are even less likely to handle all frameworks, which is why I think the former (that frameworks tend to be "don't call me, I'll call you") is actually the important point, not that they don't handle all use cases.

The reason I think this is because if you are calling a library, its just a bunch of functions that do stuff for you: if it doesn't cover that one edge case, you can write a new function that does or call a different library. Its just functions. With a framework, there's typically more structure to how things interact and are connected, because if the framework calls you instead of you calling it, then you need to play by its rules so that your code fits the connectors provided to you by the framework. For this reason, when a framework doesn't cover your edge case, it can be much harder to implement said edge case while still making it fit the frameworks expected shape.

Its not that the framework is missing something you want -- nothing ever has everything you might need, not even libraries. Its that a framework expects a rigid structure so that it can call your code generically that makes it harder to implement the missing pieces yourself or use a third party bit of code that does.

> What’s really going on here is that frameworks are more likely to be complected.

Yes, different aspects of the frameworks concerns are intertwined. This makes it harder to insert your edge case logic. Libraries tend to be independent and you can add your logic without worrying too much about unrelated concerns.

> that feels like a framework

I've heard people say this exact same thing and I feel like it misses the point (its cargo culting). Its the same as how some people say not to do a thing because its OO and Clojure doesn't like OO: that's not true, Clojure fully supports the different bits of OO and encourages you to use them when it makes sense, it just discourages you use them just because OO. Framework-like things are fine for many things, what the Clojure community doesn't like is complecting things unnecessarily which frameworks often do. If something feels like a framework but isn't really complecting different concerns, then there's no issue in my opinion.

> Frameworks can be good if they’re both simple and easy.


> So how do you make big building blocks that stay simple?

I've been wanting to make a "framework" that's basically a collection of libraries with some adapter libraries and patterns to make them work together, but with nothing stopping you from swapping them out with others (assuming you write some thin adapter). Anything similar I've seen in the past always relied on code generation to tie libraries together, which I never liked. I'd rather have more small libraries that provide adapters and tie stuff together. Its still a somewhat unformed idea though, so maybe in reality it doesn't work.

> it makes my applications much more layered

While I do like the top-level logic to be small and easy to understand, I don't actually like too many layers. That is, the flatter the hierarchy is, the easier it is to replace things. If things are nested, its often hard to replace layers in the middle (because they need to "fit" on both the caller and callee side) but if they are flat (communicating through, for example, core.async channels) then there's a limited surface area where components touch each other, and, other components can often keep running. There used to be a great article on flat vs stacked hierarchies on my.opera.com but sadly there doesn't seem to be any wayback machine entries for it :(

Thanks for the feedback. Reading the post again, I realize that what I wrote didn't actually match up with what I meant. I meant more that the reason frameworks are often bad is because "Frameworks are more likely to not handle all use cases" AND "The effort required to patch a framework to accommodate the functionality you want is often higher than the effort to put all the libraries together yourself" (because of complecting).

Or worded another way, "Frameworks are more likely to not handle all use cases [that are within their scope]." Certainly a single library is not going to handle all the needs of your app, but it will hopefully handle the things it's intended to handle without too much need for modifying its behavior. e.g. if I need to use websockets, I can just use Sente without bending over backwards to make Sente work for my particular use case.

That's not very clear from what I've written though, so I'll update the article.

Cool. Sounds like we're in agreement then. Basically, libraries are less entwined so its easier to add them together or add missing bits yourself.

Applications are open for YC Winter 2022

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact