The worst part of this kind of thing is that young carpenters honestly, really, truly, just need to learn to use a hammer. They can't even conceive of the problems that are being solved by the hammer factory, let alone the factory factory. But in the world of the factory factory factory, the apprentice carpenter (who really just wanted to drive a few nails) is now faced with trying to understand the gargantuan complexity of the factory factory factory.
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.
> But in the world of the factory factory factory, the apprentice carpenter (who really just wanted to drive a few nails) is now faced with trying to understand the gargantuan complexity of the factory factory factory.
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...
Senior here. I think this is an overly cynical take.
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.
You're absolutely right, there is definitely an optimal level of framework usage, for the reasons you state.
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.
Sounds like you haven't really understood the benefits of polymorphism, encapsulation etc.
The general idea is to compartmentalize your logic and only expose the important parts like if you need to generate pdfs from html you may need to use a lot of moving parts to make that happen but you hide all of it and only expose an interface with a single action that takes html and returns a pdf. If you later need to change how you do the pdf generation you can freely mess with the internals of the system any way you want because consumers have no dependencies on any of it. If you need to rewrite it from scratch you can implement the same interface and none of the code using it needs to change at all.
I disagree with the suggestion that parent poster doesn't understand the benefits of polymorphism and encapsulation.
Polymorphism and encapsulation are perfectly achievable without the programming practices being criticized by them.
I don't think any sane developer would complain about having exchangeable/reusable HTML/PDF/??? generators. Funny enough, "PDF Generator" is also a very popular example of a "sane" micro-service.
The real problem starts when every single class in the application is given this treatment, even in the cases it doesn't make sense to make it replaceable. This problem is compounded by having very small classes that don't do much by themselves and have (hidden) dependencies with too many other classes. That's how you get the FactoryFactoryFactory problem.
Not everything needs a hyper-abstracted solution. Most people suck at writing neat abstractions, so they spend an excessive amount of time writing shoddy solutions which no one really wants to deal with but there's a soft, begrudging agreement to use them anyway while the business sees no value in having their devs rewrite it. This goes double when you step into the world of microservices, where you now have another layer where you can easily swap the implementation behind the interface.
Surely years of old Java shops with absolutely dreadful software architecture, sloppily copied from literature, showcase the path to hell being paved by good intentions.
But factory is not "hyper-abstracted". For that matter, factory factory can be annoying, but still does not require all that much abstract thinking to understand.
It would be different if people complained about actually complicated stuff ... but, you know, factories are not difficult to understand. Even when I disagree with design decision to create a factory, it is clear what factories do.
Sure, you can write bad code using abstractions. Doesn't mean abstractions are bad or useless. There's just a lot of devs out there who don't write very good code.
There are also devs writing decent code but too tightly coupled, making it much more difficult to develop the code further without first refactoring the existing solution. It is also often very difficult to refactor the solution because its parts are also very tightly coupled so you end up with a whole tree of changes you have to make before you can do the actual refactor you want in order to make the actual change you wanted to do in the first place.
Eh. It’s usually not that hard to take two tightly coupled components and insert an abstraction layer in between. Usually tightly coupled code is small, and you can almost always use the compiler to find all the places you need to modify things.
Practically speaking I’d much rather that problem than it’s inverse. It’s exhausting dealing with code that’s too abstract. Especially if the abstractions don’t do anything anyway. Eg - Java interfaces with exactly one implementation. Removing useless abstractions never feels pressing enough to do, but you pay a tax for those abstractions constantly. And it doesn’t take many abstractions before your productivity plummets. No thanks.
The best code is like the best writing. Say what you mean. Be direct. And be humble enough to redo it all when you figure out a better way to proceed.
Two? Sure. How about when the whole application is tightly coupled so a change in one class necessitates changes in 4 others? And sure if the logic is straight forward and simple that's fine, but add in that the code is a complete mess with a bunch of weird convoluted solutions to things and whoever wrote it is long gone so nobody knows what it's supposed to do beyond "exactly what it currently does".
I think I'm pretty good at programming but that's generally what I've been doing in my career and to me it's incredibly difficult. Not that much new code, just a lot of wrangling shitty old code and in retrospect regretting that I didn't just delete it and write everything from scratch.
Bad code is still bad code. And correctly abstracting everything is still the ideal. Abstractions are like hinges. Too few and everything is a big fused mess. Too many and your system is a wobbly mess you can get lost in. You need the right abstractions in the right places.
For my money the way to do that is to start with as few abstractions as possible and only add them in the places you need them, when you need them. Start simple and refactor as you go. If you try to predict where the abstractions go before you’ve designed your system, you’ll get it wrong and then you’ll either leave your code with bad abstractions or spend far longer than you had to refactoring. (Since refactoring is harder the more code you have).
I’ve mostly worked in Microsoft shops. And I used to not like that. A lot of the guys around me adopted the attitude of, “what does Microsoft have that does that? “. As I’ve gotten older, I think that Microsoft has enough churn of their own. But it’s far less than opening up to the wild west that is GitHub entirely.
I’m pretty grateful. Everything I work on is either C# or JavaScript. And I do like the abstractions and architecture that comes out of that space. It’s probably similar to a Java shop that way.
A lot of the comments here sound like people are really hacking away with some short-lived library, not framework, off of GitHub in some random language that no one else on the team knows, and now the company will have to hire for forever. Or rewrite. That doesn’t sound like fun to me at all. I definitely wouldn’t build my own business on it.
I work the same way now and I completely agree with you. MS stuff isn't perfect and if they don't provide what I need I generally find the most popular thing on Nuget or roll my own.
Meanwhile in JS land things are all over the place. My last team had multiple apps using all of the following and more: JQuery, Vue, AngularJS, React and Svelte. Design was done in Patternlab but had to be manually copied over and translated to cshtml and some parts were done in one of the aforementioned Js frameworks.
To me that was a nightmare. I think most stuff didn't need any JS frameworks at all, and trying to understand pages rendered partly in cshtml and partly in a Js framework is terrible, especially when they're all different.
I think the simpler solution is to design the code around some kind of pdf generation library that is linked to, instead of making a heavily abstracted mini-framework to squat on the application.
Yeah that's one of those aforementioned "moving parts". You design the interface with a single action taking html and returning pdf. That way it doesn't matter how you change these moving parts, you can replace this pdf library easily and as long as you find another way to make this thing take html and return pdf you're golden, none of the code using your pdf generator ever needs to change no matter how much you need to change this service. Unless you change its entire purpose - converting html (and maybe other stuff) to pdf - none of its consumers need to change.
That's the idea. You define a clean and well-defined interface beyond which everything is hidden. This keeps the code simpler because you can focus on one little part and know nothing you do will change anything anywhere else. Its purpose is well defined.
As an example of a less well defined service I'm currently working on a class DiffService which has a method which gets data from a DB, then it gets data from another DB, then it gets data from an API and then it checks for differences between the two db datasets and uses the api data in the process somehow, I can't remember atm. In my opinion there should be one class where all the data is put together, then it should send the data into a different method in a different class where the only concern is taking the data and combining it in the required way.
This way the actual logic is separate from the data collection. It sucks trying to test this logic because I have to mock a bunch of different services and then test the logic. If the concerns were separated I wouldn't even have to unit test the data collection service - it's just calling some data collection methods and sending the data on to this new service which I could then easily test without mocking anything. I might also separate the part with that api call to yet another place if I can. That way I can have a completely dedicated DiffChecker with super simple and understandable logic, a SomethingDoer which takes that api data and does whatever it needs to with that, and a more general service class tying all these parts together. I can also use these parts in a different part of the code that does almost the same thing instead of having the logic duplicated.
I don't really need any new interfaces for this refactor - abstraction isn't exclusive to interfaces. The code will be more spread out so that does take a toll in terms of mental load but I think that is alleviated entirely by the simplicity of the new components - DiffChecker checks for diffs in provided data, it doesn't do anything else. SomethingDoer does some specific little thing I can't remember at the moment but it'll be equally simple in principle. DiffService ties the whole system together and provides an easy way to get the difference - just like it used to before. It'll just be easier to test, the new tests will be clearer which allows them to more clearly convey the purpose of the code they're testing, the new code will be reusable and allow me to easily perform a similar refactor of a similar system and reduce the total amount of code.
Some people will probably say I'm overdoing it, I think they're wrong. I think a class with one method that does one simple thing is extremely easy to conceptualize, allowing you to stop worrying about what's inside it. Meanwhile the existing solution is extremely difficult to completely wrap your head around. It gets all this complicated data, then it does multiple different operations on it before it returns a result. I have worked with this code for a bit, I've read this method at least 20 times trying to fit everything in my head and it's a struggle. It may sound simple but every part has complexity and nuance in the way they're put together and it adds up. To me it becomes much easier to fit everything in my head when I compartmentalize it into small simple parts that are easy to understand and are put together in a clear and cohesive way.
var dataA = db.GetDataA();
var dataB = db.GetDataB();
var diff = diffFinder.Diff(dataA, dataB);
var apiData = apiClient.GetData();
var enrichedDiff = diffEnricher.EnrichSomehow(diff, apiData); // This would have a more descriptive name
return enrichedDiff;
This is what I want my code to look like. This is already plenty busy, there's a lot of stuff happening here. It'll also have logging. Imagine trying to read it if it was 100+ lines because everything was written directly in this one method.
Github Issues is full of confounding factors though. Lots of Issues mean that there are bugs but all software has bugs. It also means that there lots of users and that users feel that raising an issue is a good way to get something fixed, which is good!
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.
And people can do lots of weird PRs that do not get accepted as well. Code quality, obscure features implemented, etc. but it can be hard to figure out what is what, so they might just sit there open for some time, that is not ideal, but can still mean the code base is solid. For me this is easier to figure out in the issues/discussion page. (And reading the actual source and documentation)
True, though figuring out community sentiment from GitHub issues is a bit tricky. The numbers alone certainly aren’t a good indication because projects attract a lot more issues when they’re popular.
Senior here. Where I work, everyone has the authority of the position below them. The middle management above my team decides language, framework, and architecture. They were hired from much larger companies, so naturally they just know more. I think our 10mil/yr company doesn't need the complexity of a 100mil/yr solution because we're not Amazon and we're never going to be Amazon. But, we now we have dozens of lambda functions in multiple languages with multiple configs designed in different ways deploying from multiple processes from multiple repositories. Our team is having a hard time changing and fixing anything because the cognitive overhead nears the limit of human capability. I was told "off the record" its because we didn't execute their vision the right way.
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.
Of course that’s off the record. Because the questions arise from that would place blame where it belongs, on whoever told you that.
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.
Yeah that's quite toxic. If the project is successful, the top level gets the praise for the vision. If it doesn't, the team gets the blame for lousy execution.
The responsible for executing should have a day in a lot more things, else it's gonna be a blame game.
You had it right with your first statement. Blame always goes to the top. They don’t do anything, making decisions is easy, compared to actually getting it done on a deadline.
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.
What you wrote matches my experience. Not that I approve of it, of course, but it is often like that.
"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.
That's a really common trend today even outside of frameworks and software development. It's super common for people to make a worse choice when they know a better one is right in front of them, because blame if the worse choice fails will be diffused, but blame if the better choice fails will be placed entirely on them.
Not only that, but let’s face it, a popular Java framework is going to be far more stable and long lived for years to come compared to what someone grabs off GitHub. A business sticks around for a long time. Some guy building with the flavor of the month is a big problem.
Thing is, I've had non-Seniors-Developers asking for more complex stuff as often as I had seniors doing it.
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.
> Complexity is often part of developer culture, period.
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.
No, I choose the technology and/or fundamentals that the juniors will have to learn if they want to level up as a developer.
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.
Are you sure it isn't their employer's interest? What if the company sells training or licenses for the framework? Then it definitely is in their interest. There are obvious examples out there.
Everyone needs to learn to do calculus by hand before advancing to the calculator. People picking up frameworks without fundamental understanding is a shockingly common fallacy.
That's the reason why CS classes and degrees exist. Or at least it should be.
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.
The carpenter doesn't need a degree. The architect and structural engineer do.
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.
The way I like to explain the difference between the two approaches — and therefore the two educational requirements — you are outlining here is the difference between being a software developer and a software architect. A software developer is focused on developing a certain feature or fixing a certain bug within the context of an architecture that's already determined, rarely making decisions about how to structure the overall data or control flow of a system or what abstractions the system uses, but accepting what's already there; meanwhile, a software architect is going to be making those more broad abstract philosophical decisions that form the framework of how further features are implemented.
This is not to suggest that there is a rigid distinction between the two — all software architects are going to also be software developers in the process of building an architecture, or when new architecture is not needed, and many software developers will occasionally act as software architects. Nor is this intended to suggest that the architecture of a software project must be planned out in advance with all of the concepts and data and control flow either — just that there are points in the process of developing software where these large-scale architectural decisions about what abstractions to use and the flow between them must be made. But there do seem to be two somewhat distinct "hats" people who program wear.
does what you’re making matter to people or not? It’s like that no matter what you’re doing. Y’all can sit around here and discuss, “what is a software architect” all you want.
By the time he was done formalizing what needs to be done and philosophizing about the best approach (while actively trying to prevent the engineers from hacking away), the programmers and hardware engineers delivered a production prototype that works just fine and that people want to buy.
I wouldn't say that the outcome is necessarily the same all the time, but the getting-nothing-of-any-value-done architect seems to be a common occurrence. We had one that by proxy stopped development on at least 3 projects I was supposed to be involved in because people wanted to make him part of the process, despite me having 10 or so years more experience and an evident track record of successfully greenfielding projects versus his 0. He ended up being literally the only person ever at our company to effectively get demoted.
Previously the same company had hired one of my previous coworkers as a "software/solutions architect" and he had basically the same trajectory but with him at least I suspect he was just burned out. With that said, seeing someone has the title "Software Architect" is definitely a signal to pay attention to whether this person is even remotely competent and/or produces anything of value. If they give off the impression that they are just supposed to hand off designs to someone else to implement you know you have a complete dud and a moron on your hands.
I think its good to separate function from title here. There are indeed good architects and bad architects - may you get the opportunity to work with the good ones.
Personally I find that those who ultimately build the thing they architect are the best to work with. As the build they gain experience, they bridge the gap between theory and practice, and the feedback loop leads to better architecture and better code.
You're true, my best co-workers have been architects who also where tech-leads and great ICs
Your comment made me think how any full-time uni professor is -suspicious- of not interacting with the real world. Any -good- professor should be doing research or on the private sector half of his time to not be just a bookworm
> Y’all can sit around here and discuss, “what is a software architect” all you want.
I think you're on to something. We ought to hire an architect architect to architect the role of the architect. Maybe we can build an architect factory to abstract that away and have architects set up on demand...
I don't think it's feasible to have 1 decent developer micromanage a team down to the function and data structure definition. At that point it's faster to fire the lot and just let the one developer you have do the job alone.
You have such an idyllic view of the college environment. My experience was struggling to motivate my teammates to do anything beyond the minimum, and an endless barrage of "will this be on the exam?" questions during class.
Looking back it's no wonder I am a self-learner now.
Not all colleges are the same. I had a fantastic time at my college.
For example, in our algorithms course, we needed to implement a lot of small algorithms for various things in Java. (Eg A-star, quicksort, etc). For each algorithm, we were provided a standard API to implement against so they could use automated marking. Well, me and some friends made our own benchmarking harness and web frontend around that api. Before the assignment was due, we would all upload our .class files (and upload test cases), and compete to see who wrote the fastest code.
I think I learned at least as much from doing that as I did from the algorithms course itself.
We didn’t have that much fun in all of our classes. But I cherish a lot of memories from that time in my life. I’m really glad I went to college and wouldn’t trade it for anything.
I guess less idyllic view, and more idyllic experience. I was fortunate to find like-minded folk in my class, and fortunate enough to have faculty that allowed us mere undergrads access to equipment "beyond our pay grade".
Obviously the bulk of the class was there to pass, maybe 10% of us pushed the limits, learning the craft beyond the carricilum. We were probably 10 folk or so from a class of over 100.
It was perhaps easier in my day - we had labs with machines no person owned. So you could spend time in the lab beyond the necessary, and the others would be there too.
I imagine today there's less shared working space like that, but hopefully there are still ways to find like-minded souls.
Self learning is great, and we all do that a lot now, but I've been fortunate to find others in my work community who still enjoy sharing, learning, and teaching. Its a bit less lonely that way, and none of us have all the answers.
In my BS I had just 1 team project, so it wasn't a big deal.
In my master I had more… and yes there were people who didn't do anything, people who did much more than me, people who were good at writing reports but needed intervention because ultimately they didn't even understand what our project was about.
I asked the professor once to dump a guy, because he said we should meet on a sunday morning to do our assignment, then he showed up 2 hours late, I was almost done with it, and he started by reading the 1st slide of the 1st lecture (with the name of the course, the email of the professor and so on).
The best college course coding projects are the solo ones. I consider myself fortunate to have gone to a school where 95% of the code projects were solo (and about half of them were in C, too!).
True, but seeing others exercise it can release it in you as well.
College does not "give" you anything. It never has. All it has to offer is opportunities for you to "take". You get out of college what you explicitly "take" from it. You can class through taking and passing classes, or you can actively search out every possible opportunity, stretch every boundary, suck every bit of marrow from the bone.
Ultimately college can be a time-passing exercise in fruitless make-work. Or it can be the foundation to an amazing career. Only you can determine which it is though, not yhe College itself.
Churning out scripters and giving them script frameworks and building whole products and businesses on top of those products has got to be the worst approach to labor shortages ever in the history of work. Oh the single process isn't a good load bearing structure to rest your entire network workload on? Let's create asynchronous abstractions and pack everything in portable process isolation environments and oh now we need a whole distributed OS to orcherstrate these processes etc...
I've done both, degree first, then years later bootcamp, when I needed to update my skills. I liked both. IMO, people should choose what suits their needs best.
"No company will pay you for several years just to learn"
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.
>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.
> But with high mobility nowdays, they seldom think it is worth it anymore. You teach and then they thank you and move on.
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?
On the other hand young workers usualy greatly overestimate their impact on getting things done and the work required to check their work. (I know I was like that)
On the other hand, those kind of "fake" internships are rampant here in France, specially with smaller companies or startups. From personal experience they don't bother checking their work. And how could they, the other employees are interns too.
I used to work in France, I was employed by a French company. I do remember the contractors that were French were pretty disgruntled. But I certainly miss being over there. The work culture is so much better than in the US. The pay may be suppressed, but at least everyone gets to enjoy life. Although, at the company I worked at, the pay was not as far off from the US side as the French folks thought it was. Definitely not when you consider how much better they were treated.
Cynically it feels to me like it's just a nice way for the companies nearby to get free labor.
My assumption for that is just that it's just supposed to be an internship somewhere where our focus would be to study and thus we shouldn't get any benefits from it, but I've never heard of it working that way. It was always in IT here just being an unpaid junior.
A lot of people think CS is "learning how to program in xyz."
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.
I'd wager that I'm interested in a niche of CS, mostly the internet, and websites, and apps and what not. So when I tried to learn C and code unix tools I just felt miserable tbh.
Science !== building
I agree langauge and syntax are just distractions from the -building- part.
In software engineering there's infinte hammers and you can build new hammers out of old hammers btw
During my PhD (not in CS) I met a CS PhD who was working on parallel algorithms. At the time I was struggling with large-scale simulations and HPC stuff so I got very interested. I asked him what programming languages he used.
"Oh I don't know how to code. We don't write programs in CS Theory."
This is honestly part of the reason I abhor statements around "AI/ML will make software developers irrelevant in [insert catchy timeframe]"; the complexity in many (if not most) systems is not the coding. The interaction, the boundaries between systems, the agreements between them, and the subtle nuances among; this is where Things Get Hard.
Then there are the requirements gathering that lead us down this road. And the stakeholders that forgot important details. And that one team that has a hard production dependendency on an obscure DB table you only keep around because it simplifies a join somewhere.
Teach students of CS the latter, and they have a much greater opportunity to be successful.
If LLMs keep improving at the current rate and get to the point where they can reduce hallucinating to a reasonable level, I don't see why they couldn't take on the challenge of abstract system architecture. It's still a problem that can be stated in natural language, which they keep getting better at 'understanding' (at least in the sense of giving more coherent answers).
> CS classes and degrees are akin to reading books about swinging hammers rather than just swinging 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.
I think the "hammer" metaphor is insufficient to cover why one would get a degree or not. I learned a number of fascinating things about computers in University that I would have never gotten on the job.
This sort of fits with your analogy. When I did my Manufacturing Engineering degree all I was interested in was CNC, CAD/CAM and rapid prototyping tools that existed before modern 3D printing.
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.
Depends on the university. My experience was that you spent more time then not having to swing, often in ways that would be applicable to actual carpeting rather than building wooden Monads nobody wants to use.
In germany you are expected to go on a three year apprenticeship when you want to do a job which needs practical skills.
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.
I agree but it's not that you won't need these things but that you don't know when or if you'll need them.
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.
Things like Javascriptin30.com (no affiliation) are plenty to learn how to code vanilla before learning why (or when) things like libraries and then frameworks may have value.
I mean, you certainly should learn arithmetic before using a calculator, right? But a calculator is more of a library than a framework, anyway, so your attempt at proof-by-analogy isn't at all resonating with me.
(edit: I think I misread the comment I replied to and am now in the process of maybe figuring that out downthread.)
Calculators do a lot more than arithmetic these days. Without knowledge of calculus, most people think of a calculator as a magic “black box” that outputs square roots and cosines.
FWIW, I am willing to believe that I have misunderstood the comment I responded to, and that they are not making a sarcastic proof that people should not have to learn calculus to merely use a tool like a calculator, but that they in fact should do so, and I'd actually be willing to get on board with that? (But, as anti-framework as I am, I think that might be going a bit far.)
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.
Roots were calculated at least as far back as 1800BC thousands of years before calculus existed. Trig functions were indirectly messed with since around at least 300BC and was definitely discovered by Indians around 600AD. Meanwhile Calculus wasn't published until the 1700s.
Those techniques were precursors of calculus. They're often taught in introductory calculus courses (at the university level). I consider them part of the field of mathematics we now call calculus. Indeed, if you study the history of mathematics you'll find that calculus isn't just something Newton invented out of whole cloth, as he himself was well aware:
"If I have seen further, it is by standing on the shoulders of giants."
You could argue that algebra was a precursor of calculus and that basic operations were precursors of algebra. This is a rather reductionist argument. They hadn't even invented zero or algebra when they found ways to produce square roots or that you could make interesting ratios from the sides of a triangle (yes, I know about the history of zero and that is a slight exaggeration, but no symbol for zero existed in Mesopotamia when they were calculating inverse proportion roots).
My real point is that these thing don't require calculus (though calculus does require them). Most people who take trigonometry (or "precalculus" as they usually call it today) couldn't tell you anything about limits let alone derivatives, integrals, and the fundamental theorem of calculus.
As to Newton inventing calculus, he was a vehement antagonist to Leibniz claiming that his work on calculus had been stolen. That's no the attitude of a man who believed calculus was obvious from looking at previous works.
Most people who take trigonometry (or "precalculus" as they usually call it today) couldn't tell you anything about limits let alone derivatives, integrals, and the fundamental theorem of calculus.
And to those people, the calculator is a magic “black box” that spits out cosines. My original point stands: if you are using a tool professionally you should understand how it works, at least on a basic level. For a calculator, that means calculus, Taylor series, Newton’s method, etc.
Did you know that lots of calculators (including the famous TI-83) actually use CORDIC and that the basics of that method predate calculus by a hundred years? Did you fully understand your tool? Did that keep you from using it?
If you know the purpose of a trig function, it doesn't matter HOW the answer is calculated so much as that you know the answer is accurate. This doesn't require calculus.
I took calculus. As an engineering major, I actually had real-world applications of calculus across my coursework. How many times have I found calculus essential outside of college? Surprisingly few. Meanwhile, I've found a LOT of use for trig or linear algebra. There are things where the underlying theory is very important, but in my experience, this is not one of them.
My original point used calculus as an example. You turned this whole discussion into a referendum on calculus which I have no interest in continuing. Substitute linear algebra or even the basic theory of electronics and my point still stands, which you agree with. Furthermore, you studied calculus so you understand the principles behind the tools you are using, even if you aren’t using those principles directly, and that is valuable. People who don’t understand their tools risk being owned by them.
And sine, cosibe, and tangent are just ratios between different parts of a triangle and can be derived relatively easily (just like how you can derive pi if you know the diameter and circumference of a circle).
I’m not sure what you mean by relatively easily. Do you mean by using a protractor and straightedge? How would you calculate sine of 0.1 degrees that way?
This is a good example. You dont need to learn number theory and operations in n dimensions to be able to effectively use arithmetics in your daily life. A lot of CS courses feel like stuff thats purely theoric for that purpose only.
Extremely common, and was one I fell into as a junior dev myself (early 2010's).
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.
I would add that intuition and knowing how to question it is also vastly important.
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 would add that intuition and knowing how to question it is also vastly important.
I agree. Especially knowing how to question and how to break problems down. I'm not sure intuition is a thing that can be taught, but it's a thing that emerges as a consequence of being curious and learning how to question and find answers to those questions.
That aspect is also why I think that being generally curious and having a broad base of knowledge makes you a better engineer. It's amazing how often apparently unrelated knowledge can give you an insight into solving programming problems. People who are laser-focused on "computer stuff" specifically often miss important insights.
And the concept of intuition is discussed in ch22 of thinking fast and slow (can’t find my copy atm) with regards to how firefighters are able to make those split second decisions.
Definitely. And at a slightly higher level, open mindedness is paramount to this. Engaging with other perspectives in good faith not only expands ur worldview but also pushes you to reconsider why you believe/do a thing a certain way.
And like you mention, when a problem arises and you query ur mental rolodex, there’s many more solutions/ideas to iterate over and consider
I agree with you that this perhaps the most useful engineering skill. I think schools try to teach this fairly young with supplemental book reading on top of lectures. That’s the teacher telling you where to find the information, but forcing you to process it yourself. The next level after that is finding the information you need on Wikipedia and beyond.
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.
The TI-Nspire CAS (computer algebra system) can do very complicated symbolic antidifferentiation, like ones that you'd do by hand with repeated integration-by-parts. It can even solve many kinds of simple ODEs!
Iirc they had to lobby college board to change the rules to allow colored screens on exams since the black and white screen was more expensive than the colored ones since no one made the black and white ones anymore
I'd be open to allowing smartphones/tablets on all tests so long as there's no internet. Note taking is more important then ever imo, and knowing how to apply things rather than doing he computational machinery in your head is the more valuable skill to spend time developing (not that we shouldn't teach mental computation at all, just de focus it)
> Iirc they had to lobby college board to change the rules to allow colored screens on exams since the black and white screen was more expensive than the colored ones since no one made the black and white ones anymore
Shouldn't hike the prices on the super old TI-89 Titanium unless the screen (and the CPU, and etc.) is really that much more expensive now.
That’s how I got through calculus. I learned how to integrate/differentiate once, then programmed those operations into my TI-82 using whatever awful version of basic those things supported.
You programmed SYMBOLIC integration on a TI-82 but couldn't do it by hand? Are you sure you are remembering that right? Symbol integration is non-trivial.
Almost certainly not. It happened over 20 years ago so my memory is fuzzy, but I’d guess I still had to tell it which formula I wanted to integrate with. So to study I just had to be able to identify the correct formula. You might argue that’s the not much harder than by hand, but I was exceedingly lazy (still am, but now married with kids so it’s buried deep haha).
> 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.
...and that's how the the factory factory factory also provides immediate safety and security benefits!
There must be some metric of the resonance of a particular piece by looking at the number of reposts and distribution of comments amongst them (plus an analysis of the sentiment of the comments and characteristics of the thread trees in each separate posting).
Just looking at this listing, without looking at the comments in each one, this seems to have a sustained resonance.
Its resonance may sustain because theres always people entering the field who are trying to build something, and either get caught up on a frameworks hypetrain or have fond enough memories using a given framework to build something quickly, and then getting burned trying to build something ambitious with a given framework because its opinionation proves to be too rigid one way or another, and a perpetual new influx of these sorts of people are happy to know it isn’t just them who hate (or at least were burned by) frameworks.
One of the very first times I was paid to professionally develop software for someone else I totally fucked it up by trying to build some kind of “modular” “reusable” contraption, that in reality was a vague collection of ill-defined ideas for what I wanted to make.
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.
Overengineering confessions. He that is without sin among you, let him cast the first stone at her.
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.
Good abstraction is the foundation for most of what we do.
Bad abstraction is worse than no abstraction.
Not everything needs to be abstracted.
Ontology is bad abstraction (is a has a stuff).
Some people are bad at abstraction and some people are bad at writing business code; Both can be good coders.
Is “can do X” included in that definition (ie are you alluding to composition vs inheritance)? Can you elaborate on what constitutes good abstraction, in your book?
Exactly, that's one of the reasons I'm so happy where JS is as an indie dev (def not professionally though). JS has gone through so many "you need a factory factory factory", and now we have gone back to basic principles. A few examples I've lived:
- Browser incompatibilities. You couldn't just do X, because in other browsers X might behave differently. So you would write X blueprint and use an X factory that would auto-generate code for the different browsers. This applies to both JS, CSS and HTML BTW.
- Then the modules+bundlers came. Initially they were <script>, but when you had multiple you wanted to concatenate them for performance ofc, and in Node.js you wanted a way to import them. So a tool for each was created, then a tool on top of both was created, and thus a factory of factories of sorts was created.
- Then ES6+ came, which was similar to the first point so I won't bother you with it.
- Then Webpack and all of its derivates promised to solve all of the problems above, at the same time (with Babel and whatnot), and the era of mega-factories came to be.
Luckily nowadays we have standardize mostly around ES6+, and using ESM for imports/exports everywhere, so if you write plain JS and use ESM both in your code and in library code you don't need any more factories. You can still use a tool to bundle all your code, or to use more advanced coding paradigms like React*, but that's nowhere the peak of complexity we've lived.
That's one of the reasons I dislike TS BTW, because now that we are in "bliss plain JS" some people were not happy and had to add complex tooling again with TS.
*I draw the line here and declare that JSX is not JS, and thus this complexity thing doesn't apply there. If you are writing JSX you are writing it against CRA/Vite/Next, while plain JS you are writing it against the browser, so only things built on top of JSX, like TSX, can be considered factories from that point of view. If you think it's not fair, I'll argue it's as fair as JS, since in the end every browser is a "factory" of JS -> low-level code.
Which is precisely why a framework is necessary, but knowing how to write what you want without the framework is even more necessary.
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.
There is an art to translating whatever idea you have into large building blocks rather that coding it from small primitives.
Actually knowing how to code is important, but so is knowing how to take a problem and implement it without ever doing anything the framework authors didn't think of.
You might need a nasty hack like exporting a bitmap to a ramdisk and then importing it again to read a pixel value, to avoid messing with some nasty AI, or you might have a case where performance matters and you do want to mess with the buggy undocumented crap API.
It's almost like the idea that language shapes how you think. Frameworks are kind of like subsets or dialects of programming languages. If you actually know the framework well, you can often do stuff that seems like it would need low level control, in an idiomatic way that doesn't fight the framework.
I was thinking of building a Bluetooth device you can leave somewhere that alerts your phone should it be disturbed, as a portable security system. However the PineTime, an open source smartwatch, has all the features needed for $25, cheaper than almost any small quantity prototype.
Not sure if I'll ever get around to that project, but if I do, I probably won't be building any single function hardware just for it, especially not without being sure the whole idea is worth it.
> It's almost like the idea that language shapes how you think. Frameworks are kind of like subsets or dialects of programming languages. If you actually know the framework well, you can often do stuff that seems like it would need low level control, in an idiomatic way that doesn't fight the framework.
I think the analogy does not quite fit. A framework is certainly not a dialect. For me a dialect is a variant of the language in which you can accomplish almost the same.
A framework provides you with a couple of blocks for building something specific.
In terms of language, I'd say a framework is like technical jargon. Additional abstract terms that describe concepts useful in that domain. So domain experts don’t need to always explain everything from the beginning.
A framework is not a dialect, but a business context specific language.
You may re-use normal english words to have a new meaning. a bit like how companies like to have infinite initial acronym's for everything that nobody ever will understand outside the company.
There are quite a few titles which have appeared on the HN front page more than once. I've got an archive that's current as of a week or so back, and it shows 1,734 repeated titles.
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.
Not all appearances are front-page appearances. And my very quick & dirty shell one-liner requires precise text matches.
"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):
"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.
1 14 I'm Peter Roberts, Immigration Attorney Who Does Work for YC and Startups. AMA
2 11 Richard Feynman and the Connection Machine
3 10 Openssl Security Advisory
4 10 The TTY Demystified
5 8 Why GNU Grep is Fast
6 7 Cool URIs Don't Change
7 7 How to Read Mathematics
8 7 The Architecture of Open Source Applications
9 7 You and Your Research
10 6 -2000 Lines of Code
11 6 A Primer On Bézier Curves
12 6 Advanced Programming Languages
13 6 Bit Twiddling Hacks
14 6 Dictionary of Algorithms and Data Structures
15 6 How Not to Sort by Average Rating
16 6 How to Be a Programmer: a Short, Comprehensive, and Personal Summary
17 6 How to Write a Spelling Corrector
18 6 Keep Your Identity Small
19 6 Ten Rules for Web Startups
20 6 The Bipolar Lisp Programmer
21 6 The Tao of Programming
22 6 Why I Hate Frameworks
23 6 Why Lisp?
24 5 A Regular Expression to Check for Prime Numbers
25 5 A Spellchecker Used to Be a Major Feat of Software Engineering
26 5 Akin's Laws of Spacecraft Design
27 5 Ask HN: Idea Sunday
28 5 Ask HN: What Are You Working On?
29 5 Ask HN: Who's Hiring?
30 5 Beej's Guide to Network Programming
31 5 Data Structure Visualizations
32 5 Dna Seen Through the Eyes of a Coder
33 5 Game Programming Patterns
34 5 How Software Companies Die
35 5 How to Become a Good Theoretical Physicist
36 5 How to Design Programs, Second Edition
37 5 Latency Numbers Every Programmer Should Know
38 5 Learn C and Build Your Own Lisp
39 5 Learn You a Haskell for Great Good
40 5 Learning Advanced Javascript
41 5 Let's Build a Compiler
42 5 Notation As a Tool of Thought
43 5 Statistical Data Mining Tutorials
44 5 Structure and Interpretation of Classical Mechanics
45 5 Teach Yourself Programming In Ten Years
46 5 Terms of Service; Didn't Read
47 5 The Book of Shaders
48 5 The Case of the 500-Mile Email
49 5 The Early History of Smalltalk
50 5 The Scientist and Engineer's Guide to Digital Signal Processing
51 5 What ORMs Have Taught Me: Just Learn SQL
52 5 Who Can Name the Bigger Number?
53 5 Why I Left Google
54 5 Why Lisp Macros Are Cool, a Perl Perspective
55 5 Why Open Source Misses the Point of Free Software
56 5 Why to Start a Startup In a Bad Economy
57 5 You Can't Tell People Anything
NB: I've further tweaked my scripts (and titlecasing) which results in a few minor changes to the results, though the above list remains highly illustrative.
I think I've spammed this thread enough for now ;-)
The simplest route to that for now would be to search the titles via Algolia, sorting by popularity. I could I suppose gin up the URLs for that, though as I've already noted, I think I've spammed this particular thread enough with long-list comments. (HN prizes intellectual curiosity, and whilst a few tables might meet that criterion, I think I'm pushing the limits.)
The difference between my data & analysis and Algolia is that Algolia doesn't itself report on either front-page-specific items, or on stories which have been repeated. But given a list of front-page stories, or repeated-front-page stories, you can search Algolia ... to surface all instances of those stories. The front page will in general have
If you're suggesting I list the URLs themselves directly ... as I'm working with the archive data, I don't have that readily available.
My current workflow is, roughly:
- crawl (or update) the front-page archive
- rerender the captured HTML as plain text, using w3m's `-dump` flag
- parse that text into a tagged multi-line-per-record format with the raw title line, parsed title, date (and several sub-element parsings of that), site ( as reportedd by HN), points, submitter, comments, and (artefact of the original question I'd sought to answer) any US cities or states mentioned
- create various reports and abstracts based off of that. "hn-titles", "date summary" (mostly the parsed data arranged on one line for easier awk processing), cities (US and "globally significant") and US states reports, etc.
Conspicuously absent in the parsing (3rd step) are both the full article URL, and the HN post URL.
I've got those, in the raw HTML, but I'd need to go through that and parse the original which up until now has been Too Much Work given what I can do with what I have now.
And if you're wondering how many votes are required to make the front page, here's a summary, by year, of the univariate stats for votes for the 30th story per page, that is, the lowest-ranked:
Note that the first three years were pretty low (min = 1, mean = 2.48, for 2007), but goinng back 5 years a story with > 23 points could have made the front page. There are also a few days with < 30 stories, all occurring in 2007 if memory serves.
(This is my first time seeing these particular stats, another analysis I'd been thinking of doing for a while. I had calculated the delta between 1st and 30th ranked stories going back some time. Also the variance by day of week, which is also fairly significant.)
This is the fun of posting my work publicly. Someone will pick it apart, and then it's a challenge to see if I can address the concerns.
I knew my first attempt was quick-and-dirty. It took a few minutes to improve that a lot, a few hours to track down numerous other issues (mostly involving title-casing exceptions, and adding more terms to that script which should either not be titlecased (e.g., "DNA", or which are mixed-case (e.g., iPhone), or which are ambiguous and should be treated differently in different cases (e.g., "us", which might be a first-person plural pronoun, or an abbreviation for "United States").
For the latter, I determined that "US" appearing either immediately after "the" or at the start of a title was virtually always the United States sense of the string. I've enshrined that in `titlecase`, though there are probably some other terms that tend to occur before or after the term which could be used to further disambiguate, say, "US Congress", "US Senate", or "US Law", for example. The additional gain from those is small.
If I were writing an AI then it might incorporate those weights, but this is just a simple sed script...
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.
Yup that’s why I like babylonjs. It’s not so much good documentation but that the docs try hard to have working codepen style examples for almost everything you can think of doing with it. Code as documentation. Contrast with a lot of python docs where you usually get a docpage telling you what the arguments are and the return type but nothing else.
If I had to guess I would say there is a common resonating theme this strikes with many developers:
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.
I don't get it. I assume the author is trying to make it sound absurd that you would need all these layers of factories to build a simple spice rack and, by analogy, that frameworks are also absurd.
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.
That's a mistake. Imagine you're instead a carpenter.
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.
Unfortunately this is true, as I grew more experienced I’m very careful with the dependencies I add to a project. I don’t work with React Native but I hear horror stories of how the hundreds of dependencies force you to either stick to the old versions of stuff or keep fixing or rewriting things that used to work. Seems totally unsuitable for a side project you want minimal maintenance over time.
If “hello world” is the whole requirement behind an app, and you won't develop it further, you don't heed to use react. In fact, here's your whole app: “hello, world!”. Copy it, save it in .txt file, serve in static anywhere you want.
I wish more people would actually follow this advice. When they don't need anything "reactive" they would not use React. When they don't actually need an SPA, they would not use React. When they don't actually need dynamic behavior on a website, they would not use React or JS.
But unfortunately people use what they don't need all the time, rather following hype than reason.
Or, may be, they use the tool they're familiar with, because what they need is to be productive immediately instead of wasting their time to learn different tooling. Even if this different tooling is simpler that what your already know.
Right but the earlier you catch your mistake the more time you'll save in total.
Generally people use 10x on cost at every subsequent step. Andy Grove famously talked about how this made the FDIV pentium bug cost Intel untold millions instead of pennies.
He said when the mistakes and decisions seemed free early on, that's actually when they were the most expensive.
As more commitments were made towards the design, it became costlier to back out. Then they discovered it after production and shipping, and by then it became so costly and famous people still remember it 30 years later.
To be more direct, if someone doesn't know how to do it right they Shouldn't Be Doing It. If someone can't fly a plane, they shouldn't be flying planes. If someone can't operate a construction crane, they shouldn't be operating one.
Same thing here. If they're doing it wrong because that's all they know, they are unqualified. They should not be given the responsibilities.
So that method of doing what you're familiar with is the cost of incompetency. Planes and cars crash under incompetent hands and software doesn't fare much better.
I'm a little bit confused. At first, we were talking about people using React for Hello World or similarly small and simple project, but here you're talking about making architecture decisions for huge projects?...
In context of a simple project: yes, React is not the best tool for the job if you look at project requirements. But also consider the fact that the bundle size and optimization might not be that important from business perspective, and project scope is very limited from time perspective. That's why using React might be the best choice: you're optimising for developer productivity on the short run.
However, the situation you are describing now is different. Not only project's business priorities are different, but also the scope is much larger. Which means that spending time on choosing tools and learning a new tool would tale a much smaller % of project's timeline, and thus it makes sense to spend a lot of time on that to potentially save a lot of time and improve other characteristics later on.
In other words, you don't do pre-production on hello world, but you do on something huge.
Who is going to maintain the React app in 3 years? Who is going to work with the various "repairments" made to get normal browser behavior back into a SPA? History, back button, forward button, bookmarkability, context menu (if modified). The original developer will have moved on to the next gig. Are you going to rebuild, or pay even more for the next developer with more experience, to subject themselves to work with this?
This is the hidden cost associated with such decisions. If you decide to make it an SPA, you are automatically opting in for paying wages of frontend devs for the next years and not only that, you are probably opting in for them to need longer time to get browser staples back working. Things like a navigation, that could be a rather simple <ul><li> construct, maybe 1 or 2 days of work for rendering simple HTML templates on the server, with some nice CSS styling, can suddenly take weeks to implement and adjust. Can the most likely little need for SPA justify this extra cost?
Usually you are also not only having one frontend developer, but multiple ones to pay, since you don't want all the knowledge in one hand only.
Take a good developer salary and this can easily get into the millions over the years.
> Who is going to maintain the React app in 3 years?
Uhm, developers? Using projects documentation?
> Who is going to work with the various "repairments" made to get normal browser behavior back into a SPA? History, back button, forward button, bookmarkability, context menu (if modified).
I never had to manually “repair” any of that. Most often you just don't need them. Why would you use a back button in an image editor or an IDE?
> The original developer will have moved on to the next gig.
Developer, singular? Are we taking about small projects here again?
> Are you going to rebuild, or pay even more for the next developer with more experience, to subject themselves to work with this?
In my personal experience, React projects were one of the nicest codebases to work with. I came to projects 2-4 years old, found great documentation, good architectural decisions, and was able to compete a ticket on the first day.
Overall, I think it’s a difference in experience. I build complex web applications. IDEs. User interfaces with complex, customisable data widgets updated in real time. People I talk with about web development are building 3d visualization platforms with C++ compiled to WebAssembly. Games. Image editors.
What your are talking about seem to be simple CRUD apps. I have built those with server-rendered templates, yes (here's a takehome for some company from a couple of years back: https://github.com/golergka/url-shortener).
However, a lot of apps _seem_ to be simple CRUD apps in the beginning, until you anticipate future features and other requirements that will force you to adopt a frontend framework all too late. Do you need a form with search over content from the server? You need a system to query data and cache the results. Update data in real time with websocket connection, while also allowing your user to edit it? You need a system to consolidate state. Save user's data in local storage? Also local state, but also schemas and migrations for when your app updates. Table of 100s of thousands units of data, which user should be able to filter, sort and edit, with updates from the server too? Don't even get me started. There's a lot of other examples I'm too lazy to type. Overall — you either adopt a proper frontend framework or try and implement it in “simple JS” and then spend much more time fighting a lot of subtle bugs that simply would not happen if you used proper abstractions and tools.
You mean the documentation that was never written, because the developer thought: "Ah but this is just the usual usage of the framework I am using. I don't need to write anything about that."
> I never had to manually “repair” any of that. Most often you just don't need them. Why would you use a back button in an image editor or an IDE?
Well, on most SPAs you would need them, because people build SPAs all the time without caring, whether they are actually building an app or are actually building a website. So what you get are things that would be a normal website, but implemented using SPA frameworks and then have broken browser functionality. An IDE or an image editor would probably be OK examples for SPA, but the reality unfortunately is very different.
> What your are talking about seem to be simple CRUD apps. I have built those with server-rendered templates, yes (here's a takehome for some company from a couple of years back: https://github.com/golergka/url-shortener).
Exactly! I am talking about the cases, when people take out the sledgehammer, where a screwdriver would have been appropriate.
Yea it’s nonsense. Factories are fantastic. If you want to do something as a hobby, sure don’t use the most advanced tools and do it by hand, but for everyone else especially professionals who are charging other people for their time and effort using the best possible tooling is essential.
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.
I use the same argument for IDEs versus fancy text editors like EMACS. Sure, you might prefer the specific keyboard shortcuts, but IDEs objectively make developers more productive through features like source code integration, debuggers, and refactoring capabilities.
Use whatever you like on your home projects, but at work you should be using whatever is most efficient.
And interestingly, your argument also falls apart in the same way as the framework argument. It might make the average developer more productive on an average project. But most projects are not average, and neither are most developers. Everyone has some unique combination of strengths, just like every project has special cases that don’t fit within the box of a framework.
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.
You could argue that it's specifically true for projects, but the definition of average absolutely doesn't require that.
If for example you had 100 projects were 50 of them were built by expert teams who poured love into their work, and 50 were made by 12 year olds who spent one day on their projects before giving up, the "average" quality of the 100 would be a long way from either the great or the shit products.
Likewise if a group of ten people has five CEOs earning a million a year, and five waiters earning minimum wage including tips, none of the ten are "by definition" earning half a million a year.
Of course in my data sets there is a kind of "normal distribution" such that most objects are near the mean, but that needs to be found out not assumed.
I have no idea how many tech products are near the mean as opposed to near one extreme or the other, and doubt anyone could guess without bias and without actually researching the question.
> Most projects are average by definition. Otherwise that wouldn’t be the average.
You're assuming outliers in both directions don't dominate the process.
As an example, let's say we have 10 projects, that have some property that can be rated on a scale from 1-10. Difficulty to accomplish is the first thing coming to mind. If we have 5 projects that are a 1 on this scale, and 5 projects that are a 10, the average is going to be 5.5 despite none of the projects being anywhere close to that.
There’s way too much variance in projects for the average to be meaningful, in my opinion. They will have some or many average parts, but they will also have some number of parts that are special.
It might be normally distributed, but across tens/hundreds/thousands of dimensions. For example, some axes might be
Like, if you want a terminal-based UI and don’t need SQL access, then you definitely shouldn’t use Ruby on Rails.
Some of those dimensions are obvious at the start of a project but some aren’t. You might not find out until later that you need something that your framework doesn’t support. And when that happens, you can end up in a situation of hacking together the feature working around the framework, especially if there’s a deadline.
Like I said, frameworks are great if you are very careful with their limitations.
It's a really weird sentence. I think most people would consider IDEs are the "fancy" ones, compared to emacs. I have to read your comment 3 times to ensure I didn't read it wrong.
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.
"I actually wrote a vim versus IDE comparison. Do you know how much faster vim was? 4.3 seconds! 4.3 seconds I saved every day! All those months learning were totally worth it."
My experience with having to use Spring Boot everywhere is that the amount of effort involved in debugging Spring Boot problems is hardly worth the benefit of avoiding the minimal glue code to call some database or pass around some object. But hey, some dentist said this toothpaste is the toothpaste to end all toothpastes...
What with Google and now GPT, it's critical that your framework is well talked about on the internet. Otherwise searching "show me some code to do XYZ using the frankenframework" will come up empty and then it's game over for your framework.
That makes building your own framework even less of a good idea than it used to be.
OTOH, if you build a framework/library, you might be able to use AI to generate thousands of examples of using your framework/library, then publish those examples. If it's too difficult for the AI to generate correct examples, then that may be a sign of what parts would also be difficult for humans.
We may in fact see an explosion of new frameworks and libraries that use this strategy.
Like factories, frameworks are methods of reducing production costs, but come at the expense of certain aspects of product quality.
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'm not sure the expense of reduced quality is even an issue. Just like an (decent quality) spice rack I buy from a store is probably better quality than spice rakes built by most people, an app built on a (decent quality) framework is probably better quality than apps hand built by most people.
> the 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.
Exactly. This post falls apart because it's predicated on the company not selling hammers anymore. That's not true about software: you have plenty of choices if you don't want to use a framework. People are happily string together libraries to make web servers in almost every language I know of, including the heavyweights like Java and C#.
I think you might actually be surprised at the level of non-sophistication of most of these factories. Especially for the "made in China" items, but even in the US. My friend works at Masterbrand, a HUGE houseware manufacturer and it is essentially a massive workshop of people using the most basic tools within reason for the job. This is specifically by design because they found that the more advanced tools required more advanced workers and upkeep that ultimately made them more vulnerable to labor and tooling disruptions. Now 99% of the jobs are setup where anyone can step in with very minimal training.
Indeed, but they don't just do basic items. They make huge industrial products the same way. See this video for example where they melt down steel scrap in arc furnaces covering their faces with just cloth and pour those huge steel gears.... https://youtu.be/2lrGQbMEHaQ
By that very analogy, using frameworks for building a service is absurd.
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.
Is the author trying to build themselves a spice rack or many spice racks for all the world? In one of those cases, yes, you would want a factory, but that isn't this case.
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.
And the spice rack itself is just a container for preprepared ingredients from spice factories, to enable a cook to easily access them.
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.
The point that flew over your head is every one wants one spice rack. There is no scale, no one wants a 1km long spice rack or 10,000 small ones either. That you can just buy a ready made one is even more to the authors point. Most software shouldnt exist! Why even build a spice rack, indeed!
I will give a counter point.
I love well-designed opinionated frameworks. Whenever I want to do something simple, I agree that a framework may be overkill. A micro-framework is nice for those scenarios though.
However, whenever I build a project that will be maintained or extended by many people, opinionated frameworks give me the advantage that they force you to do things in a particular way.
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.
> 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.
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.
Strongly agree. For me the mark of a useful framework is that is reduces the complexity of the task you are trying to do. If it increases the complexity of the task, it isn't the right tool for the job! Choosing the right level of abstraction is the most important part of software engineering.
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 think it really depends on the use case, no? You can design a framework to be more or less restrictive, and the best tend to be less so, (which allows you to do stupid things but has good guidance on how to NOT to do that).
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.
I disagree with the problem statement; that the framework is trying to solve a meta-problem.
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.
Yes this is possibly why the author renamed the post. There certainly has been a problem of over-abstraction in the industry, with some of the most guilty parties being the frameworks (e.g. the infamous AbstractSingletonProxyFactoryBean from the Spring framework).
Maybe. But that specific overabstraction is in the implementation of the framework. It's trying to proxy all the method calls to objects to perform logic around them. It is true that Spring wants the developer to configure auxiliary logic that gets applied around the written code, instead of actually calling that logic. So perhaps that's what the author was getting at.
I think of frameworks as essentially higher order functions, e.g. map/reduce, where one provides the function parameters. That many frameworks seem much more complicated than this is certainly not a good thing.
There are still good frameworks that don't take unnecessary control. I think the most common bad ones have some ulterior lock-in motive, usually some company trying to extend its influence, and you have to look out for that.
Yes, the state of the industry is a hot mess, but I'm not sure this article rings true. Failing to leverage good frameworks is as big a problem as over using the bad ones. I would point to Rails as an example of an appropriate framework (and Laravel if PHP is your jam). The trouble is so many others are bad, incomplete or defunct, but I don't think the answer is the golang mantra of 'we don't need no stinking frameworks'. Seeing mediocre developers reinvent the wheel, slowly and badly, is super painful and wastes time and money. If you hate the frameworks available to you then perhaps you should consider finding a better ecosystem. Relax your bias and follow the happy developers, wherever that may lead.
I'm not sure I'd describe the golang community's attitude as a complete write-off of frameworks. I don't think I personally know a Go developer who doesn't use some sort of web framework (I personally use Echo, for example).
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 agree with your more nuanced take on the golang community's position. I still think that a fully realized framework is, in general, a better starting point for the vast majority of projects. Part of the problem is that such frameworks are few and far between. I'll stick to the Ruby community: I know developers I respect who really like Sinatra, which would be more akin to a microframework. It is their go to starting point, but when I go to work on their projects I very quickly find myself straying out of Sinatra's capabilities into things that are fully baked into Rails. I then have to spend time pulling that capability into Sinatra, which is not how I like to spend my time as an application developer. There are many frameworks that are positioned as 'elegant' or 'focused' when they are simply incomplete in the face of real world development and teams end up having to either cobble together disparate micro-framework or rebuild basic capabilities to get to a fully realized app. I would argue that is not time well spent and that everyone thinks they are super good at creating solid, performant, extensible, well documented code, but they are not (statistically speaking) and by then it is too late and others have to live with their junk for years, or worse yet they all bail because now they know hot-framework-x and board the recruiter train to their next salary bump.
Laravel is prime example of a bad framework trying to reinvent the language, educating young developers to use it and its ecosystem and to never get out of the stranglehold.
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.
I don't know the php ecosystem well at all. I just didn't want to come across as 'Rails is the only one true way'. Lots of php folks seem to love it, and it derives a lot from Rails, so I thought it was a fairly safe shout out. But, it is HN after all, so no opinion can be put forth without and equal and opposite negative reaction.
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?
Why would you imply I tried to say anything against frameworks in general? My comment was specifically about Laravel because it was singled out as a great framework.
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.
The only case where failing to leverage a good framework would be a real problem is in front end development, and that's just because the front end stack is so horribly designed that it often needs a framework just to make the complexity demanded by business possible. Those frameworks often bring in a ton of problems, of course, so it's really picking your poison. But libraries and hand-rolled solutions should be used when you aren't stuck with JavaScript.
I remember following up the Angular tutorial. I was about 15min into the tutorial, and I was already editing 8 different files. I never got lost so quickly. I lost a job because I could not use angular, but never felt bad about it.
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.
This is why React won: No template language to learn. No prescriptions for managing your app. No piles of abstractions to do basic things. It's just a UI lib. Import it, declare what to paint on-screen, done.
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.
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.
It's also part of its hate - it's been wrangled into a hot mess with routing, data fetching, state management and inability to play nice with html elements (specifically forms; controlled vs uncontrolled components). Not to mention "pure" functions vs classes, hooks, context, render lifecycles leading to the development & usage of useMemo() etc etc.
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".
> Oh, you want routing? "Not my business", says React. Go add a routing library
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.
Most often you don't have to go through so many. The community usually has some preferred selection of tools and you have to choose from 2-5 different options. You still need to do some research but it is not as bad as you present it.
The advantage of this is that better tools may replace worse tools and totally different approaches can be tested whereas you have to hope in a framework that the initially chosen strategy can be improved enough.
Counterpoint: While $MYFIRM is a React + Django shop and that's absolutely the right decision due to ecosystem factors, I do wish Ember had won the frontend ecosystem race.
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.
> 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.
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.
That's why angular is hated so much. It makes easy things more complicate. In my opinion it's a bad framework. Use a good framework instead! Just because some (or a lot of) frameworks are bad, it doesn't meant that the concept of a framework is bad.
Same experience with Angular; idk what they were thinking. Just a button is like 10X harder than vanilla JS. React showed that you can accomplish the same thing with a lot less repetition, which is odd because there's supposedly less going on under the hood than with Angular.
I'm not a huge fan of these pieces that don't speak to why frameworks are created in the first place.
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.
Related: "Write libraries, not frameworks," which goes more into depth about how frameworks establish precisely such a "seam" and the responsibilities it entails.
> Frameworks' key trait is that they impose limitations on the programmer. Rather than providing a set of new things the programmer can do, they establish a boundary on the things the programmer can do.
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.
Not sure it's always the key trait. In software frameworks are so often accompanied by a rich library of packages or code that folks may consider another important trait is their baseline of functionality.
Some frameworks are "batteries included" while others are a "bag of reusable components".
Ah, but that is exactly where the carpenter analogy truly works - a good carpenter understands the strengths and weaknesses of all those techniques, and when to apply each. Just like a good software dev understands when to apply frameworks and libraries, and knows enough about each to choose the right ones. (And yes, which ones just aren't quite ever the right answer.)
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.
Yeah but React is really good. A lot of these articles[0] delve into an analogy that they twist into a complicated mess and say "hey look at how complicated frameworks are." But React isn't complicated. Most kinds of interaction, even for the smallest apps, are easier with React than with vanilla JS. I've never felt like I'm managing a factory factory factory when using React. And if I do, it's easy to peel back the veil and write vanilla JS alongside React.
[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.
>Most kinds of interaction, even for the smallest apps, are easier with React than with vanilla JS.
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.
Sure, to me a library is something you call, like ReactDOM.render(), React.useState(), etc, and a framework calls the code you create. You create files and modules for a framework in the way that it dictates, and a library doesn't constrict you in any way.
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.
Oh, this is new to me. It's not recommending create-react-app, it wants me to use Next.js or something. Yeah that seems like a bit much. I was even doing a React project recently and went straight to create-react-app, bypassing all this, haha.
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.
Yes, you can use React not like a framework, but very few people do that. If you say you're using React, it's assumed you're doing it the usual way (with JSX and all).
You're conflating React the library with create-react-app which is a collection of pre-configured tooling for making SPAs. React on it's own is very much just a library with a couple functions.
The standard docs can go fuck themselves. I've never seen a community try and fuck up a good library as hard as the React community does.
React itself is great. Almost everything built on top of it and every word spoken about it on the internet is garbage.
The incessent focus on shit like CRA, NextJS and people shitting themselves over "NIH" is going to kill React in the next decade and we're going to be stuck with something 10x shittier in it's place. Well done team!
For bad docs, my stuff worked pretty well following them. Is create-react-app really gonna screw up my project?
Will say that the React Native docs suck because they keep trying to shove Expo down your throat, which simply doesn't work if you're trying to actually build a production app, plus it keeps changing and breaking stuff. Or at least that was the case a few years ago; I haven't even gone there since.
Edit: Seems react.dev is beyond create-react-app and now it's pushing some overkill stuff that feels like corporate lock-in. Yeah that's a concern.
Part of that is almost certainly because it is far, far easier to explain how to get started with create-react-app then it would be to explain the various alternative approaches, especially considering how inexperienced on average the kind of people who are looking up how to set up a react project must be (professional developers needing the information for their actual work probably constitute a small minority), even if those alternative approaches themselves are not complicated at all to those who have the prerequisite knowledge to understand how a library like react would be incorporated into their particular setup.
Some inline on(event) attributes can be simpler to enhance basic MPA functionality, compared to pulling in React. I suppose it depends on the requirements and what one is most comfortable with.
This was written in 2005. I feel this ship has so sailed at this point. I would love to go back to the world where I had the bandwidth to waste on framework hating.
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.
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.
Reminds me of an issue I submitted against Apache WS-XMLRPC 15 years ago, related to a class named RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory:
This reminds me of FizzBuzz Enterprise Edition and I have come across software that was pretty much written like this more than once.
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).
You know why this is so dumb? Because there's an analogy that's very similar that explains why we have frameworks.
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!
It appears that you are entirely missing the point and the author's criticism of frameworks. Your analogy is the false promise repeatedly fallen for that created the situation described in the story.
No, i get it. But the author analogy is dumb (even if funny). There's literally no one stopping you from just downloading a "hammer" from the internet and just using that. The "stores" haven't stopped selling "hammers". Even if they're also selling "factory factory factory".
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.
I do take the point but I feel like the era of the factory factory was a while ago and I'm almost nostalgic for it compared to the dubious soup that we seem to have to deal with now.
I want a version of this satire where they only sell hammer subscriptions, but to get the hammer the guy actually wants he needs to buy an Extended Hand Tools subscription that auto renews and costs as much in three months as buying the original hammer would have.
It's not a hammer subscription, it's hammering-as-a-service. You ship them the nails and wood, they ship you back the nails hammered into the wood. You don't have to worry about the complexity of storing or using a hammer anymore, let alone the difficulty of selecting the right hammer, it all just works. They charge extra to sell you the nails and wood, to avoid the complexity of packing and shipping your nails and wood.
They have strict specifications about the types of nails and wood that they can hammer, but they're not documented anywhere. If you send them the wrong type of nails or wood, they'll put them both into an industrial shredder and send you back the dust, because technically the nails have now been integrated with the wood.
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.
Frameworks are bad because they don't compose. What does compose? Simple types and pure functions. If you want to create a community with high levels of code reuse, start there.
I was listening to a talk (strange loop conf, can’t search the talk itself) where the speaker claims C and languages derived from it feel clunky because they were invented, while Lisp, Haskell were discovered. The latter group is more cohesive and relies on simpler truths instead of the amalgam of idioms you can find in Java.
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.
> "Really? I thought you just said that the Universal Hammer was the wave of the future."
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.
I've always been hesitant about adopting frameworks, and I still favor Flask over Django. Yet, I spent a couple of years in a Go-centric department where the senior members were so against using frameworks that we ended up building everything ourselves from scratch. This included creating our own load-balancer, event store, and aggregation engine.
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.
There is no silver bullet that solves this problem.
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.
There isn't a one-size-fits-all solution to this issue.
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.
Dare I suggest that it is possible that the nimble startup was moving quickly not necessarily because of tool choice, but because of the small team size and because the appropriate amount of complexity was introduced? And conversely the inflated team was slow exactly because it was inflated and complexity was introduced? This effect happens with or without bringing third-party or in-house tooling/frameworks into the equation, and is well known and well covered since Mythical Man Month.
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.
The speed difference boils down to flexibility and tool usage. In the startup, I could swiftly create a new service, harness Kubernetes for deployment, and seamlessly integrate it into the existing architecture. Data computation used tools like Airflow/BigQuery, storing results in production PostgreSQL.
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.
I think there's too many red flags there to chalk it up to a single problem: time-consuming conversations, rigid abstractions, resistance to changes, demanding PMs, total overhauls needed, more bureaucracy on change approval, you also complained about fixation on code quality.
Saying that it's all up to the one single difference even though there's so many ancillary issues screams of "I've found a silver bullet syndrome" to me.
Simplicity is easy to mandate: "just use simple tools!". It's not always obvious when the finished product looks wonky and slanted and has to be retrofitted several times that the complexity was always there, in the world. The complexity in our tools is hopefully there to help with some complexity in the world.
In my experience, it's always the junior who shouts "This could all be so much simpler!".
> 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.
I just listened to George speak to Lex. He talked about the engineering time they spend in tinygrad to make it simpler. A lot of hours goes in to refactoring to make it as simple as it is. Writing simple software for complex problems takes a lot of work.
The path of least resistance at every step is definitely more complexity, so that’s what happens. Fighting complexity has to be actively prioritized.
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.
> In my experience, it's always the junior who shouts "This could all be so much simpler!".
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."
Yes. My “worst” code was when I was mid-level. Too clever, showing off what I learned.
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.
> My “worst” code was when I was mid-level. Too clever, showing off what I learned.
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.
In my experience, it's always the junior who shouts "This could all be so much simpler!".
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.
In my experience, juniors almost never shout that. They are still living within the managed "website in 0 lines of code!" world the framework purports to provide.
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.
> 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.
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.
IMO senior understands that simplicity is possible, but economically not viable for most projects. So complexity is inevitable evil. And true mastery is delivering products, keeping complexity at bay. Not spending time to pursue ideals and at the same time keeping project from felling down to unmaintainable mess.
> In my experience, it's always the junior who shouts "This could all be so much simpler!".
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.
> 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.
As a senior my goal is to write that really complex stuff and then hide it behind a simple interface that always works the way you expect so you never have to look under the hood.
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:
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.
For others: this is the classic Out of the Tar Pit paper, which I also adore so so much. It promotes very explicit state management and functional programming to reduce accidental complexity.
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."
The difference is, that the universal hammer is in fact mostly good enough, or at least can be, if it's well designed, for everyone except people who are interested in simplicity for its own sake.
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.
Frameworks are good if what you are trying to do aligns with the model/architecture of that framework. Trying to do something outside that gets exponentially more painful the further away you are from that framework.
The same also applies to external libraries and the architecture of your library/application.
Bad frameworks suck, good frameworks are good, that's about it.
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.
Just FYI, when this was written, "framework" was a buzzword. Everyone tried to write a framework for something, and tried to sell it over well-working libraries. The hype died down because it became obvious that frameworks are overly complicated and don't compose well.
p.s. The hype predates even HN. I remember reading these stuffs on magazines. Holy crap, I'm old.
This must be a Java joke I'm too C++ to understand.
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...
It is Java's particular set of features and lack of features that give programs written in it a tendency towards design patterns like the one described.
- 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.
Well, there's not much preventing a C++ programmer from limiting themselves to a feature set similar to Java's (replacing garbage collection with generous shared_ptr usage).
This piece was written before React even existed. (React is from 2013, this is from 2005.) Besides, I can't think of a single "factory" oriented concept in React, could you elaborate?
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.
If we step back and look at this as a problem of abstraction. An advantage of abstraction is that the people working at the higher levels of the abstraction don't need to know what is happening at the lower levels. Therefore people can specialise and we can achieve better efficiency as an industry. If everyone needed to understand everything we'd be screwed.
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.
So coming from c++ these factories are sounding a lot like compilers, how does a framework differ from a new language and standard library?
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.
The fallacy here is the assumption that we get "hammers" as libraries, and not some splinters of wood in one crate and a whole bunch of hammer heads in another.
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.
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.
Show, don't tell. You know what would be more effective than these dozen "frameworks are bad, React is bad, programming sucks these days..." posts a day? Just show me your work. Link to your websites and repos that you built by flipping bits with a magnet or whatever other level of abstraction you prefer and let me judge its worth. Let me see how clean the code is, how easy it was to build, how mature the final product is.
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.
For me the most important issue with frameworks is debugging problems.
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.
Two sides to this. Author uses everyday life to describe the multiple layers of abstraction in software engineering. That's precisely the advantage of software: that abstraction is easier to construct—by simply writing down rules in text files—than mechanical engineering or other fields.
This is a great article, and I pretty much agree with everything in it.
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.
Any non-toy web service development, I disagree. HTTP is great except for the fact that as a protocol it carries no built-in mechanism for introspection on the services/types offered by an API. Openapi addressed this. But building an openapi spec by hand is moronic. Frameworks like fastapi or nestjs (forgive me if im forgetting your favorite) will generate an openapi spec. That spec can be used to autogenerate type safe clients, which solve the problem of HTTP not having discoverability or type safety.
After reading this I understand why angularjs is a different kind of framework. Instead of a factory factory factory you get a provider provider provider, which is 1000x better.
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).
> So this week, we're introducing a general-purpose tool-building factory factory factory, so that all of your different tool factory factories can be produced by a single, unified factory. The factory factory factory will produce only the tool factory factories that you actually need, and each of those factory factories will produce a single factory based on your custom tool specifications.
Looks like someone's been doing too much enterprise Java progamming!
Framework-itis is a widespread disease. Developers and technologists weaponize frameworks to win arguments and feel vindicated that they are setting professional standards
Even worse, training beginning app designers that the implementation holes in the framework is the crayons in their new design approach to the app. At first, some see it but many do not. My bias, I app design with the flutter framework one of 3 front ends Google decided to devote engineering time towards.
It’s easy to hate on frameworks due to their secondary problems once you’ve lost sight of the original problems. If you stop using a framework, you are bound to recreate one probably shittier framework. Although I do agree premature abstraction is a bad idea you still need some
Essays like this are not constructive imo. Reading it I'm not even sure what a "framework" is to the author. It would make more sense to talk about the specific technologies that inspired the rant, and then evaluate the tradeoffs and suggest alternatives.
I’m reminded of the YouTube/Facebook videos where the furniture maker first makes their own lumber from timber, planes it down etc. It’s really not necessary for the vast majority of projects you can buy good quality hardwood at the local mill.
I disagree, “req/res body cookies that’s it” is not the underlying system. It’s an abstraction over the TCP/IP and HTTP stack.
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.
I might be doing it wrong, but I just approach those as new pipes to be put onto the system? they're after all basically different ways of transmitting data from point a > point b.
Why would you choose a framework that didn't provide a escape hatch for your use case is the real question tho.
Anyone who has worked in Python or Go would tell you that it's not the right analogy. Opinionated rigid solutions kill innovation and this analogy is rather quite innovative!
A misconfigured or naively implemented spice rack never provided an entry point to leverage your infrastructure to engage in illegal activity and resources at your expense.
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.