Why I Hate Frameworks (2005)
factoryfactoryfactory.net
factoryfactoryfactory.net
When one of the sub factories breaks down, or when a saw came out where a hammer should have, the carpenter might find themselves awfully tempted to take a ball peen hammer to someone's face. But sadly, they don't know where to get one or how to use it.
Sometimes I wonder if that's the point of all this complexity. (EDIT: I mean really excessive complexity as alluded to in the article with factory factory factories, or 100 microservices all in different programming languages just for a website (true story))
I mean who actually gets to decide what sort of approach to use, and what are their incentives?
The senior in the team is in charge of deciding what approach to use. The senior's (personal) objective is not to get fired, maintain their position as the most senior so they can get the payrises and promotions, etc. So they sort of have an incentive to choose something that is going to be easier to understand for them than for others e.g. juniors, a kind of "moat" to protect their position of power and high salary getting attacked by lower paid juniors who don't yet have the experience to understand complex abstractions over manual tasks they haven't yet done themselves.
I mean obviously that's not a kind thing for a senior to do, nor something that's in their employer's interest, but on the other hand it is rational given their incentives...
You want to pick a set of tools which will help you get the job at hand done most effectively. It’s often easier and cheaper to hire or train a team to use a framework or library than it is to reimplement the functionality that library provides from scratch. Eg, if I was building a big single page app, I’d rather use react than reimplement react’s functionality, badly, on top of jquery or something.
Projects last years. An engineer with solid fundamental knowledge can get up to speed with most of these tools and libraries in a few days. The math usually checks out to make them worth using.
But I still acknowledge your point. There are plenty of terrible senior engineers out there making bad choices on tools. And there is a lot of damage a bad tool choice can make to a project. Libraries and frameworks rarely tell you when they’re buggy messes. And coworkers rarely tell you when learning some new tool feels beyond them. So I’m sure there’s plenty of projects out there trying to use fancy tools which have a net negative effect on team productivity.
I suppose what I meant was really excessive framework usage, the type of which is alluded to in the original article with the factory factory factories etc. I shall edit my comment to clarify that.
The whole factory factory factory thing feels separate to me. I think of it as a disastrous, productivity destroying meme that spreads through words like “hidden implementation” and “one interface, multiple implementations”.
You don’t to be a senior to be vulnerable to the mind virus, though once it gets into the heads of your senior engineers your whole team or company can be in peril. The disease has claimed entire programming communities with its cloying rot. (Dare I say the J-word and invoke its wrath?). As an individual, it can take years to recover from these ideas. Some poor hacker souls never recover.
GitHub Issues usually gives you a good insight, into what problems exists and whether they get fixed, or not.
(as a senior, you likely know, but others reading this, maybe not)
IMO the better metric is how many outstanding unmerged pull requests exist. If there are too many this means that bugs exists and they aren't getting fixed.
I'm starting to think I work in a toxic environment.
Software design doesn't have a formal theory that defines optimal design and there isn't any empirical evidence either.
We know the shortest distance between two points because we have a formal theory that defines it. Because software design has no such thing, everyone is making shit up.
Doesn't matter how intelligent you are. If the thing that's being designed can't be quantified it's the wild west. Those brains are focused on optimizing things we have no idea how optimize and things we can't even measure.
Their vision? Like from a dream they had? That was the end of their contribution? Share the vision and play no role in managing anyone building it out? Nice. That honestly sounds like someone that needs kneecapped.
The responsible for executing should have a day in a lot more things, else it's gonna be a blame game.
Get all the credit when things go well, deserve all the blame when things don’t. Because it’s also poor management when your workers aren’t properly managed and thus don’t properly build out your vision.
"The senior in the team is in charge of deciding what approach to use."
The only thing I'd like to add is that the senior is rarely free in their decision. It is often an unspoken choice dictated by culture and upper management. (Ironically it's worse in companies with technically apt management.)
You work in a Java shop, everything else than the couple of standard Java frameworks will be an uphill battle and you bear all the risk to get your problems blamed on your framework choice.
This is not an excuse of course, but unfortunately our choices are rarely by technical merit alone.
It's cultural. Complexity is often part of developer culture, period.
I've even had a non-technical CEO asking to use Angular around 2013-2014. Developer culture is leaking.
Also a lot of accidental complexity comes from the business/staffing side. So, you need to have 200 developers because some high-up said so? Better jump on that Kubernetes and Microservices train. Are the business processes more complex than they have to be because of inertia and disorganization? Let's spend a million bucks customizing that off-the-shelf ERP system.
I’d even say no one seems to realize that the default tendency for a developer is to complexify. One either needs to learn to keep things simple by experience or is forced to it by constraints like time.
The senior's (personal) objective is to add fashionable buzzwords to the resume/CV so in a year they can hop to another company and get paid 20% more. You get a pay rise and a promotion a lot quicker by changing jobs than sticking around.
No Kubernetes experience? Just unnecessarily add Kubernetes to your current project. Now look for that Kubernetes job! The worst thing is, this is totally rational behaviour.
Right now it’s just firefighting every second of the day.
The best way to get them to work the right way is to use a framework that incentivizes it. If doing things wrong is made harder, and doing things right is made easy, everyone wins.
No company will pay you for several years just to learn complexity theory, write sorting algorithms, study schedulers, rewrite UNIX tools, understand hardware architectures, etc... They want you to be productive right away, and the shortest path is just to follow recipes with the latest framework.
That's the point of education, universities teach you what you won't learn on the job. So that when you finally get to work, you will have a better understanding of what you are doing.
They argue that bootcamps and quick courses are enough, or that chatgpt exists now so programming is a dead profession.
I disagree, I think I've had a lot of use from having had education… but I might be biased. But I've had to explain things occasionally.
If you plan to be a programmer all your life, and a journey-man one at that, then feel free to learn-programming-in-21-days.
If you're planning a career in software, then I think understanding fundamentals (database normalisation, the Order of a solution, the ideas of Coupling and Uncoupling, memory usage versus performance, the impact of CPU cache, multi-threading safely, operating system task priorities, compilers, and a good few more things that underpin the science behind building software, then a degree is helpful.
Not because of the books, you can get those at home, but because of the structure (ie the path through the carriculim) the mentorship from professors, TAs and so on, and most of all the exposure to your peers - the wonder of collectively pushing each other to explore beyond the curriculum, beyond just this week's assignment.
Most of all it teaches intellectual curiosity- that spark some people have to see something in code they don't recognise, understand the novelty of it, and go and find out about it. It's easy to keep up because you have the structural foundations to absorb new things all the time.
ChatGPT can't do the things I do, and even calling it ChatGPT is a shallow understanding of why not. Broadly speaking LLMs are a tool I can use to learn new things, which is great, it knows how to weild many kinds of hammer. But it doesn't understand the nuance and context of building a whole building. One which has never been built before.
Precisely because LLMs are good at regurgitating the past, but understand literally nothing, they only replace programmers who are good at regurgitating the past (writing code) but understand very little about what that code -means- (as distinct from what it -does-)
Of course each College is different, and YMMV, but if you gave the time, and resources, and opportunity to do a formal degree, then I think it worth it in the long run. But like most things in life you get out what you put in. The curriculum is just the hint of a starting point to what you learn there, don't go to "be taught", go to suck the marrow from each moment, to actively "learn" from the challenges you set yourself.
This contributed to a junior coder market where people are not ready.
I only found a handful of resources out there which are really preparing everyone for a long journey.
Long gone are the promises of a $500k job after 3 months of studying...
No, they never did. But to stay with the hammer metapher - young carpenters would indeed learn on the job, how to use a hammer and all the other tools. But they would not get the same pay (or even no pay and just food and housing).
In general it used to be way more common, that companies invested in peoples learning, expecting payoff much later. But with high mobility nowdays, they seldom think it is worth it anymore. You teach and then they thank you and move on.
The high mobility part is overblown.
The biggest teaching factories are also the ones who spend exorbitant amounts on bureaucracy and accessories while gratuitously taking advantage of young people eager to prove themselves, having little to no responsibilities and no understanding of the professional world. Their whole shtick is to find suckers willing to stick after, all the while taking advantage of naïve youth.
The vast majority of people don't move if you keep their pays on actual market rates. Interviewing is a chore. Moving for jobs is a chore. Most people hate getting out of their comfort zone. Yet, many will push individuals to 'prove themselves' first, having any pay raises lag behind for several years, where individuals find themselves getting their promotion's worth of money only after moving to a different company.
It's the companies that have optimized for this behavior and chosen internal promotions should be few and unrewarding. Not the other way around. God forbid they reap what they sow.
You mean you tell them you will teach them, require them to have the skills to begin with anyways, work them like any other employee but with a fraction of the cost promising them full employment at the end, and at the end thank them and tell them to move on?
(keeping the first person tone of your post)
In fact programming is just a tool used to implement CS ideas and demonstrate their application in the real world.
In my degree we spent maybe the first 6 weeks on actual learnjng-to-program (in turbo pascal.) Then another later on in Scheme. In 3nd year we did C, I don't recall what instruction we had there - maybe a week? Then 2 weeks in 3rd year where we did 10 different languages in 10 days.
Language was considered a distraction from the science part.
No, it's not reading books about swinging hammers. We were learning about physical forces on wood, and by wood, and other construction materials. We learned the difference between a spice rack, the drawer, and the 40-floor building to house the spice rack.
Sure we wielded the hammer like Thor. But the focus was on the hammered not the hammer.
Computer Science is akin to learning how to forge a hammer, what materials to use in said hammer, and then determining what size and shape is applicable for a given task.
Sometimes the specified hammer is made. Most times it is not.
"Swinging hammers" is rarely, if ever, considered.
After a career completely unrelated to manufacturing I've come back to basic metalwork as a hobby. What interests me is working with non-computer driven tools like lathes and mills.
What really surprises me is how much can be achieved just with hand tools like saws, files and chisels. I have books on filing as a way to shape metal by hand.
This is worth knowing because sometimes it's sometimes the quickest way get something done. Especially, when the first part of an alternative process would be "order tool X from the internet".
So it goes with solving problems with software. It's sometimes quicker to implement something I learnt on my second degree in CS than to spend time searching to see if a well supported library covers exactly what's needed for a very specific, temporary use-case.
You work part time at a company and go part time to school, combined thats between 35 and 40 hours a week. You don't get paid that much during that time, but if someone pays for your room it's enough.
Without going that route you literally don't get a full paid job.
For a professional MBA that's taken over a department, it's not so much that they won't pay you to learn what's not definitely part of the job but that they can get away without doing so. It appear superficially to be the low risk option.
It's the same reason that manufacturing gets outsourced instead of invested in as a core competency that sets you apart from the competition.
To a lot of people anything that makes the numbers go in the right direction is what's important. They'll even pretend that the sole fiduciary duty is to raise short-term profits at the expense of long term value.
When so many of the world's largest corps are now hollowed out marketing operations reselling generic products, it's hard to argue against using the latest trending framework.
(edit: I think I misread the comment I replied to and am now in the process of maybe figuring that out downthread.)
I frankly still can't tell as that's use of "fallacy" to describe "people picking up frameworks without fundamental understanding" is apparently extremely confusing to me as it isn't in the form of a fallacy--like, is the fallacy that this happens? that this is a problem? is it the thought which leads people to do that? etc.--so I automatically added stuff to the sentence to make it work and maybe I did it wrong.
Some reasons (based on my experience):
- University classes were either very low level, or using some new framework to increase your employment prospects
- All the experienced devs would hop jobs every few years, leaving less opportunity for mentorship.
- Lack of convenient resources for gaining base knowledge. Googling "how to make a todo list webpage tutorial" will always have articles using the latest web frameworks, for instance.
(Not really anyone's fault, a good engineer has know where to go for the right information. But as a junior without that skill it's easy not to get good information.)
My personal strat when learning a framework is sometimes building what I want without it, running into the common problem patterns, and then looking at how a framework solves it.
It's very time consuming so I only do that for personal projects, but I think I've learned the most base knowledge for really groking a framework doing that.
That colleges aren't teaching this as a first-rate topic is a real failure. This is, in my opinion, the most important skill any engineer should have.
My main driver is Ruby - I have a good feeling about code that can be refactored to use Enumerable more effectively; but I also know that Enumerable offers so much that I might be expecting too much of it. So 80% of the time I point to a method that solves the exact problem and the rest of the time I know how to write it differently.
"Why do you know about filter_map?"
"Because people were confused about reduce and each_with_object and map and maybe you just want to loop through non-nil objects in one pass"
I think students at all levels tend to avoid this, and there isn’t stomach to fail them for it on the academic or family sides.
How to ask the best questions
How to find the answer to such questions
Totally undervalued skills everywhere
...and that's how the the factory factory factory also provides immediate safety and security benefits!
/s
Why I Hate Frameworks (2005) - https://news.ycombinator.com/item?id=28920095 - Oct 2021 (296 comments)
Why I hate frameworks (2005) - https://news.ycombinator.com/item?id=12635142 - Oct 2016 (66 comments)
Why I Hate Frameworks (2005) - https://news.ycombinator.com/item?id=9203959 - March 2015 (63 comments)
Why I Hate Frameworks (2005) - https://news.ycombinator.com/item?id=6542817 - Oct 2013 (37 comments)
Why I Hate Frameworks (2005) - https://news.ycombinator.com/item?id=6283601 - Aug 2013 (118 comments)
Why I Hate Frameworks - https://news.ycombinator.com/item?id=2787525 - July 2011 (100 comments)
Why I hate frameworks (2005) - https://news.ycombinator.com/item?id=1533274 - July 2010 (55 comments)
Why I Hate Frameworks - https://news.ycombinator.com/item?id=431786 - Jan 2009 (125 comments)
Why I Hate Frameworks - https://news.ycombinator.com/item?id=95722 - Jan 2008 (18 comments)
----
Edit: related ongoing thread:
A FactoryFactoryFactory in Production (2017) - https://news.ycombinator.com/item?id=36638525 - July 2023 (62 comments)
Normally we downweight follow-up posts but that thread is quite good!
Just looking at this listing, without looking at the comments in each one, this seems to have a sustained resonance.
Maybe I’m biased–it certainly resonates with me!
Or maybe thats just me.
I have since come to believe that this is a trap that many people fall into.
Even a colleague of mine at my current job might be sort of in this track himself at the moment I think. And I don’t feel that he is interested in listening to me at all. Even though we are supposedly on the same team.
I think these kinds of things, when you fall into the trap, is something that you have to eventually realise on your own why it was a bad idea.
Meanwhile I am at the verge of quitting because I find it frustrating that we are working on this thing where it seems I am not being listened to and we are implementing something in a way that I recognise from my own past mistakes as a patently poor way of going about things.
But at the same time, I love the company I work for, and the pay is really good, and I am scared that if I quit I won’t find another job for a long time that will pay well enough to support myself and my girlfriend and our expenses.
Anyway. Point is, I agree with you, there will always be people trying to build these frameworks and what have you.
There’s a seductive aspect to abstraction and generalization. But I don’t even think that’s what makes these things so bad in practice. It’s other, more trivial things, like losing stack traces, imposing of types and flow control that the author didn’t anticipate, but pains the user tremendously.
We don’t really have good measurements for - and often overlook those aspects - which causes us collectively to suffer only after a great commitment of time and labor. I’m pretty convinced that complexity isn’t just mentally confusing but actually hard measurable, as long as we have language to describe it and a well tuned skepticism towards unnecessary layers of indirection. Function coloring is one such attempt, imo, at explaining the great costs of something which looks innocent.
If you only know how to code within the constraints of the framework, you're gonna fail for anything non-trivial. If you try to ditch frameworks entirely, same deal.
The following 39 titles have appeared on the front page 5+ times, based on an exact text match, excepting a year indicator in parentheses, e.g., "(2023)". Note that the apostrophe glyph differs in the 2nd & 3rd entries for Peter Roberts AMAs:
1 10 OpenSSL Security Advisory
2 7 I'm Peter Roberts, immigration attorney who does work for YC and startups. AMA
3 7 I’m Peter Roberts, immigration attorney who does work for YC and startups. AMA
4 7 Richard Feynman and The Connection Machine
5 7 The Architecture of Open Source Applications
6 7 The TTY demystified
7 7 Why GNU grep is fast
8 7 You and Your Research
9 6 Bit Twiddling Hacks
10 6 Dictionary of Algorithms and Data Structures
11 6 How to be a Programmer: A Short, Comprehensive, and Personal Summary
12 6 The Bipolar Lisp Programmer
13 6 Why Lisp?
14 5 A Primer on Bézier Curves
15 5 A regular expression to check for prime numbers
16 5 Advanced programming languages
17 5 Akin's Laws of Spacecraft Design
18 5 Ask HN: Idea Sunday
19 5 Ask HN: What are you working on?
20 5 Beej's Guide to Network Programming
21 5 DNA seen through the eyes of a coder
22 5 Data Structure Visualizations
23 5 How Software Companies Die
24 5 How to Read Mathematics
25 5 How to Write a Spelling Corrector
26 5 Learning Advanced JavaScript
27 5 Notation as a Tool of Thought
28 5 Statistical Data Mining Tutorials
29 5 Structure and Interpretation of Classical Mechanics
30 5 Teach Yourself Programming in Ten Years
31 5 Ten Rules for Web Startups
32 5 Terms of Service; Didn't Read
33 5 The Book of Shaders
34 5 The Scientist and Engineer's Guide to Digital Signal Processing
35 5 The Tao of Programming
36 5 The case of the 500-mile email
37 5 Who Can Name the Bigger Number?
38 5 Why Lisp macros are cool, a Perl perspective
39 5 You can't tell people anything
A further 67 titles appear 4 times each, 259 appear 3x, and 2,120 appear twice.("Front page" here means the archived HN front pages under the "past" link at the top of the page here.)
Data through 2023-06-21.
I could run the analysis based on the URL rather than title, but that would require parsing the raw HTML which I've yet to do.
Possibly related: have you considered making your aggregator ignore punctuation and case in addition to the year indicators?
"Why I Hate Frameworks" does appear six times on the front page, though with case and phrasing variants which mean that an exact text match won't pick it up:
Why I Hate Frameworks
Why I Hate Frameworks
Why I hate frameworks (2005)
Why I Hate Frameworks
[dupe] Why I Hate Frameworks (2005)
Why I Hate Frameworks (2005)
By my shell one-liner, it would have been counted as appearing four times (instances 1, 2, 4, and 6 above).I could tweak the script by lowercasing (or title-casing) titles (I've a script that does the latter), and eliminating any instances of "[dupe]". While I'm at it, "[flagged]" and "[dead]" possibly as well, though I think the latter won't appear in the archive. And let's convert all apostrophe variants to a single apostrophe character (') (ASCII hex 0x27).
With those adjustments, I see "Why I Hate Frameworks" appearing six times, as expected, and there are 57 titles appearing 5+ times, rather more than the 39 initially posted above. There are 3,077 repeated front-page titles in total.
The one-liner, FWIW (rearranged to multiple lines):
egrep '^ Title:' parse.log |
sed 's/^ Title: //' |
sed 's/([0-9][0-9][0-9][0-9]) *$//; s/\[dupe\]//; s/\[flagged\]//; s/^ *//; s/ *$//; s/ */ /g; ' |
sed "s/’/'/g" |
titlecase |
sort |
uniq -c |
sort -k1nr |
gawk '$1 > 1' |
cat -n
"titlecase" itself is a sed script that uppercases words, with specific exceptions. I've just augmented it with a few more technology-related terms."parse.log" is the output of my first stage of parsing of the HN front page archive, which lists specific story properties in a tagged format, e.g., "Title:" "Date:" "Site:", etc.
I recently started getting into Javascript 2D game programming.
MDN has a nice simple straightforward tutorial[1] on how to make a Breakout game in pure Javascript. Having read this tutorial, it all fits my brain. It's simple and I understand it.
There are also lots of frameworks you can use, e.g. Excalibur, which also has a breakout game tutorial[2]. This does not fit my brain: there are vast number of classes to learn, and how everything fits together is not obvious at all.
While I was reading the MDN tutorial I was thinking to myself how I could easily build a framework to automate a lot of the stuff. (No doubt many others thought the same!) If I did build such a framework I would understand it well. It would fit my brain. But would anyone else understand it? Possibly not.
I suspect that what makes a framework easy to learn is, above everything else, good documentation.
[1]: https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_...
It seems many developers tire of working for employers who immediately bend to the will of the least competent employee by immediately jumping into unnecessary abstraction stupidity and/or they tire of their least competent peers defining the metrics for success and product quality.
Some people can program. Other people chase trends and call it programming.
It's basically the same idea but coming from a different angle, and it resonated with me enough that I still remember it.
But if you were building spice racks at scale, of course you would build them in a factory! And you'd use machinery made in other factories. And those factories would have tools and machines made in yet other factories.
That's why you can go to Amazon or Wayfair or the Container Store and find 100 different spice racks for less than $30, and why nobody builds a spice rack by hand, except for fun.
You're being called up because the problem is specialized.
Now as a carpenter, you go to the container store and then go back to your shop to dismantle prebuilt products and glue a bunch of different pieces from different containers together and present the Frankenstein cabinet as the product back to the customer. Also, you're on the hook for maintaining it.
Is it faster then just doing it yourself? Higher quality? Cheaper? Maybe...
Competency is the key skill here - someone could claim they're competent in both the NIH and framework way and they choose frameworks because of their vast power of assessments but statistically speaking, they're probably just choosing the frameworks because they lack the competency to DIY and are Dunning Krugering themselves.
A lot of this depends on the types of jobs you decide to take on. The boring ones are pretty easy to do with frameworks but the interesting ones are wildly unclear whether you're saving or wasting time by choosing one path over another especially if you're interested in the product's reliability and longevity.
The amalgamation of frameworks approach makes long term upgrading somewhere between very expensive and impossible. Dependencies, schemas, templating, test syntax can all change in totally incompatible ways as your version gets abandoned and you get locked in to whatever was hot 10 years ago. So much for security patches.
Eventually you'll end up forking the dependencies you once used to save you time and then patch them yourself - code ages way quicker with (most) frameworks.
In fact, if somebody didn’t use a common library or framework and instead “rolled their own” it’s downright irresponsible, obnoxiously egotistical and just creates a huge maintenance burden for whoever has to maintain it when you move on.
Take for example a crud app in ruby. If instead of using rails or another framework you instead “rolled your own” for one it would take you way longer for two it would never be as battle tested as the framework and lastly you are guaranteeing that whoever has to maintain it will need to learn the idiosyncrasies of your amazing implementation with zero outside help. It’s a recipe for disaster.
Use whatever you like on your home projects, but at work you should be using whatever is most efficient.
A framework is great if you don’t know much about the domain and just want to get something together quickly. But if you’re working on anything novel, then eventually you’ll bump against the walls of the framework. Hopefully you designed the project in such a way that you can break out of the framework for these inevitable special cases.
And I like frameworks! I’ve used a few in various languages and think they do a good job organizing the code for the basic cases. But every professional project I’ve worked on has eventually been trapped by piling workarounds on top of the framework to make it work for some unsupported or complex case, or an inevitable architecture fail which the framework has not considered an escape hatch for.
Just like developers and their tools. I have an IDE and nvim at work. The IDE has a lot of power for major refactoring and hinting features, and it’s reasonable enough for an untrained dev.
But it is very slow for the other 99.8% of my job where I’m not doing a big “find and rename all instances”. I am usually wading through a large project and jumping between files to try to understand a complex system. Once I understand it, I’m jumping between those files again to make my changes. All of that is much faster in a lightweight editor than an IDE. But I still open up the IDE every now and then to double-check some change that I made, or do those big fancy refactors.
Plus the comparison doesn't work at all. When you use your home-made framework to solve a common problem, you make it harder to maintain for others. When you use emacs you use emacs.
Emacs and IDEs are tools, but frameworks and libraries (and programming languages) are not merely tools. They're tools AND raw materials.
Where's the incentive to do the latter?
Them fighting words my friend.
That makes building your own framework even less of a good idea than it used to be.
We may in fact see an explosion of new frameworks and libraries that use this strategy.
To be fair this is from 2005 so frameworks were less composition based.
But yeah, HN has been full of noobs for a while. In both a technical and epistemological sense.
Sometimes, that quality/cost tradeoff is desirable, sometimes it's not. The trouble comes if using a factory or framework is the only, or even main, tool in your toolbox, and it ends up getting used for everything.
I you get the work done efficiently this may be a good strategy. It may be a worse strategy, to spend a lot of time to find the "perfect" framework and a lot of time to master it, just because it's a better fit for the problem. "Good enough" very often does the trick.
Absolutely. From an engineering standpoint, "good enough" is often the right thing. An essential thing engineers do, after all, is to select appropriate compromises.
A framework you would use in order to pump out a ton of services quickly, just like a factory in this case. They'd be similar, with similar functionality and such, but you can produce them quickly and upgrade things across all of them fast. They wouldn't by optimal, but time from development to launch would be quicker.
But most startups and companies start with one web service, where at that point you don't really need a framework. What you need instead is careful deliberation and implementation, together with development speed and also enough proper architecture to continue to facilitate development speed in the future, but not too much as to over-engineer things. A balance if you will.
But unless your business/startup is about pumping out 100s of websites, a framework will hardly help you achieve your goal faster.
The same is true for code. Are you writing one application or are you writing the same application for many different customers? In one of those cases you would benefit from some sort of template but in the other case it all the extra stuff to scale just gets in the way.
If you want your one self-serving spice rack to scale then just plan ahead and make it bigger than your current needs so that you can add more spice later. Again, that also applies to code. If you want your one application to scale then just plan ahead. Jumping immediately into a framework only indicates you lack the confidence to make appropriate planning decisions.
The end product here is the food, after all.
When you go to cook a meal you’re oblivious to the framework of abstractions that go to make it possible for you to obtain and store and conveniently dispense your spices - as well you should be.
The pieces are mass produced, the assembly is done by humans. Because unlike software they are not insane.
There is no at scale for 99% of companies.
The break even point for a factory building spice racks buying machines instead of humans is an immense volume of spice racks - like 100+ spice racks an hour type thing. Maybe more.
Just like software, the number of companies that need to produce spice racks at this volume is miniscule. Unlike software, the ones dumb enough to buy machines they don't need go bankrupt very quickly.
Django is a perfect example. If all I am doing is two or four pages that just return static HTML, then why would I pick that at all? A new django project creates a specific file structure: urls.py, models.py, settings.py, views.py, middleware.py, etc. If I get a new Django developer that is not familiar with the project, I can pretty much drop him in and he will not what is going on quickly. I don't need to explain what a viewset is because chances are that the dev has used Djano Rest Framework before. Whatever changes are made, will follow the same patterns, so maintainability overhead is reduced.
When you add a project that is built from scratch without using a framework that has strong stances on how files should be organized, all bets are off. You have to spend a lot of time trying to wrap your head around the custom abstractions that have been built - and it is hard to argue that some of that will translate to a different job.
Yes, of course when you want to do something else that forces the opinionated framework to do things that it was not designed to do, it is a true pain - but you have to ask yourself if for that particular case it makes sense to use that framework at all (most likely not).
Frameworks also evolve. I use to curse constantly when I had to touch a Backbone JS project in the past, but now, I can jump and look at a React project that uses Redux and get to make changes right away without paying high cognitive cost. It may not be perfect, but it gives me structure and pre-defined patterns to worry about solving the actual problem I want to attack - and not waste time trying to create yet another leaky abstraction. My two cents.
I've worked in projects like this. In most cases, they contained what amounted to a part of a framework. The catch in the ones I worked on is that the authors had not realized they were building a framework and so did not think through their division of functionality, cross-cutting concerns like logging, and so on.
Inevitably, each of those had started as simple project. Over time, they had accreted one easy add-on after another. Eventually they're large, complex, and difficult to work on for anyone who didn't create them.
It's been my experience that most projects tend towards complexity over time. A well-chosen framework will require a bit of complexity up front to get going and provide a lot of options you can integrate as your needs grow. Preferably while letting you focus on the specific things you need that are different, rather than having to think about how you want to do logging and so on.
If all you need is HTTP routing, then Flask is great, but every time I tried to use it for the kinds of things Django is great at (databasing, templating, forms), I had to effectively roll my own crappy version of Django. (Something something every sufficiently large C++ program has a poorly implemented version of LISP embedded into it.)
I saw this dramatically demonstrated by an enormous Flask installation that would have greatly benefited from a little imposed structure. I bounced hard from that gig after being shown the code because it was going to be a massive pain to understand the poorly designed abstractions. But it wasn't even the maintainer's fault - it was pretty good code but it had only been designed by one person, both the abstractions and the business logic. And the abstractions were leaky simply because abstractions are difficult to design.
The framework allows you to completely offload the architectural decisions underneath the framework to many person-years worth of design, bug squashing, and security fixes. How do I add headers to a request? Django has one opinionated way. Where do I put my database models? models.py and if you put them there you don't have to do any connection fiddling.
The ideal of a framework is that if you release attachment to how things you don't actually care about anyway are done, you get thousands of free high quality lines of code.
I learned a lot from Sandi Metz about the costs of "The Wrong Abstraction" https://www.youtube.com/watch?v=8bZh5LMaSmE
For instance, you could have an http framework that handles things like compression, buffering, timeouts etc, which are likely to work everywhere. But you could also design it such that each mime type comes with a separate class, like a HTMLTreeBuilder, or something like that, which would be horrible and way too constrained.
Elaborate type systems can, in some cases, seduce this kind of overengineering. If it really looks like something can be modeled as a type, chances are that the author cannot resist it.
The problem with frameworks is instead that they assume that they're in control. They're the program, you're just writing a plugin.
This makes it unnecessarily hard to use them in all but the most straight-forward use cases. And they're usually also trying to do too much; config for starting, special way of testing, incompatible with other frameworks and libs etc.
Contrary to that, a library does one thing and one thing well. Like a Unix tool. Much easier to use, better coverage, and usually easy to combine. And you can plug them in anywhere.
Frameworks are overreaching, but not in the way that the article paints it.
Rather I think it'd be better phrased as "frameworks should use simple abstractions and methods as often as possible", which the language naturally pushes people towards imo. I believe this causes most Go frameworks to be referred to as "microframeworks".
I'm not sure what made you think it's an "appropriate" framework, it's literally antipattern on antipattern and it's not even the worst thing, neither is the fact it's 10x slower than anything else out there - what's worst is the blatant lying, bunch of security issues and using it as an advertising platform to push subpar services onto devs stuck with it.
Or do you prefer to not use any framework and instead write your own one on the fly because you're probably going to do it a lot better with all the best practices and no bugs and great documentation?
To indulge you, about good frameworks: Symfony, Aphiria. Aphiria in particular because it's small, cuts down on repetitive tasks and doesn't reinvent the language with things like "Macros" or abuse of Reflection or mishandled patterns like singletons - all of which Laravel gets wrong.
Symfony because of active development. Every large tool is bound to be bad at something. Symfony is no exception, however it's not an advertising platform - and Laravel is an advertising platform. Sane choice is to use the tool with maximum benefit and least negative impact.
Micro frameworks that don’t do more than routing. I’d love to see those beautiful reinventions of the wheel people do when using “simple” frameworks for email, ORM, validations, authentication, authorization, cli commands, translations, error and performance reporting, etc etc.
I remember somebody commenting here on HN about a developer conference, where the speakers were bragging about their software being complex.
This is an awful trend with software, and is related to John Carmack's "layers of crap", Wirth's Law and developers who want to keep their job by writing code only themselves understand.
The quality of any engineering work is highly correlated to how simple and approachable it is. Unfortunately sofware developers have the unfortunate tendency to have a taste for complexity, because they feel complexity is a form of art since they view computers are complex things.
It doesn't have to be like that.
Oh, you want routing? "Not my business", says React. Go add a routing library. You want a framework for managing global state? Go find one. Want a kitchen sink frontend solution which bundles all of these commonplace features together? Use Create React App, or Next.js, or whatever fits your use case.
That's why I love React. The complexity of the solution matches the complexity of the problem.
Hello world:
const App = () => <div>Hello world!</div>
root.render(<App />);
Basic reactivity (output click event to console): const App = () => <button onClick={console.log}></button>
Composition & enumeration (dynamic bullet list!): const OneTwoThree = () => [1, 2, 3].map(i => <li>{i}</li>)
const App = () => (
<ul>
<OneTwoThree />
</ul>
)
Set UI output data and CSS style based on asynchronous query results: const App = () => {
const [isGoogleUp, setIsGoogleUp] = useState(true);
const checkGoogleStatus = () =>
fetch('http://google.com')
.then((response) => setIsGoogleUp(response.ok))
.catch((err) => setIsgoogleUp(false));
useEffect(() => {
checkGoogleStatus();
}, []);
return isGoogleUp
? (<span style={{ color: 'green' }}>Google is up!</span>)
: (<span style={{ color: 'red' }}>Can't reach Google.</span>);
};
I can't imagine things being much simpler than this. No extra CSS files. No `Controller` classes. No janky, bespoke HTML "attributes" to make array loops or conditionals work. Just pure JavaScript (JSX optional) painting what you declare. That's my jam. I can't endure the agony of learning another damn template language or SomeCompany's (leaky) abstractions.Don't get me wrong, in its purest & simplest form it is great. Unfortunately it's very rare you get to leave it like that because we now make web _applications_ instead of static websites.
Most of the time you're actually better off just using html5 with css3 - it's very rare that you truly need something that is "reactive".
Great, now I have to sort through hundreds of different routing libraries and dozens of different build systems, and then do it all again when I need a state library. This is why people hate React.
Having worked in an Ember shop before, having everything just work and not be constantly updating dependencies and managing around cross dependency hell and endless package underwriting was very nice. Not to mention that to this day, I still haven't found a good React equivalent for Ember data, and I miss not only how productive my org was with Ember and how nicely our codebase scaled over time with sane conventions that we didn't have to invent the hard way by trial and error.
I would say very nearly the same thing about Django in that if it used SQLAlchemy and HTMX/etc for Django Admin, it would be nearly perfect. Even so, Django is a framework that has never let me down in production and it's always irked me when I've had to build something in Flask-land or FastAPI-land that just worked out of the box in Django, or was a well maintained package in the Django ecosystem.
Double edge sword in my opinion.
Every single react Project I jump into is completely different and a pain in the ass half the time to figure out what is where and what is doing what.
On the other hand I can jump into just about any Rails project and hit the ground running.
Vue is similarly unopinionated, but it is more intuitive to my particular brain.
Imagine simplifying the last example without useState and setState, nor useEffet and depList
The counter point to this is that the purpose of frameworks is to turn O(N) problems into O(k) problems by implementing a seam in the code.
The problem a framework ultimately solves is that some teams will choose to use screws, some will use a hammer and nails, some will use a nail gun, some will use glue, some will carve connecting joints, some will use metal and weld, some will take a large piece of material and carve it out, etc. etc. and now you have 50 different ways to perform one task, which is to get the end result of joining two objects.
That means 50 different on-boarding processes, and 50 different design paradigms to manage, 50 different classes of corner cases, 50 different monitoring/operational paradigms, 50 different hiring processes, etc. etc.
Sometime between 50-500 engineers it becomes necessary to properly framework-ize the unit of business logic that product developers work on, like a route, to prevent operational overload.
Simply stated and very insightful.
This is a way better article than the posted one.
Another way of thinking about this is that a framework is a regulating authority on a tragedy of the commons. The commons in the case of software is complexity. Too much complexity becomes impossible to manage and grinds development to a halt.
Some frameworks are "batteries included" while others are a "bag of reusable components".
Now, do we do that well? Clearly not. But that is the right place to collectively focus on improvement. We don't need to argue that frameworks or other solutions either should or should not be used, we need to focus on why they exist, what problems they solve, what problems they cause, and drive understanding of when to use each tool.
[0] I realize this was probably one of the first of such articles and thus has fallen victim to [1], but someone did post it today.
[1] https://tvtropes.org/pmwiki/pmwiki.php/Main/SeinfeldIsUnfunn...
I think the difference isn't between the difficulty/complexity of that individual action but the overall complexity of everything up to that point. Once upon a time the simplest web tutorials might have involved "Open a text editor (already on your PC), write these 10 lines, save it in this directory on your web server or open the file in a browser". Now even the simplest tutorials have way more dependencies/prerequisites and often involve building projects, installing things, framework choices, etc
Once you're already setup and going it may not feel complicated but from the perspective of the dude just trying to buy a hammer it certainly looks complicated.
- completely changes how you write your frontend
- changes the language itself (JS -> JSX with embedded HTML)
- has lots of react-* libs built around it
- comes with a script initializing an app skeleton
I would call that a framework. And it's a very good one.
But defining react as a framework or a library isn't easy, the word "React" isn't just one thing. JSX, initializing script, and the app skeleton are all optional to using React, yet React without JSX doesn't exist, everyone does it, like bundling your web app is a must in production nowadays.
React wasn't so much a framework when it started, you could add pieces of react in different parts of your page, to the point people sometimes argued that it was overkill to have the entire page be a react app. It is slowly walking into the framework direction, and the new react.dev docs violently suggest you use a react with a framework. A developer doesn't just "start" using react in these times, they need to understand a lot to create a full project with react.
You can use it for only a part of your UI, and you can implement any parts of your UI that are embedded within react components without react as well. It doesn't lock you into doing things its way in any manner whatsoever, it is literally just a library with functionality that you can utilize wherever relevant in your app.
> completely changes how you write your frontend
JSX is not an integral part of react. It's quite feasible to use react without using JSX, and I have done so in the past in some of my side projects when I wanted to avoid setting up a build system for a while. JSX just compiles down to plain old function calls, and you can use those directly without JSX without any issues.
> (JS -> JSX with embedded HTML)
JSX doesn't really have embedded HTML, it's just syntactic sugar for plain function calls that only somewhat approximates HTML.
> has lots of react-* libs built around it
Which are usually either libs that implement a react component with react or just wrap some non-react library in a way that's slightly easier to use than using the library directly in an app using react, but it's not like that latter is impossible or even difficult.
> comes with a script initializing an app skeleton
Such scripts exist, but they are not integral parts of react and are by no means required to use react. React is just a library, and if you want to, you can use it without doing anything else except including a single .js file with a <script> in your html file, even if the more usual way of including react in your project is a lot more convoluted.
Most including the standard docs would recommend using create-react-app unless you really know what you are doing
Now days, Framework's mutant offspring ad-order-of-magnitue-larger, Platforms, is what I cope with. Why I Hate Platforms would be the same general rant writ large.
https://stevenheidel.medium.com/a-factoryfactoryfactory-in-p...
Although, frankly speaking, Java libraries are still the most convenient to include/extend than most other compiled languages I've seen so far. Probably because of that culture of over-engineering for abstraction/extensibility.
To be fair: finding the right level of abstraction in a sea of uncertainty can be a tricky problem - but sometimes this also just happens for very different reasons than out of necessity (ivory tower architecture commitees, external companies selling the most expensive solution, ego fueled idiocy or just plain old ignorance).
A: I wanna buy a tree. B: Ok. We have trees. What do you need a tree for? A: i want trees so i can make lumber out of them. So i can cut them in two by eights. So i can build a deck deck for my patio B: Hmm we sell two de eights. You wanna buy that instead? A: Oh yes why! I would like that! I'll buy two by eights instead of trees so i can finish my job faster!
Go ahead and build your apps out of whatever you want, no one is forcing you to build it using frameworks.
But I promise you, if frameworks did not exist half the apps I use today wouldn't either. There's a right tool for every job and the article pretends there isn't.
Edit: I donno why, but the concept of dubious soup has me CRACKING UP right now.
The ever growing field of prompt engineering continues to grow.
Their free plan will let you hammer in 5 nails per month into a single piece of wood, but you can't use a different piece of wood each month. For $30/month you get 50 nails, and up to 5 pieces of wood, or for $60/month you can get 120 nails and unlimited pieces of wood, and two-factor (they'll call you before they hammer in the nails, and ask where you actually want the nails hammered). If you want to have unlimited nails, you have to contact them for enterprise pricing.
They will also sell the measurements of your wood and the nail positions to other carpenters.
If you need to build stuff out of wood, you have three options: buy something pre-made, hire someone to build it for you, or hire a team of carpenters to build it in house. Arguably, the third option should be your last choice.
Stretching the metaphor a bit, sometimes it makes sense to hire a team of carpenters, but contract out or buy pre-built a few particular parts that are particularly difficult or complicated.
That's essentially what these SaaS products are supposed to offer. The problem is not that they exist, the problem is that it can be difficult to know when you need or don't need any particular product.
I concur with this because programming with Clojure feels wonderful. Your code is a straight line from input to solution. With imperative languages, you see yourself applying the duct tape.
This really demands that I link to the "Chef of the Future" Honeymooners episode, which I expect most readers of this site will not be familiar with and that I only know because my dad was a huge Honeymooners fan. It's apt to the blog post, as it turns out:
To provide some context for the scene, Ralph ("chef of the future") is a bus driver and he's always looking for the next get-rich-quick scheme. Ed ("chef of the past") is his neighbor who Ralph thinks he's smarter than and always enlists in his schemes. Ralph's schemes never work out for him. The scheme in this episode is to sell a kitchen multi-tool ("handy housewife helper"). Here the two of them are supposed to be presenting it to a live TV audience. Unfortunately, Ralph's stage freight and the fact that the multi-tool is worthless get the better of him.
Sometimes when I read about a new framework or other software contraption that's supposed to make my life easier, I wonder to myself: "but can it core a apple?"
> Everyone is using a general-purpose tool-building factory factory factory
So that would be like a 3D printer that can print 3D printers?
Personally, I think I own about 4 or 5 different kinds of hammers. And I'm just a homeowner who fixes things on weekends.
When I attempted to point out that we were investing substantial time solving problems that have already been resolved, I was invariably met with references to "frameworks" and "complexity". However, in my perspective, our reluctance to utilize frameworks led to an inflated team size, slower development cycles, and a lengthy onboarding process for new members.
I believe that if we had chosen to use industry-standard tools for our backend & infra (e.g. Kafka, Kubernetes, Apache Beam/Spark streams), we might have had to deal with a higher degree of complexity, but it would have been manageable. I would much prefer to diagnose issues with a Kubernetes deployment than to debug obscure panic-inducing code written by a colleague, which is questionably designed and lacks readily available support.
One of the main advantages of using a framework is standardization: thanks to tools like git, we don't need to familiarize ourselves with every company's unique version control tool. Similarly, if everyone agrees on using Kubernetes and Docker, we can eliminate the need to learn each company's specific deployment process. This would allow us to dedicate more time to providing actual business value, rather than contemplating how our code should be transitioned into production.
As for the department - it just got shutdown due to not making enough money and costing too much.
The thing I've seen the most in this industry is the opposite of that: teams that would mostly use third-party tools and frameworks, but the result was effectively the same, with complexity exploding and becoming so unbearable that the teams inflated to compensate, with productivity grinding to a halt. It happens with third-party tools as often as it does with NIH.
Like you say, Kafka, Kubernetes and Spark would add a higher-degree of complexity. They aren't really that simple to manage in real world production environments. That's the problem here: the complexity. It doesn't matter where it comes from, it will bite you in the ass.
One extreme of that is off-the-shelf enterprise software, that often requires a team of consultants to integrate. I've seen a few disaster, one software specifically started with a 500.000 price, but things became so complex the project ended up costing 4x that. There is no panacea against complexity. It costs money and takes time.
The main problem here seems to be the "questionably designed and lacks readily available support" part, which is something universally bad, even when using third-party software. You can design your infrastructure badly. You can make questionable design using third-party tools just as much as you can with your own code. And support is also very often not readily available.
"Similarly, if everyone agrees on using Kubernetes and Docker"
I'm totally sympathetic to things becoming standards, and I don't have an axe to grind with those two tools, but the reason for the pushback against tools like Kubernetes and Docker is grounded on reality. Not only they introduce complexity by themselves, they are often just band-aids for accidental complexity introduced by teams and by third-party things like programming languages and frameworks.
Before joining the department, I was part of a start-up where, with a considerably smaller team, we were able to process even larger amounts of data. We could introduce a new feature in a single day - a feat unthinkable in the department I just described. This speed was not achieved at the expense of stability but was a direct result of our choice of tools.
Addressing the aspect of "questionable design and lack of readily available support", I believe only a handful of individuals are capable of developing something on the scale of Docker or Kubernetes, let alone doing it effectively. Assuming you're fortunate enough to hire such individuals, would you genuinely want them dedicating their cognitive resources to these types of problems? Even if they are highly skilled, can their solution truly compete with industry-standard frameworks developed by a team of equally competent individuals? And even if such an individual could design a superior solution, they are now responsible for maintaining it and training juniors on a system they likely have little motivation to understand.
Moreover, the 'Not Invented Here' syndrome can lead to a cascade of more of the same. For instance, we needed to orchestrate several processes. Had we adopted Kubernetes, I would have suggested utilizing Airflow, which could have been implemented in just a few days. However, we chose to develop a custom pipeline runner, which took several months to complete.
I understand that the no-frameworks sentiment has its roots – perhaps from Java's insistence on using frameworks. However, it seems that the industry swings from one extreme to the other. Golang emerged as a reaction to a world overrun with frameworks, but it appears to have veered too far in the other direction.
And no, I don't see the point of rebuilding Kubernetes and Docker in-house and most critics also don't. What I'm saying that teams will be better of if they work towards not needing Docker or Kubernetes (or any NIH replacement) at all. But that requires challenging the assumption that software needs "something" like Docker or Kubernetes.
Sure, if there's a tool for X then by all means use it, but my point is more that not doing anything in-house can often lead to the same issues.
In contrast, with a Golang monolith, service integration often involved complex, time-consuming conversations due to rigid NIH abstractions. And given the tendency of senior engineers to resist changes, progressing became challenging. A developer like me would be caught between resistant seniors and a product team demanding immediate feature release. Additionally, data processing often required extensive custom coding, slowing down operations. And if more than one machine was needed, it would mean a total overhaul and a long wait.
In comparison, a lean startup allowed me to use apt tools (like BigQuery), containerize it with Docker, and then let it be - without involving anyone senior. Moreover, in case of a new feature, we could simply replace the entire component instead of struggling with additions.
The agile startup emphasized less on seeking senior developers' approval for every change. In the monolithic Golang environment, senior devs often fixated on code quality without acknowledging that, in a microservices context, it's frequently more effective, faster, and simpler to reboot and rewrite parts instead of altering the existing solution. Hence, the intense focus on solution maintainability becomes less critical.
In my experience, it's always the junior who shouts "This could all be so much simpler!".
Don't have time now to find links of Jonathan Blow, George Hotz, Casey Muratori, and many other decidedly non-junior programmers complaining about the absurd, unnecessary complexity of modern software development.
The people who complain are the people who know how much simpler it can be.
Now, there is a separate phenomenon of green devs who think they can rebuild X only because they can't fathom the bulk beneath the iceberg's tip. That is real too. But it takes nothing away from the very real fact that the vast majority of software written today is much, much more complex than it needs to be.
The path of least resistance at every step is definitely more complexity, so that’s what happens. Fighting complexity has to be actively prioritized.
And it's not only about time: it's a hard skill to learn. Often, the simple solution won't occur to some engineers, no matter the time allotted.
Try to discuss this with people and it’s endless hand waving about resume driven development or not enough time or devs aren’t good enough or nobody really writes good software.
It’s absolutely toxic.
Or the actual senior engineer, as opposed to the mid-level engineer with a senior title. It's the ones in the middle that really love adding in the complexity - you have to relearn how to prune it back out.
> An architect’s first work is apt to be spare and clean. He knows he doesn’t know what he’s doing, so he does it carefully and with great restraint. As he designs the first work, frill after frill and embellishment after embellishment occur to him. These get stored away to be used “next time.”
> Sooner or later the first system is finished, and the architect, with firm confidence and a demonstrated mastery of that class of systems, is ready to build a second system. This second is the most dangerous system a man ever designs. When he does his third and later ones, his prior experiences will confirm each other as to the general characteristics of such systems, and their differences will identify those parts of his experience that are particular and not generalizable. The general tendency is to over-design the second system, using all the ideas and frills that were cautiously sidetracked on the first one. The result, as Ovid says, is a "big pile."
Music was my first career, and there was something that really stuck with me while studying music theory- learn as much as you can, and then don’t think about any of it when you go to compose.
This was my experience as well, for pretty much the same reason. At some point, I gained enough experience that I no longer cared about impressing anyone or showing off, and my code became substantially better.
Vis-a-vis the conversation that has ensued from this statement, I'll offer the suggestion that the real seniors are the ones who don't make blanket statements one way or the other, and appreciate the distinction between incidental complexity and intrinsic complexity. Some times, the problem itself is simply complex and requires a complex solution. One should not rush to eschew complexity in those cases. Other times, the complexity is incidental and is brought in by the choices of the developers. In (many|most|all|??) of those cases, we should try hard to avoid that complexity.
And mids just think that's what the job is and nothing to do about it. It's not 1985 any more and 1985s tools aren't enough to write a cloud db backed ios app.
It's the seniors, and the good ones at all levels even if they aren't good at it yet, who object to complexity on a pure lack of elegance basis. They value elegant solutions and complexity is usually the ugly brute force solution that's merely complex when it's claiming to be sophisticated.
Even if they don't have any idea what to do differently, they just know that something surely can't be sensible just on the face of it. I would hope everyone at least gets the ancient "hello world by different levels of programmer" joke, and can see when it starts happening for real around them.
I actually think the opposite of that. Experienced programmers, from my observations, have learned that complexity is an inevitability that requires management (all nontrivial programming is really an exercise in complexity management, after all). They resist adding complexity unnecessarily, but also recognize where it can't be avoided and opt for managing it instead.
In the real world, "elegance" is an unattainable ideal that is to be admired and desired, but experienced devs recognize that pushing too hard for it will result in the exact opposite of it.
20+ years later and I’m still saying this. Quite possible I’m still the junior in terms of skill though.
This is a very "senior" mindset.
Yeah, this is true. But I often wonder how much of this is because the seniors have given up on simplicity and since they have internalized the complexity it doesn't bother them anymore.
I've seen this first-hand. It makes for a bad experience and a demoralized, ineffective team.
Essential complexity is exactly that. The entire game is to separate it from the accidental complexity. My career/life was revolutionized by a paper that is 100% focused on this very topic:
https://curtclifton.net/papers/MoseleyMarks06a.pdf
The solution to eliminating accidental complexity is ultimately presented as a flavor of relational model, which I simply read as "please just use SQL for most things". This perspective has served me exceptionally well over the last ~4 years now.
A quote I like from Chapter 8:
> The relational model [Cod70] has — despite its origins — nothing intrinsically to do with databases. Rather it is an elegant approach to structuring data, a means for manipulating such data, and a mechanism for maintaining integrity and consistency of state. These features are applicable to state and data in any context.
Chapter 9 offers an actual proposed solution - Functional Relational Programming.
At the end of the day, suffering in a cesspit of complexity is a choice. The relational model is the answer for untangling highly-complex (aka high-dimensional) problem domains, especially ones that require arbitrary downstream views of the data. The central piece of magic with the relational model (as applied to the real world) is the query planner. You should start thinking of this as an actual code-writing super AI that can answer optimization questions 1000x faster than your best developers. All you have to do is give it a tiny pile of hints to work with, and almost any arbitrary request will be satisfied in a nearly-ideal amount of time.
our friend ChatGPT summarizes the paper thus:
"In summary, "Out of the Tar Pit" argues for a shift in software design principles, advocating for the reduction of accidental complexity through functional programming and dataflow concepts, proper state management, and the use of formal methods. By focusing on these principles, the authors believe that software systems can be made simpler, more robust, and easier to understand and maintain."
That was the company where I first heard the term "Train Wreck".
("Documentation? You're lucky it builds!")
We had layers of complexity and frameworks and embedded scripting on literal 8 bit game consoles and it was still fast enough.
I think the problem he's describing comes from the fact that programmers like to build tools to make other tools. Give people a framework and they'll say "I can totally use this to make something someone else might do something cool with".
Perhaps it's some kind of desire to leave a legacy or make your mark it have something awesome on your resume, or just because nobody has any ideas for apps anymore that actually seem worth it to build.
The same also applies to external libraries and the architecture of your library/application.
Factories in Java, like the URL hints at, are just bad. Maybe they made sense in older versions for reasons that I forget. Haven't felt the need to make factories in modern Java or in any other language.
p.s. The hype predates even HN. I remember reading these stuffs on magazines. Holy crap, I'm old.
But I was actually hoping for a factory automation online game because I feel like I need to sink the next 2 - 14 days of my life into a shapez.io or mindustry or something like that...
- Everything's an object -> Let's define lots of nouns!
- Classes cannot be declared to implement interfaces after the fact -> Let's write some adapter classes!
- People get tired of writing adapter classes and notice that JVM has reflection capabilities -> Let's make a framework that generates adapter classes as needed!
- Everything's heap-allocated -> Let's avoid excess allocations by re-using objects! Which means you've got a big web of interlinked mutable thingamabobs floating around, made possible by Java's pretty-good GC.
- 'const'ness ('final'ness in Java-ese) is defined on the type, not on where it's used -> Most classes are written assuming mutability, and if you want immutability, you need to create an entirely separate type hierarchy.
I could go on.
When I want to write a Java program but keep it simple, I usually end up writing something that looks more like a C++ program. Minimal, domain-specific classes with as much setup in the constructor and as much `final` as I can get away with. But it's not as ergonomic a language for writing programs in that style as C++ is. And once a coworker brings in some library written in the conventional combinatoric-explosion-of-classes-and-pointers-to-mutable-objects-everywhere style, you're pretty much stuck with it.
It was a joke. Jokes don’t have to make sense. They just have to be funny. I understand that you did not find it funny, and that’s ok. It certainly wasn’t even all that funny. There are wide variances in what people find funny. Even the most uproarious joke a comedian tells will have those who genuinely didn’t enjoy it.
But at the same time it is generally considered dickish to try to convince the people who did enjoy the joke that they shouldn’t. People tend to enjoy laughing and smiling. Having some buzzkill come in and vomit “well akshually” all over the place is a sure fire recipe for annoyance.
As an example, the movie “Monty Python and the Holy Grail” opens with King Arthur being trailed by a servant banging two halves of an empty coconut together. King Arthur’s time is estimated to have been around the late 5th century. Coconuts were not introduced to Europe until centuries later. If someone were to object to the scene with these bits of history they likely will be viewed unfavorably. The reason for this is because most people do not expect satire to be historically accurate.
Personally, if I see the words “frameworks” and “hate” in a sentence then immediately my brain goes “REACT!” The joke, such as it was, was an expression of that.
Should you require further elaboration on the subject of humor please do go jump off the nearest bridge.
I don't like React.
In reality there are abstraction that work very well. You don't need to understand the internals of python to use it for example, though you may be able to use it better if you do. C however I would argue that you do need to have a mental image of what is happening to use it.
Also the operating system. People use that all the time without knowing how it works.
Maybe we are just at that early in web dev and we are waiting for the Unix of web frameworks to arise. Or perhaps there is an inherent tension between the developer needing to fiddle with the details while the framework tries to abstract those details away.
Or for that matter, an os and POSIX?
A language is just a standardized framework, and languages are created to solve general cases of specialized problems.
Sure, I don't need the python framework to do something, but if I don't care overly much about performance, why would I want to deal with manual memory management of c.
And just because c exists means we should not use c++ or rust?
Choose the right tool for the job, but starting at a high level of abstraction and working down as needed often makes a lot more sense than starting low and working up.
Maybe don't use unproven frameworks and all frameworks has a different level of provenness. yes there are some people out there that don't need anything, and can program a http server and website in assembly. But it's either a toy or fun side project if they do.
A "hammer" is useable on its own, it's a self-sufficient object of value. The "libraries over frameworks" mindset as practiced leads to splitting libraries by underlying technical concerns, not practical utility. There is no practical utility in a "routing library" or an "ORM library"; there is a lot of utility in a "login system", but realistically a login system has a lot of cross-cutting concerns, from database access to sessions to forms to templating.
Instead what we get is a wide selection of hammer heads and handles, all requiring assembly and not quite fitting to each other.
https://dl.acm.org/doi/10.1145/362575.362577 (HTML, links to PDF)
A good framework would be one in which you start your solution and find that at many locations, your pseudocode gets replaced by an equivalent call into the framework. There are, however, some other requirements that are not obvious from this specification of good framework that make it a great framework. Discoverability, testability, debuggability, deployability, documentation, readability and, of course, performance.
But, yeah, you start out with one and you lose interest in the project because of the difficulty of getting started.
In practice, what I have seen is there are people who endlessly talk about the right and wrong ways of working and others who realize that tools are secondary to actually getting your work out there in the world.
A framework forces you to commit to it fully when you use it for a project. This is unlike a library, which is optional and can be locally replaced with ordinary code if something doesn't work as expected.
A framework is like magic when everything works, but when you see some undecipherable framework error message you have to look behind the curtains and try to understand the code of the framework. Which can be very difficult depending on your skill.
In the past I have spent hours or days debugging problems with the framework with features which would have taken ten minutes to solve in non-framework code.
That said, author is not wrong. Reminds me of talks from Bob Martin about frameworks and software architecture. Summarised and linked (shameless self-plug) here: https://www.compilatrix.com/docs/framework-there-to-screw-yo...
However, I want to comment on a bit of the discussion about hammers and carpenters in the comments on HN.
Let me put this briefly - carpenters learn about wood way more than they learn about tools. Knowing how to cut wood, bend wood, fasten wood, use wood to hold things up, make wood look nice, etc. Those are things carpenters do and learn about. The tools are secondary.
Also, one final note - carpenters don’t really use ball peen hammers - those are for metalworking. Carpenters use claw hammers because the claw removes nails.
1. Start out loving frameworks for how easy it is
2. Convince yourself frameworks are the devil and you can do without, spend a lot of time rolling your own and learning a shit ton about the nitty gritty.
3. Eventually realize it's a fruitless waste and you'd rather spend your time working on more important things.
4. Either you go on to create the next big thing or you go back to using frameworks but smarter this time around (in my experience piecemeal or better able to extend).
Looks like someone's been doing too much enterprise Java progamming!
I would absolutely buy a tool factory factory. Tempering the steel alone would be worth it.
I’d even be interested in one more layer up, for access to car, rocket and chip factories.
Some time ago, I wrote a small article, what you could learn instead of frameworks. Pretty rough, but still worth a read I think.
https://pilabor.com/blog/2021/05/learn-concepts-not-framewor...
1. My problem fits the way a framework is shaped perfectly and the things it does for me are done in the way I want them done
2. My problem doesn't fit any framework and I rather take a micro-framwwork and build the rest myself
The latter is more common
All web frameworks are the same to me, doesn't really matter if they're python, javascript, php, or whatever tbh.
req/res body cookies that's it
What happens when you need to disable nagles, avoid copies of the request body, use websockets, gRPC, etc? You’d need to pray that the framework gives you an escape hatch.
Why would you choose a framework that didn't provide a escape hatch for your use case is the real question tho.
TIL: Nagles/TCP
Not sure this post actually has anything to do with frameworks at all.