That is also true for "macro" frameworks.
> Wraps around the company/org-shared tech stack or framework
That is often also true for "macro" frameworks.
> Creators claim that the framework "magically" solves many problems, and push more people to use it
That is often also true for "macro" frameworks.
---
It is not clear from the reader's perspective what actually characterizes a "micro" framework. It's also not clear why the size is the issue here, when all complaints seems to be about design or quality.
Is googletest a micro or macro framework? Is google/zx a micro or a macro framework? Give us some clarifying examples. Actual things people can look for, not internal unknowable projects. There must be some exceptions too (silver bullet rules don't exist), mention them.
Also, rethink the title. Maybe "makeshift frameworks" is better terminology, as it more accurately reflects the problem that is described in the content.
The "micro framework" phase happens when that "macro" framework fails to deliver something. It happens way less often than a team picking a big estabilished tool.
However, the sizes never mattered. That is likely what causes the confusion in the first place ("it's large so it must have lots of things I want", "it's small so it must be easy to understand").
The real red herring is focusing on the size (or LOC, or any vague metric) instead of other more relevant architectural properties.
This isn't what is normally understood in software engineering by those terms.
A library is something you call.
A framework is some kind of application scaffolding that normally calls you.
You can use more than one library. You normally only have one framework in-process.
I found the blog post a little hard to parse. Is it an argument against wrapping frameworks, or wrapping libraries?
I agree that wrapping frameworks is fraught with danger. I can't quite agree for wrapping libraries. Wrapping libraries makes a lot of sense if you're only using a tiny fraction of the library functionality, the breadth of the wrapper's API is much smaller than the library's API, wrapping it enables you to substitute it (whether for a smaller / faster / whatever dependency in the future, or for testing, etc.), and so on.
For example I mostly agree with your calls/called definition but you also get self-described libraries like React giving you defined structure and hooks that call your code.
The later stuff adds other ways of doing the same thing but a library it remains.
That's as self described by the React team, and I think the consensus more broadly.
React's Wikipedia page says "React ... is a free and open-source front-end JavaScript library", and has no mention of Framework.
Why die on a hill that it "is" something it says it isn't?
There's plenty of guru who say that they are the reincarnation of Jesus and/or Buddha, doesn't mean that we have to take their word for it.
In the same vein, North Korea is officially the "Democratic People's Republic of Korea", even though it's obviously not a democracy.
Library is something that can be pulled off project and replaced with something else. There's no non-trivial project where replacing React with anything would be possible. Every React web app is built around React.
Framework can be more or less modular, Angular or Ember choose to be 'battery included', while React choose to be more modular, which is simply choosing the other end of the spectrum on the convenience-versus-flexibility tradeoff.
React ostensibly only care about rendering, but in a way that force you to structure your whole data flow and routing according to its rules (lifecycle events or the 'rules of hooks', avoiding mutating data structures); No matter what they say on the official website, that's 100% framework territory.
Lodash or Moment.js, those are actual bona fide libraries, and nobody ever asked whether to use Vue, Angular or Moment.js, or what version of moment-js-router they should use.
I think you can probably see that distinction already, but to spell it out React is described as a library precisely because it does just one thing - the view - and leaves it to you to figure out the entirety of the rest of the stack / structure of your app.
Framework, at least to me, but I also believe commonly, means something that lets you build a full application end to end using it.
You can't do that with React unless your app is just something that lives in the browser either in-memory or with some localstorage backing or something. If that's your app, then probably I'd agree React is your framework per se, but that's hardly ever the case.
By the way, back to my original point, I still do think these things are impossible to define and in lots of ways these terms don't matter - if it's a framework for you, it's a framework - but I just had to defend my position since you described it as absurd :-)
It is best described as a pattern implementation (observer / pub-sub).
Example Node.js EventEmitter usage:
const EventEmitter = require('events');
emitter.on('data', handler);
emitter.emit('data', value);
-----------
You explicitly instantiate it. You explicitly register listeners. You explicitly emit events. It does nothing unless you call it. There's no lifecycle, no main loop, no required structure.
EventEmitter is not a framework because it does not define application structure. It doesn't own the program's control flow. It doesn't decide when your code runs (beyond callbacks you register). It does not enforce conventions or architecture.
People sometimes call it a framework incorrectly because of two sources of confusion:
1. Callback-based APIs feel like inversion of control. But this is partial IoC, not framework-level iOc.
2. It is often embedded inside frameworks. Examples: Express routes, React synthetic events, Electron internals.
The promise is to simplify and unify things but as noted, such efforts often have the opposite effects.
"Teams are struggling with properly adopting FooTech - our FooBarTool wraps it in a beautiful package and magically solves everything with a single command and one config file"
"We should template all this yaml"
> A framework is some kind of application scaffolding that normally calls you.
There is no real distinction between these two.
Don't call us, we'll call you.
Leave the driving to us.
I think I broadly agree with this. In essence, libraries don't impose an application-level life cycle. Frameworks, generally, do.
The rest of the article, I don't know….
The most successful, long-running app I maintain has a mini-framework that allowed me to assemble what I need piecemeal rather than relying on any off-the-shelf framework that would have been obsoleted several times over in the seventeen-year lifespan of this code.
I guess about one in three things I do in it require me to dip into my framework code to look at it, but this is mostly to remember how it works! About one in five things have required me to make a small progressive change.
Twice in its lifetime a core component has been swapped out (mailer and database library).
And twice in its lifetime, because it is beginning to converge on a general web framework, I have considered porting the code out of it and into a general framework, which might make it easier to hand over. One day, I suspect, something will break compatibility in a way that makes that the sensible route, but the code works, fast, has a pretty obvious set of abstractions, and there are implicit examples of everything it can do in everything it already does.
Almost all articles like this start out with "here is a thing I claim is a generalised problem that I am sure you should not do", that is a well-meaning but false generalisation, and is then caveated to the point where no new point is being made.
Underneath they are always: don't write bad code. If you do, learn from it.
If I'd followed the advice of this article when I started this project, I would by now have rewritten the entire thing more than once, for little gain.
Much more concise and much more sensible: consider whether your additional levels of abstraction have value.
But do mini frameworks have value? Sure they do, especially if there is setup and teardown that every function needs to do.
The best assumption to start with is that adapters are bad by default, because they are an unnecessary layer to maintain (and potentially a point of failure and bottleneck depending on what they are and do). Then, make the argument for the adapter as a guilty until proven innocent case.
If you can make a solid case for it, fine. There are many solid cases for adapters, e.g. drivers for a database or hardware.
Never write an adapter that you can handle more scalably, flexibly, and almost as easily by calling something directly.
A toolbelt of small utility-like composables are often easier to maintain and reason about. This results in added explicitness (i.e. less magic, fewer surprises).
Personal experience shows that the immediate efficiency gains of a framework often get diminished in the face of all the hacks people introduce later, just to work around the remaining 10% of cases that the framework did not anticipate or traded-off against.
Please note this is a comment based on personal experience and professional preference.
BOCTAOE.
The abstracted-away logic in a Laravel application can either be called magic or abstraction, but so can the optimizations of a database query planner.
I think often you still need to know the underlying mechanism, but it is still useful to get the innards out of the way.
The problem is that your code has to work within this abstraction and can only solve problems covered by the inventors of the abstraction.
Spring Boot and other similar frameworks come to mind; by forcing huge amounts of indirection you lose a lot of visibility of your call stack because the convenient "glue" code is now orchestrating everything at runtime, but that code isn't yours, and it isn't easily inspected or fixed.
And I think twice before I use a framework. Frameworks enforce a certain way of programming which you can never be sure to match the problems you will have to solve in the future. Libraries don't do this - at least not to the extent of a framework. Libraries are composable building blocks.
Nevertheless, there may be applications where frameworks are beneficial (e.g. GNU Radio).
"Good magic decomposes into sane primitives" highlights an essential distinction: not all magic is bad (but it's not always clear at first which kind of magic is in play).
Moral of the story, abstractions always fail the edge cases, especially at scale. But when the entire eng org adopts something, it works much better. Everyone has to be bought in. Which at Google scale is hard.
https://research.google/pubs/megastore-providing-scalable-hi...
The worst is when three lines of completely standard code (immediately understandable to anybody inline) get „helpfully” lifted out into a utility function.
At the end of the day. You end up cobbling together a bespoke, worse version of Django anyway.
This article reminded me of two classic pieces of writing.
The first is 20+ years old now: Joel Spolsky's law of leaky abstractions:
https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-a...
One of the reasons these mini-frameworks lead to problems is that they leak. They don't cover every case which means you inevitably have to fully understand what they are doing for you in order to debug them or work around their limitations. Your cognitive load goes up!
The second is Will Larson's "Migrations: the sole scalable fix to tech debt."
https://lethain.com/migrations/
The OP complains that they've never seen a technology migration at Google that finished. Will advocates for migrations to be driven by a team that both coaches other teams on the migration and then, crucially, finish the job themselves to make absolutely sure it gets done to 100% completion.
And it is very easy to start feel like you know you have a great abstraction when you don't. And unfortunately it's easy and fun to make abstractions, kinda like making babies. And has kind of similar weight to it too.
I just have to say.. stay safe out there.
Are you the Internet of Bugs gentleman?
Distributed (multithreaded, concurrent, ...) systems are a counterexample that are highly vulnerable to snake oil. In normal software it makes sense to build up from a small set of intellectually coherent primitives. In those cases you inevitably end up with poor performance and usually reliability if you try that. Java started out with a snake oil approach to threading (synchronized!) and Doug Lea talked some sense into them and now we have java.util.concurrent which has a rich set of primitives which are pragmatic and meet the real requirements, not a vision of purity.
On the other hand, If it was a mini-framework to pound out numerous not-so-simple HTML form applications it could greatly enrich your life and your team's.
** mini-frameworks is a realization of the creator's mental model, but it's not everyone's mental model**
People being smart enough to make their own understanding work well - but not smart enough to see they are just pushing their way of doing things and not working on something “generally understood”.
I have the impression that he confuses "obscure" with "mini". Either framework or library..
laike9m•2h ago
I can be found here:
https://x.com/laike9m
https://mastodon.social/@laike9m
hu3•1h ago