
Growing a Framework, Or, Clojure Made Easy - jacobobryant
https://jacobobryant.com/post/2019/grow/
======
dkersten
> 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.

Yes.

> 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 :(

~~~
jacobobryant
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.

~~~
dkersten
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.

