> real and only difference between a library and a framework, is whether it introduces new concepts
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.
If you look above the unorthodox library/framework distinction, I think the criticism is about birthing new (inadvertently leaky) abstraction layers with new semantics to capture the specifics of the domain. Often with either esoteric words attached to supposedly novel patterns, and/or unconventional usage of existing terminology.
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"
> A library is something you call.
> A framework is some kind of application scaffolding that normally calls you.
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 framework is some kind of application scaffolding that normally calls you.
This. A framework relies extensively on inversion of control. It provides the overall software architecture of an application, and developers just inject the components called by the app to customize some aspects.
The word "concept" here is doing extreme amounts of heavy lifting here.
If I had to bring the point home I'd say that the author himself committed the very mistake he is warning against in that very sentence.
Frameworks define conventions and non-language features (language feature=data structures, callable functions, etc) that cannot be expected to be understood by simply reading the existing code and therefore need to be learned explicitly by reading the documentation of the framework. Frameworks are allowed to bend rules and expectations, because you're supposed to learn and be aware of them ahead of time.
This directly applies to the irresponsible use of the word "concept". The meaning of what he was trying to convey cannot be understood based on simply reading the sentence.
these things are hard, maybe impossible to define.
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.
Having been around in the industry for a while I'm seeing abstractions being misused all the time. Being guilty of it myself also when I was younger.
For me, the only purpose of an abstraction is to reduce complexity, but often times I'm seeing it being used to reduce repetitiveness, which often times replaces well understood more verbose code with less understood less verbose and less flexible alternative. For me, as a team lead, easy to read code is far more important than subjectively perceived elegant abstraction that everyone then has to learn how to use, and potentially fight with.
In many cases I have noticed people jumping into abstracting away a complexity right away, often times ending up with a leaky or inflexible abstraction. To those people I say, do that painful thing at least 10 times, then think about abstracting it away, since then you probably have some level of understanding about the pain you're trying to alleviate and all the nuances that comes with that domain.
Everywhere I've worked that uses DynamoDB, someone will invariably write a bunch of abstraction functions that become very annoying to debug, to add functionality, and can break an entire app if changed.
DynamoDB is admittedly very verbose, but it's almost always worth it to keep your CRUD operations written within the SDK rather than as an abstraction.
This was great. I enjoyed the alternative definition of "framework" as something that introduces new concepts (differing from the more common idea that it's code that calls YOUR code.)
This article reminded me of two classic pieces of writing.
The first is 20+ years old now: Joel Spolsky's law of leaky abstractions:
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."
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.
I never heard the term mini framework before but I like it. Applied within that context it makes sense. I was at Google 2011-2013 through an acquisition and witnessed some of what the author is describing. Actually something very specific comes to mind. There was a SQL library built on top of BigTable, Google's internal columnar data store, I think it was called Megastore [1]. The team implementing a new product decided to use it over BigTable directly because what it would mean for ease of development but it turned out as soon as they needed to do any data migration it was locking the entire database (or I guess the table? Aka BigTable). Anyway at the time this was a major issue and they had to revert to BigTable best practices as opposed to what this library was doing. Because essentially it was a library layer, not some new data store. Eventually Google built a different SQL based data store to replace the whole thing which you can see the open source version known as CockroachDB, which some ex-googlers invented.
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.
The modern variant of this is "platform vs service". At my previous company, it seemed like the only path to promotion was "platform" something something. So every org was in the middle of some way over-budget rewrite of their services as some big bloated platform thing, incompatible with every other team's platform, with less functionality than their old services offered. I don't know why leadership sees all these failures and seems to think "ooh, that's exactly what I want for my team too!" But you can't get a promotion if you're not platformizing.
Basically, premature abstraction / abstraction at the wrong boundaries coupled with the political power to force adoption of the bad abstraction. Yep. That’s an annoying attribute of working at a big corp. I prefer working in tiny teams and companies for this and many other reasons.
In my career, I've found that this problem crops up the most when a team is unable to make impactful changes to a system that they depend on. It's so much easier (and requires less collaboration and fewer approvals!) to build an abstraction over some core system than to actually fix the core system, even if fixing the core system is always the better choice.
I was very guilty of this as a young go-getter engineer! Why try to convince another team that something should be fixed if I can just paper over it?
I also think the author is understating how bad the original framework was. I've seen some of these and the "itchy points" are real true problems. The team supporting the framework decides that fixing the pain won't get them promo because it doesn't show up in any metrics, and certainly they won't accept your submitted improvements. Your only choice is to wrap it.
Of course, since their thing is a framework, your wrapper must be a framework too. (Is it possible to wrap a framework into a library?)
The end of the story is even sadder. You work on your replacement and wrapper, and oh no, the framework you are wrapping has problems or slowness because of the framework it depends upon!
** 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”.
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'm not sure I can accept the findings of this article. It seems to me that all the concerns and issues can be summed up to bad design. A mini framework should be designed to be easy to adapt and extend, and any layer on top should be just as easy to further adapt and extend.
That to me is the crux of this, "avoid frameworks that are difficult to adapt and extend".
I feel like “bad design” is too reductive. The article is an attempt to explain why it’s bad. What are the practical problems it introduces?
I think it could go a little further in explaining what I think the root cause of the issue is: the people developing this mini framework do not have the time or focus to turn it into a full framework. Compare to Django, Rails, React who, whatever your opinion, clearly have time and mission to build, test and document a framework for others to use.
The very nature of working for a SaaS company means your true goal is to build shit for your customers. Any internal tooling has to overcome this large hurdle to get the attention it needs to be able to truly thrive. And rightly so.
This is why I use Ruby on Rails. Shared constraints and boring conventions age better than clever mini-frameworks built around one team's mental model.
I wrote this article to reflect a pattern I observed (and hate) while working in Google, but I'm sure this is not a company specific problem. Would be interested to hear other people's stories :)
Thanks for the article. I generally agree that adding more layers in an attempt to "fix" lower layers is often a fools errand. And just a quick typo I noticed and I'm smugling in this comment: legondary->legendary.
Mini-frameworks would be dangerous at a place like Google where smart people think they are smart. I think they're heaven sent for smart people who think they're stupid.
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.
It’s a simple math problem. And it is also Conway’s law that says all software design follows the organization that built it—that is all software design is political.
A framework calls you. You call a library.
A framework constrains the program. A library expands the program.
It’s easier to write a library that is future proofed because it just needs to satisfy its contract.
It’s harder to write a framework because it imposes a contract on everything that depends on it.
Just like it is hard to write tort law without a lot of jurisprudence to build out experience and test cases, it is hard to write a framework from only one use case.
No one likes lawyers because they block you from doing what you want. This is the problem with frameworks.
However the government likes laws because they block you from doing what you want. Same with whomever is directing engineering that wants all other programmers to work in a consistent way.
Technically everything you have written is true. But the proliferation of frameworks is almost a self-reinforcing antipattern.
> No one likes lawyers because they block you from doing what you want.
Or even doing what you need to do.
Certainly, to the extent that a mini-framework is composed of more constraints piled on top of an extant bigger framework, mini-frameworks are, like swimming pools, attractive nuisances. "Hey, look, guys! This is so much simpler!"
> It’s harder to write a framework because it imposes a contract on everything that depends on it.
Judging by what people write and use, I'm not sure this is _exactly_ true. Sure, writing a _good_ framework or library is hard, but people accept piss-poor frameworks, and accept libraries that were designed to work in conjunction with a single framework.
> It’s easier to write a library that is future proofed because it just needs to satisfy its contract.
But the thing is that the library itself defines the contract, and it might be a piss-poor one for many applications.
There is some excellent code out there, and there is a lot of shitty code out there. I think the problem is social; too many people want to write code that is in charge. Now, maybe it's somewhat technical, in that they have used things that are in charge, and they were too big (leading to the mini-framework of the article) or they were otherwise not great, so this leads to yet another framework (cue standards xkcd cartoon) because they realize they need something in charge, but aren't happy with their current options.
And, of course, since the frameworks they know take a kitchen sink mentality, their new framework does as well. (Maybe it's a smaller sink, but everything needed is still shoved in there.) So there are yet more libraries that are tied to yet another framework.
Because writing good libraries that are completely framework independent _can_ be as challenging as writing a good framework. And when someone decides they need a new framework, they are focused on that, and making it work well, and since that drives their thought process, everything else the write gets shoved into the framework.
As a rule of thumb, "magic" is a code smell. Libraries should be preferred over frameworks whenever possible.
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.
I don‘t like dismissing technologies on the basis of being „magic“, since the magic could often just as well be called abstraction, and the line between them is often personal preference.
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.
In case "framework" is understood as something that calls my code and that forces me to write my code in a certain way, I totally agree.
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).
I had to look up BOCTAOE (But Of Course There Are Obvious Exceptions)
"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).
Idk how I feel about this, my experience is the opposite of this.
Most Spring (+Boot) projects have been far more painful to work with - numerous abstractions and deep and complex relationships between them just to support every technology and integration under the sun. Hard to work with, hard to debug (especially with proxies and how the DI works, alongside the nonsensical rules about how @Transactional works, e.g. how it doesn't if you call a transactional method from within the same component/service), sometimes performs like shit or leaks memory and migrations between major versions are a pain. We just spent multiple months migrating a project from an old Spring version to a more recent version of Spring Boot. It's a pain.
Compare that to Dropwizard: it is fairly stable and most updates are maintenance related. It uses a bunch of idiomatic packages from the ecosystem: Jetty, Jersey, Jackson, Logback, Hibernate/JDBI3, supports Liquibase or Flyway, there's also validation and views or whatever you want, but none of it is pushed down your throat. The docs are practical and more manageable just because it does LESS overall, the code is simpler and there are far fewer surprises. And because the logic is mostly just Java and there's no castle-in-the-sky bullshit with annotations, if you want to swap out HK2 for Dagger (if you still want DI), you can - which I think is good because Dagger also does a lot at compile time and avoids the whole Spring runtime injection can of worms altogether.
The size of a framework doesn't instantly make it good or bad, but oftentimes the bigger ones will be more difficult to reason about and sometimes the amount of abstractions gets out of hand.
> Introduce new concepts that doesn't exist in the original stack
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.
If you have a very specific product with limited scope, a micro-framework would work just fine. My experience in the real world™ is as such: people start with micro-frameworks and keep bolting on stuff to the point where it would have been better if they started with a macro-framework in the first place. At least there is better compatibility between framework components and a clear upgrade process. I agree with the "makeshift framework" terminology by the way. One way or another, my experience is that products that start with micro-frameworks, over time turn into a "makeshift framework" over time regardless. If the scope is clear and limited from the start, micro-frameworks are great. If unsure, micro-framework is a no go (for me).
Maybe I should have written it more clearly, but the mini-frameworks I described in the article are not makeshift -- instead they're permanent and stay forever, expanding as time goes, until being replaced by something else.
Frameworks promised faster development cycle, lest code and uniform codebase. But over the years, this proved to fail to deliver except in certain minority of cases.
I think modern programmers nowadays understand that it is much better to take the path of libraries than frameworks as it provides them with the same functionality of a framework(which is just a bundle of libraries), but with the freedom of implementing their code however they want, unlike wit ha framework, which forces certain structure and style as frameworks had to made certain decisions for the programmer in order to be a functional and comprehensive tool. This lack of freedom will usually bite most programmes LATER, when it is too late to go back and refactor code or change style and whatnot.
And that inherently also makes small frameworks even less usable than the larger ones.
I don’t blame the dev teams who ended up creating mini-frameworks. In many big tech companies, central framework teams are chronically underfunded. What I do blame are ego-driven mini-frameworks built by senior principal+ engineers that don’t actually solve real problems.
> Also, people lack the motivation to maintain existing stuff, because you don't get paid more or promoted doing this. Therefore, mini frameworks often die with the departure of the original authors, unless it has gained major adoption before that, which happens less likely than not.
I wonder how much of the problem stated in the article is actually a result of this resume-driven development style? The author says how the mini-framework was pushed by their engineering manager, I know it's cynical but I assume the real goal of the project was for the manager and engineers building the framework to have something fancy to show for their next promotion packet.
> Start fresh. Don't build a wrapper around the existing framework, build your own from scratch.
I don't know about this one. We have a mini-framework that's kinda GraphQL but not quite. REST-ish, but not quite. Weakly documented and constantly dealing with edge cases. Breaks all sorts of standard OpenAPI tooling because the schema returned is monstrous. Used to cause all sorts of issues with TypeScript and stack recursion. Requires a ton of code -- owned by one guy -- to make the OpenAPI doc generation to work correctly.
I keep thinking "Just use GraphQL" because it's basically GQL at this point...except jankier.
Sometimes someone genuinely has a clear vision that is superior to the status quo and is capable of executing it, improving quality, performance and maintainability. The challenge is distinguishing these cases from the muddled abstractions that make everything worse. This argument feels a bit like "no one gets fired for buying IBM." Blanket advice like this is an invitation to shut down thinking and stymie innovation. At the same time, the author is not wrong that imposing a bad abstraction on an org is often disastrous. Use your powers of reason to distinguish the good and bad cases.
This is one of the rare HN thinkpieces that's actually correct. You cannot remove essential complexity. You can shuffle it around, but it never goes away; you will have to deal with it. You can try to hand it off to someone else, like another team. But that actually makes it worse, because there's still some critical piece you depend on that's hidden behind the silo walls.
Rather than trying to hide things to "ease adoption", the correct answer is to educate people. Devs hate learning things. But once they learn the new thing, the pain goes away, and the results are better. The more you try to avoid it, the more problems you create later.
I think concrete examples of this are tricky because these "mini frameworks" only exist inside of a companies' proprietary codebase. My understanding of the concept is its an abstraction layer built on top of a more general abstraction, except the more general version is well documented and well understood by the company (for an internal framework) or even overall developer community (for something open source).
This. This. This. I currently work in a codebase where so much code has been abstracted away for “cleanliness” that it’s impossible to understand what code is actually running.
The worst is when three lines of completely standard code (immediately understandable to anybody inline) get „helpfully” lifted out into a utility function.
Somehow, somewhere there is a pleasant balance between DRY and non-DRY which is different for everybody. God forbid having a colleague who sees a thing repeating and slaps an abstraction over it at whatever cost because DRY!
Optimising for "code is easy to change" hits that balance well enough.
Start with a loose bag of functions. These are easy to compose in to larger pieces of functionality. And, this is key, easy to decompose when things change. Once this WET bag becomes a chore to change, the right abstraction might just show itself for DRY-ing out.
The right number of frameworks in a company is log10(number of employees). Go over this limit, and everyone needs to learn too many frameworks with too little support, examples, tools, and documentation.
> We often hear that "people leave managers, not jobs." But sometimes, people leave jobs despite loving their managers.
These two aren’t really mutually exclusive. Your manager may be extremely friendly and accommodating to you personally (as it seems like the author’s manager was), but part of a manager’s job is growing and supporting their reports with their career goals. If you’ve spent years majorly underleveled like it seems this person did, your manager is failing you. No matter how much of a nice person they might be, they’re not doing their job well if you’re attempting to grow at the company and aren’t succeeding.
So yes, I do think that this person still left a manager. He left a manager who wasn’t meeting the needs he had to stay at the company.
This reminds me a bit of using LLM frameworks like langchain, Haystack, etc., especially if you’re only using them for the chat completions or responses APIs and not doing anything fancy.
It's why I've always eschewed stuff like flask even when I felt like Django was going to be overkill. The problem is that, especially for web apps, everybody needs the same stuff. You need to handle cookies and forms and auth. You need to be able to inspect and manage your data. You need to be able to do tokens and password resets.
At the end of the day. You end up cobbling together a bespoke, worse version of Django anyway.
barrkel|2 months ago
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.
baobun|2 months ago
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"
exasperaited|2 months ago
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.
adpatersbad|2 months ago
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.
locknitpicker|2 months ago
This. A framework relies extensively on inversion of control. It provides the overall software architecture of an application, and developers just inject the components called by the app to customize some aspects.
forinti|2 months ago
Don't call us, we'll call you.
Leave the driving to us.
boxed|2 months ago
imo it's better to just figure out the definition in the current context, than try to force your own definition unto others. You can't anyway.
imtringued|2 months ago
If I had to bring the point home I'd say that the author himself committed the very mistake he is warning against in that very sentence.
Frameworks define conventions and non-language features (language feature=data structures, callable functions, etc) that cannot be expected to be understood by simply reading the existing code and therefore need to be learned explicitly by reading the documentation of the framework. Frameworks are allowed to bend rules and expectations, because you're supposed to learn and be aware of them ahead of time.
This directly applies to the irresponsible use of the word "concept". The meaning of what he was trying to convey cannot be understood based on simply reading the sentence.
davnicwil|2 months ago
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.
est|2 months ago
I think English is not OP's first language, framework here basically means wrappers.
k__|2 months ago
0x696C6961|2 months ago
oncallthrow|2 months ago
> A framework is some kind of application scaffolding that normally calls you.
There is no real distinction between these two.
erkok|2 months ago
For me, the only purpose of an abstraction is to reduce complexity, but often times I'm seeing it being used to reduce repetitiveness, which often times replaces well understood more verbose code with less understood less verbose and less flexible alternative. For me, as a team lead, easy to read code is far more important than subjectively perceived elegant abstraction that everyone then has to learn how to use, and potentially fight with.
In many cases I have noticed people jumping into abstracting away a complexity right away, often times ending up with a leaky or inflexible abstraction. To those people I say, do that painful thing at least 10 times, then think about abstracting it away, since then you probably have some level of understanding about the pain you're trying to alleviate and all the nuances that comes with that domain.
65|2 months ago
DynamoDB is admittedly very verbose, but it's almost always worth it to keep your CRUD operations written within the SDK rather than as an abstraction.
laike9m|2 months ago
simonw|2 months ago
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.
maayank|2 months ago
asim|2 months ago
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...
daxfohl|2 months ago
The modern variant of this is "platform vs service". At my previous company, it seemed like the only path to promotion was "platform" something something. So every org was in the middle of some way over-budget rewrite of their services as some big bloated platform thing, incompatible with every other team's platform, with less functionality than their old services offered. I don't know why leadership sees all these failures and seems to think "ooh, that's exactly what I want for my team too!" But you can't get a promotion if you're not platformizing.
christophilus|2 months ago
aefalcon83|2 months ago
lpghatguy|2 months ago
I was very guilty of this as a young go-getter engineer! Why try to convince another team that something should be fixed if I can just paper over it?
lostdog|2 months ago
Of course, since their thing is a framework, your wrapper must be a framework too. (Is it possible to wrap a framework into a library?)
The end of the story is even sadder. You work on your replacement and wrapper, and oh no, the framework you are wrapping has problems or slowness because of the framework it depends upon!
ozim|2 months ago
** 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”.
chanux|2 months ago
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.
bogzz|2 months ago
Are you the Internet of Bugs gentleman?
mircerlancerous|2 months ago
scott_w|2 months ago
I think it could go a little further in explaining what I think the root cause of the issue is: the people developing this mini framework do not have the time or focus to turn it into a full framework. Compare to Django, Rails, React who, whatever your opinion, clearly have time and mission to build, test and document a framework for others to use.
The very nature of working for a SaaS company means your true goal is to build shit for your customers. Any internal tooling has to overcome this large hurdle to get the attention it needs to be able to truly thrive. And rightly so.
didip|2 months ago
Those people have their own OKRs and promo desires.
Often times, sending patches to OSS orgs are easier.
So naturally, extension to the original framework happened.
anon5739483|2 months ago
laike9m|2 months ago
I can be found here:
https://x.com/laike9m
https://mastodon.social/@laike9m
hu3|2 months ago
PaulHoule|2 months ago
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.
sunir|2 months ago
A framework calls you. You call a library.
A framework constrains the program. A library expands the program.
It’s easier to write a library that is future proofed because it just needs to satisfy its contract.
It’s harder to write a framework because it imposes a contract on everything that depends on it.
Just like it is hard to write tort law without a lot of jurisprudence to build out experience and test cases, it is hard to write a framework from only one use case.
No one likes lawyers because they block you from doing what you want. This is the problem with frameworks.
However the government likes laws because they block you from doing what you want. Same with whomever is directing engineering that wants all other programmers to work in a consistent way.
zephen|2 months ago
> No one likes lawyers because they block you from doing what you want.
Or even doing what you need to do.
Certainly, to the extent that a mini-framework is composed of more constraints piled on top of an extant bigger framework, mini-frameworks are, like swimming pools, attractive nuisances. "Hey, look, guys! This is so much simpler!"
> It’s harder to write a framework because it imposes a contract on everything that depends on it.
Judging by what people write and use, I'm not sure this is _exactly_ true. Sure, writing a _good_ framework or library is hard, but people accept piss-poor frameworks, and accept libraries that were designed to work in conjunction with a single framework.
> It’s easier to write a library that is future proofed because it just needs to satisfy its contract.
But the thing is that the library itself defines the contract, and it might be a piss-poor one for many applications.
There is some excellent code out there, and there is a lot of shitty code out there. I think the problem is social; too many people want to write code that is in charge. Now, maybe it's somewhat technical, in that they have used things that are in charge, and they were too big (leading to the mini-framework of the article) or they were otherwise not great, so this leads to yet another framework (cue standards xkcd cartoon) because they realize they need something in charge, but aren't happy with their current options.
And, of course, since the frameworks they know take a kitchen sink mentality, their new framework does as well. (Maybe it's a smaller sink, but everything needed is still shoved in there.) So there are yet more libraries that are tied to yet another framework.
Because writing good libraries that are completely framework independent _can_ be as challenging as writing a good framework. And when someone decides they need a new framework, they are focused on that, and making it work well, and since that drives their thought process, everything else the write gets shoved into the framework.
narvidas|2 months ago
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.
Lukas_Skywalker|2 months ago
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.
hasley|2 months ago
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).
wouldbecouldbe|2 months ago
chrisweekly|2 months ago
"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).
boxed|2 months ago
You have to define the terms.
It's not clear how your statement above isn't semantically equivalent to "prefer good over bad" or something otherwise nonsensical.
KronisLV|2 months ago
Most Spring (+Boot) projects have been far more painful to work with - numerous abstractions and deep and complex relationships between them just to support every technology and integration under the sun. Hard to work with, hard to debug (especially with proxies and how the DI works, alongside the nonsensical rules about how @Transactional works, e.g. how it doesn't if you call a transactional method from within the same component/service), sometimes performs like shit or leaks memory and migrations between major versions are a pain. We just spent multiple months migrating a project from an old Spring version to a more recent version of Spring Boot. It's a pain.
Compare that to Dropwizard: it is fairly stable and most updates are maintenance related. It uses a bunch of idiomatic packages from the ecosystem: Jetty, Jersey, Jackson, Logback, Hibernate/JDBI3, supports Liquibase or Flyway, there's also validation and views or whatever you want, but none of it is pushed down your throat. The docs are practical and more manageable just because it does LESS overall, the code is simpler and there are far fewer surprises. And because the logic is mostly just Java and there's no castle-in-the-sky bullshit with annotations, if you want to swap out HK2 for Dagger (if you still want DI), you can - which I think is good because Dagger also does a lot at compile time and avoids the whole Spring runtime injection can of worms altogether.
The size of a framework doesn't instantly make it good or bad, but oftentimes the bigger ones will be more difficult to reason about and sometimes the amount of abstractions gets out of hand.
gaigalas|2 months ago
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.
anon5739483|2 months ago
laike9m|2 months ago
gethly|2 months ago
I think modern programmers nowadays understand that it is much better to take the path of libraries than frameworks as it provides them with the same functionality of a framework(which is just a bundle of libraries), but with the freedom of implementing their code however they want, unlike wit ha framework, which forces certain structure and style as frameworks had to made certain decisions for the programmer in order to be a functional and comprehensive tool. This lack of freedom will usually bite most programmes LATER, when it is too late to go back and refactor code or change style and whatnot.
And that inherently also makes small frameworks even less usable than the larger ones.
YMMV, but not really.
whoevercares|2 months ago
dbattaglia|2 months ago
I wonder how much of the problem stated in the article is actually a result of this resume-driven development style? The author says how the mini-framework was pushed by their engineering manager, I know it's cynical but I assume the real goal of the project was for the manager and engineers building the framework to have something fancy to show for their next promotion packet.
CharlieDigital|2 months ago
I keep thinking "Just use GraphQL" because it's basically GQL at this point...except jankier.
thefaux|2 months ago
0xbadcafebee|2 months ago
Rather than trying to hide things to "ease adoption", the correct answer is to educate people. Devs hate learning things. But once they learn the new thing, the pain goes away, and the results are better. The more you try to avoid it, the more problems you create later.
laike9m|2 months ago
huqedato|2 months ago
I have the impression that he confuses "obscure" with "mini". Either framework or library..
dbattaglia|2 months ago
unknown|2 months ago
[deleted]
riwsky|2 months ago
The entirety of the problem was that the design was bad! Adding a layer of abstraction is a design choice.
oncallthrow|2 months ago
The worst is when three lines of completely standard code (immediately understandable to anybody inline) get „helpfully” lifted out into a utility function.
oncallthrow|2 months ago
smetj|2 months ago
gherkinnn|2 months ago
Start with a loose bag of functions. These are easy to compose in to larger pieces of functionality. And, this is key, easy to decompose when things change. Once this WET bag becomes a chore to change, the right abstraction might just show itself for DRY-ing out.
lostdog|2 months ago
geoffpado|2 months ago
These two aren’t really mutually exclusive. Your manager may be extremely friendly and accommodating to you personally (as it seems like the author’s manager was), but part of a manager’s job is growing and supporting their reports with their career goals. If you’ve spent years majorly underleveled like it seems this person did, your manager is failing you. No matter how much of a nice person they might be, they’re not doing their job well if you’re attempting to grow at the company and aren’t succeeding.
So yes, I do think that this person still left a manager. He left a manager who wasn’t meeting the needs he had to stay at the company.
tucnak|2 months ago
willj|2 months ago
mkoubaa|2 months ago
petcat|2 months ago
At the end of the day. You end up cobbling together a bespoke, worse version of Django anyway.
lrvick|2 months ago
I am glad they were up front about this. Saved me a read.
dsadsadsadws1|2 months ago
[deleted]