Ask HN: In what ways is programming more difficult today than it was years ago?

237 points by luuuzeta ↗ HN
Reading Peter Seibel's Coders at Work, and this is Joe Armstrong on the issue:

>Also, I think today we’re kind of overburdened by choice. I mean, I just had Fortran. I don’t think we even had shell scripts. We just had batch files so you could run things, a compiler, and Fortran. And assembler possibly, if you really needed it. So there wasn’t this agony of choice. Being a young programmer today must be awful—you can choose 20 different programming languages, dozens of framework and operating systems and you’re paralyzed by choice. There was no paralysis of choice then. You just start doing it because the decision as to which language and things is just made—there’s no thinking about what you should do, you just go and do it.

For context this book is copyrighted 2009 so this interview is more than a decade old, and I'm sure many things have changed since then.

323 comments

[ 2.9 ms ] story [ 218 ms ] thread
Established companies with opinionated infrastructure can help with this.

I sure wouldn’t want to write the backend of a crud app in Fortran, nor the front end. Or do anything with Fortran besides scientific computing (Fortran = Formula Translator…it was built with a limited use case in mind!)

Companies that adapt to newer frameworks and not write everything in C++ are more efficient, but only if they control how much variation of tooling there is within a discipline.

So today, you do have to specialize in a discipline a bit more (front end, backend, data) but each discipline has a sensible set of tools IMO. A developer can and should get some exposure to a secondary discipline to be well rounded and “T-shaped”, but should also appreciate the value of specialization.

> each discipline has a sensible set of tools IMO

More like 4 or 5 distinct sets of tools and that collection changes every few years.

That’s fine. I’d rather use Airflow than Luigi, BigQuery/Snowfake over Hive.

Evolution is generally good.

So, yes, within a discipline there is more than one tool, but often only 1 or 2 current tools that are mature and worth using if you’re starting a new project

I think the overabundance of choices is still a major issue but I think an even bigger problem is the growth in complexity of languages and development environments. C++ was already a complex language in 1998. Today it's probably at least three times bigger, to the point where being a true expert in the language is almost beyond the capacity of a single individual. Other languages and ecosystems are no better. There's little comparison between what you had to know to consider yourself an expert web developer in 2000 compared to today.
Indeed, it's a monster language - every 5 years it looks completely different, but it'll take 15 years to get even the mainstream compilers to implement the changes from 5 years before.

It makes little sense to violate everything we know about language design (esp. regarding simplicity and orthogonality) and the cognitive limitations of humans (esp. developers) and keeping the Frankenstein language alive.

It got hashtables in its standard library only when everyone and their dog had already been forced to implement their own for 15 years!

And STL is so complicated that Stroustroup joked that he couldn't have done it if Alex Stepanov hadn't been able to pull it off. That may be a compliment to Stepanov's intellect, but it isn't a compliment for C++'s design.

The growth of language size in the past 30 years is even more stunning when you compare today's C++ to C, or Java to Pascal (or Object Pascal) from 1990. No modern language can be taught in less than a thousand page textbook. And if you include the standard templates and libraries the book size can double again.

The evolution of any language inevitably adds reams of extensions, variations, and libraries. This makes the tool not only a lot more heavyweight, but much slower and harder to master, and personally, a lot less fun to use. Give me a tiny simple language (e.g. C) any time over a giant language that requires me to navigate multiple programming paradigms and layers of abstraction (e.g. C++).

Modern languages are like having to speak in Latin. You spend all your time trying to please an nazi grammarian, rather than speaking simply and naturally, as the language was originally conceived.

You also have a whole lot more polyglot codebases now. So it's not just one language, it's all of them. As a web developer, you'll likely be working with PHP, Javascript, and Python, sometimes Ruby and Go for some things, along with a number of specialized config languages for things like docker, nginx, etc. And of course they each have their own package managers, dependencies, etc. If you thought _one_ language was getting complicated, just wait until you see a system that uses a half dozen of them.
There's some truth to this, but unless you're in a senior architect position or starting a clean sheet project, it's unlikely that you'll have the freedom to choose your platform or framework as a programmer. Like pilots, most people will start out doing "short haul" work on existing equipment and routes. This means you'll have to learn the frameworks that your employer (or desired employer) uses.

And those things, frameworks and platforms, are the biggest technical burdens for programmers today. The ability of the web to create what we used to call "interactive apps" (but are today just apps) has lead to the desire and expectation that all web content will take on this level of polish and appearance. While that's possible, it's also arduous. In today's world, you must also learn the frameworks, tooling, and CI/CD processes that lead to your work making it onto someone else's screen. That's a whole lot harder than what we used to do -- like when publishing meant copying a floppy and putting it in an envelope, for example.

The ability of platforms to change their specs and rules all the time (and their insistence on doing so) is another new programmer burden. In the old days, one could write to a piece of hardware or OS and expect that code to run for a long time. Not so anymore. Now the hardware is virtualized and many layers of middleware and SaaS are required to make your code do anything. All of those are moving targets and will change out from under you, without your desire or permission, while you try to continue to deliver new code and service your old code.

Finally, and this is the final nail in the coffin for some more experienced programmers, the misunderstanding of the concept of "agile" or "XP" and how it became scrum -- a series of micromanagement theatrics and paperwork pushing -- has made programming a lot more difficult and a lot less fun. One of the best parts of software development was the unpredictability and experimentation that led to innovative results and small, incremental improvements. Close contact with customers was also a hallmark of early software development. Today's top-down, "How long will it take you to write and debug a feature that doesn't exist?" management mentality cannot and does not lead to quality software, as everyone can tell. It does lead to programmer burnout, quiet quitting, and a lot of wasted time in dev shops.

> frameworks and platforms, are the biggest technical burdens for programmers today.

This sounds precisely correct from my experiences lately. At some version of scale, one simply cannot run the application on just a workstation. The complexity of distributed systems has gone way up, primarily in my opinion, because it solves an organization’s problem, not an individual programmer’s.

A little off topic, because I can't think of any ways in which programming is harder now. IMO getting into programming is easier than ever. The most popular language in the world (Javascript) is installed on nearly every computer and you can start programming with a single keystroke that opens devtools. Create a canvas and you're ready to dive into graphics programming with OpenGL. That stuff used to require a compiler, SDL, drivers, and what not. Really curious to see actual ways in which programming itself is harder now.
The c64 opened to a prompt you could easy program vs a browser which could lead you to a programming site.

qBasic was installed on windows machines and didn't require the internet.

People on mobile don't have a keyboard that makes programming fun.

You needed to program to get your computer to fully work before.

It was easier to learn before because you had to and programming was part of operating a computer.

> you can choose 20 different programming languages, dozens of framework and operating systems and you’re paralyzed by choice.

In practice, a lot of these choices are already made of us. When you join a new project, the space of choice is limited. But when choice is too be made, what I find difficult is that you need to reach a consensus with your colleagues. When you're introverted, it's taxing. There's always some person that needs extra convincing.

Code review wasn't as pervasive and can be tiring too. Sometimes you need to explain again and again why you made that decision (it was in a design document, it was discussed in a meeting, and then the question is brought again in the code review).

But the worse part for me is the accumulation of abstraction layers and dependencies. I'm working on a project with tons of internal dependencies that are loosely specified and documented, all of them introduce some unreliability. The whole edifice is fragile, and yet is expected to work 24/7. This causes a lot of stress.

I really appreciate the code review process, but one of the sorts of tyranny that can come from code review is for everything needing some kind of explanation. It's not necessarily a good thing for crap to get into a codebase, but as long as the code works well and is readable, I am less concerned if something is redundant. Either someone will realize that redundancy later or it will remain in place because it's just not that important. But code reviews today can feel like an anal probe from FBI agents.
Yeah, I call it collectivized micro management.
(comment deleted)
> But the worse part for me is the accumulation of abstraction layers and dependencies.

Yes, open source has a lot of positives, but the bad part is how it has created a culture that incentivizes such a huge amount of dependencies for every project. It seems that for any new requirement the only possible solution is to add a new dependency on yet another library. This results in fragile builds and daily changes caused by dependency updates. In some cases it causes as much troubles as the perceived benefits.

Organizing information exchange in such a way that respects agent autonomy and heterogeneity. Developers have choices; programming environment infrastructure and interfaces between the developed systems need to allow the people to do what they want and still communicate. They way I just press “share” on my phone and can instantly port whatever content to whatever other application is a marvel.
They had fewer options to choose from but they didn’t have discussion forums, stackoverflow, youtube and all the other wonderful resources to get help and learn from. And once you decide what to work on, most of those other options out there don’t affect you at all. It seems pretty great if you ask me.
It's interesting his choice is around what programming language you choose, as I kinda assume everyone I work with will be a solid programmer just as a baseline requirement. How well you can slot your code into complex systems and how to design those systems is usually what is difficult.

We have way better resources for learning but also much higher expectations. You need to be able to write good code without much thought so that you can maintain a higher level of context while programming. Sometimes you get to write just a nice little isolated bit of code, but usually there are a lot of moving pieces. (no matter how functional and immutable we try to make it.)

Google doesn't work as well now. You kind of have to know more tricks to still be able to find similar quality information.
Depending on one's definition of "years ago", the fact that google exists at all is a giant boon.
Dunno, I think if anything reliance on Google has increased. Back in the day I usually looked at the documentation. Back in the day there was documentation. Also books, like not written to be a bait-and-switch cash-grab but they were genuinely well put together by experts in the field.
The standards for software are definitely elevated.

Maybe about 20 years ago, if you had a website that allowed users to post a comment and upload a small jpeg, it was considered crazy bonkers cool.

Today, you probably need some advanced 3d UI that communicates with your phone and millions of users in real-time with geotracking and 100 other features to get a pizza to your door in under 5 minutes to barely raise an eyebrow about the technology.

There's no time to do things correctly: only "pretty well". The bar for productivity in terms of time to iterative deliverable business value is getting higher, and it's frustrating having to make quality/throughput trade offs.
I feel like the existence of sites like stackoverflow have led to less quality in available documentation. Like the responsibility has been offloaded.
Perhaps, but they also deliver thousands of helpful recipes for "using thing X with thing Y" that neither X nor Y's documenters would have anticipated the need for. We are fortunate that Stack Exchange has tried to keep this community relatively open (and not e.g. paywalled).
I’m inclined to agree. I also feel SO gives newbies the wrong impression about programming.

It’s great to have quick solutions to small problems, but too often newbs stop with the SO answer and move on, which means while they’ve solved their problem in the moment they never spend the time to actually learn the underlying reasons why the solution worked or explore the issue deeper to actually achieve understanding.

The good software engineers I know are all yak shavers. They’re willing to spend extra time learning how something really works and ensuring they fully understand an issue and its solution, even if the issue is just a small part of what they need to accomplish.

Programming today is easier in many ways: Information is readily available for free (I recall saving up a lot of money for a kid to buy specific programming books at the book store after exhausting my library’s offerings). Compilers and tooling are free. Salaries are much higher and developers are a respected career that isn’t just “IT”. Online programming communities are more abundant and welcoming than impenetrable IRC cliques of years past. We have a lot that makes programming today more comfortable and accessible than it was in the past.

However, everything feels vastly more complicated. My friends and I would put together little toy websites with PHP or Rails in a span of weeks and everyone thought they were awesome. Now I see young people spending months to get the basics up and running in their React front ends just to be able to think independently of hand-holding tutorials for the most basic operations.

Even business software felt simpler. The scope was smaller and you didn’t have to set up complicated cloud services architectures to accomplish everything.

I won’t say the old ways were better, because the modern tools do have their place. However, it’s easy to look back with rose-tinted glasses on the vastly simpler business requirements and lower expectations that allowed us to get away with really simple things.

I enjoy working with teams on complex projects using modern tools and frameworks, but I admit I do have a lot of nostalgia for the days past when a single programmer could understand and handle entire systems by themselves because the scope and requirements were just so much simpler.

> Spending months to get the basics up and running in their React frontends just to be able to think independently of hand-holding tutorials for the most basic operations.

Frontend devs who were present before the advent of the major web frameworks, and worked with the simplicity of js script + DOM (or perhaps jquery as a somewhat transparent wrapper) benefited from seeing the evolution of these frameworks, understanding the motivations behind the problem they solve, and knowing what DOM operations must be going on behind the curtain of these libraries. Approaching it today not from the 'ground up' but from high level down is imo responsible for a lot of jr web devs have surprising lack of knowledge on basic website features. Some, probably a minority, of student web devs may get conditioned to reach for libraries for every problem they encounter, until the kludge of libraries starts to cause bugs in and of itself or they reach a problem that no library is solving for them. I feel like this is particularly bad outcome for web devs because web I feel is uniquely accessible for aspiring developers. You can achieve a ton just piggybacking off the browser and DOM and it's API, the developer tools in the browser etc. But not if you are convinced or otherwise forced to only approach it from the other side -- running before you crawl, or trying to setup a webpack config before you even understand script loading, etc.

At my current company we have a take home assignment for some roles. When I have to grade one the first thing I do is check to see whether you can submit the input by pressing enter.

About half the time you can’t because it’s not actually a form, and they forgot to add handler for enter.

As someone whose been learning the last few years, a lot of learning materials suggest you don’t make a proper form element and just make your own button instead of using using a form element and all the built in benefits it brings for reasons I don’t really know. I’ve probably wondered about this sort of thing for few good hours total, but I guess this comment steers me in the right direction.
Yeah, don't do that unless you have good reason to do so.

Browsers have a standard, default, expected behavior. Sometimes, in rare cases, it makes sense to break that in order to do something else instead. But you shouldn't just silently break it for no reason other than to confuse the user.

In addition to what others have mentioned, using elements for their stated/official purpose helps with accessibility. Yes, you can use the role attribute, but some accessibility technology works more completely if you use proper elements. (And just can be easier to use; I guess the best way to compare it is using VO on a site where everything is just divs is like the blind version of this[0] Or Comic Sans. Just visceral 'ugh'.).

[0] https://www.theworldsworstwebsiteever.com/

I always found this behavior strange. Tab often doesn’t work correctly in a browser, cycling through elements that shouldn’t be focused, sometimes in a strange order. Enter submits a form. How does one cycle through “fields” then? I have also seen premature form sends when you hit enter to autocomplete etc. It also creates multiline textarea vs input inconsistency.

Desktop frameworks “committed” input on enter and most often focused the next field, so you could skip them by enter enter enter. This worked correctly since FoxPro/TurboVision/Norton times. Only Ctrl-Enter would press a “default” button out of order.

But web has its own ways as usual.

At my current company, we changed enter to stop submitting because it’s not intuitive to users. I think there are exceptions for forms with only one field.

So perhaps that isn’t the best litmus test? I wonder if it’s written down that should work as part of the assignment.

It’s intuitive to any user who has used a web form anytime for the last 2 decades.

Breaking default browser behavior because you find it unintuitive is generally a bad idea.

Now if you’re dealing with something that isn’t really a web form—as in you’re overloading input fields for some interactive non form like behavior—then I can see it.

In my case, if the person had some well thought out reason for doing it, I might let it slide. But the vast majority of times I’ve seen it, it’s because the person doesn’t even know how to use forms. Not understanding the underlying technology at at least a very basic level is a strike against you in my book.

fwiw, in my industry, I should not assume anything about technical literacy. We’ve had honest debates over whether we can even rely on people to have an email address.

Again, it’s not that I disagree with most of your premise, but in fact, as the comments (not just mine) show - people have issues with submitting too early, so it can be a good decision to break that depending on context. Fewer errors. Which is why I brought up how the problem is presented to the candidate. You might be filtering out people based on something less universally accepted and understood than you think.

Web forms have a default behavior. It doesn’t matter whether you accept it, you should understand it.

If you accidentally break it because you don’t understand it, that’s a strike against you in my book. If you consciously break it for a good reason and can coherently defend that reason, that’s a different story.

You can always find an outlier who is new to something, but you'd have to show that it's more than a majority of the users to motivate changing the default. Otherwise it's obviously more unintuitive.

At least you'd have to get a sample big enough to make a statistically significant conclusion.

And the burden of proof is on you, because you are changing the default, not the other way around.

Think of any other products, they all have established default behaviours, yet it's also very easy to find someone who's never used a product before and finds it "unintuitive".

And intuitiveness is only one part of usability anyway.

I’d suggest adding instructions to handle enter if that is your criteria.

When doing a take home exercise the candidate is desperate to figure out what you are judging on. The more you make that explicit the better your outcomes will be.

Right now your process biases for enter handler adders. Is that your intent?

Part of the difference between a junior and a senior role is that people in a senior role are expected to fill in missing details independently, without detailed directions. If you only test people on their ability to follow detailed directions, then you will only be able to test for junior roles.

When I give candidates prompts / questions / scenarios, I try to include some specific instructions, but also leave some details out. The idea is to come up with a prompt that junior developers can still work with by going head-on, but which has some open-ended nature to it, to see how people respond to things which are open-ended or even ambiguous. It's not a trick or trap; candidates are explicitly told what's up, and that I'm evaluating not only their ability to solve a problem, but to define the problem in the first place.

This is kind of silly. Actual senior developers get near-real-time feedback from the rest of the organization, and if their interpretation of a request is off, they get multiple attempts to satisfy the request. None of this is true of a coding exercise.

If you want to evaluate a candidate's ability to cut through ambiguity or manage sprawling scope, evaluate that and only that in a specific exercise. Don't just build a shoddy coding test and then rationalize it's weaknesses by saying that good candidates will succeed despite the flaws of the test. That's both disrespectful and un-rigorous.

> Actual senior developers get near-real-time feedback from the rest of the organization, and if their interpretation of a request is off, they get multiple attempts to satisfy the request.

Junior developers get near-real-time feedback from senior developers who are supervising them. Senior developers have to be able to give that feedback, have to be able to anticipate user needs, and have to be able to run long-term projects where you may have to work for days, weeks, or months before receiving critical pieces of feedback.

> If you want to evaluate a candidate's ability to cut through ambiguity or manage sprawling scope, evaluate that and only that in a specific exercise.

This is a common mistake that I see inexperienced interviewers make. Trying to throw more detailed and specific exercises at candidates is a fool's errand at best, and at worst it means that you're putting candidates through additional tests (and your acceptance rate will suffer).

The main problem with ambiguity is that it appears unexpectedly. If you give someone an ambiguous problem and say, "Tell me what is ambiguous about this problem," then you're not testing what you want to know. What you actually want to know is whether candidates can recognize ambiguous problems without being prompted to recognize them--and the reason for this is that ambiguous are extremely common in real-world scenarios.

An ambiguous problem is not a trick or a trap. It is explicitly part of the interview process, and interviewees are given guidance that the problems they are given may not be precisely defined.

> Don't just build a shoddy coding test and then rationalize it's weaknesses by saying that good candidates will succeed despite the flaws of the test.

Why do you say that the coding test is shoddy?

My observation is that a large percentage of candidates will succeed at coding tests if you give them an ambiguous prompt. In practice, they will either ask questions to resolve the ambiguity, or just pick a way to resolve the ambiguity for the purposes of the test. This matches real-world scenarios--you are going to often encounter ambiguous or incomplete problems in the real world.

If you want a precisely-specified coding problem, then go to Hacker Rank or Project Euler or something like that, or join a competitive programming team.

> This is a common mistake that I see inexperienced interviewers make. Trying to throw more detailed and specific exercises at candidates is a fool's errand at best, and at worst it means that you're putting candidates through additional tests

Have you tested this assertion with data? Because I’ve built interview pipelines several times now and the data I collected showed the exact opposite. The more specific a test was for the trait you wanted to select for the better results you’d get across all metrics, interviewers and candidates. It’s almost my defining characteristic of a good selection criteria after 2 decades of interviewing.

Unsurprisingly, I can report the same thing about the interview pipelines we're running at Fly.io. Not a week goes by where someone in our leadership team doesn't remark about how valuable the exercise we run specifically for this junior/senior scope-management/question stuff is.
How are you giving these additional, more specific tests? I would think that your acceptance rates would start dropping once you get past five rounds or so.

My personal experience is that people new to interviewing are the ones who think that making individual interviews more precise will improve the process, but my experience is that improvements to the overall interview process aren’t done by improving how good individual interviews are.

You have a budget for the number of hours you can make a candidate spend on work samples; it's the amount of time they'd spend in the interviews your tests are offsetting. This isn't complicated.
You have between 10-16 hours of time with a candidate depending on the desire ability of your job. I like to break it into: 1 hour of pitch/expectation setting where the only screening is for ability to complete the process (language, appropriate background, etc) and to catch obviously fraudulent candidates, 4 hours of take home technical assessment (programming project), 4 hours of soft skill assessment (3 hours of prep and 1 hour of presentation is my favorite format) and 1 hour of meeting with the hiring manager.

But, the format is not really the point. The point is to have a specific thing you are trying to discern from your filter and to focus your efforts on making that the only thing you are judging on.

You do know that handling enter by submitting the form is the default behavior if you do absolutely nothing? You actually have to go out of your way to override that and suppress it.

Sometimes it makes sense to do something else instead, but if so, you should handle it in a sane way and actually do that something else. Not just suppress it.

Looking back over my relatively short 30 year career across an assortment of tech companies (hp, google, microsoft, apple, etc) I would add that this mostly changed due to what was rewarded. Around 15 years ago when the first vestiges of OKR review processes and the idea of "impact" started to form; We shifted our designs from things that made our long term outlook better (simple) to things that were easy to explain to management how they had HUGE impact (complex).

Be right back, writing a new design doc for a messaging service and protocol spec to go with it that I can use to pad my next review cycle.

This is a good explanation.

Newbies drop directly to webpack/react and are overwhelmed or having a lot of trouble getting some details right.

Unfortunately a lot of details that are lost in time are accessible if you go through "build stuff basically from ground" so understanding first "why" we needed these frameworks and what were problems to solve.

There is also bunch of people who go to rediscover basic stuff and they claim "you don't need a framework - vanilla js is enough" - but they also miss context and did not run into problems that were pain points before we had frameworks.

This is true for other devs as well. I started playing around with networking code as a teenager (back when port 80 (before 443) was prominent but not the clear majority of traffic on the net.) Watching the evolution of TCP, HTTP, the C10K problem, retry storms, and event loops has made a lot of sense: clear responses to clear issues. But I've noticed a lot of junior devs grow up with the solutions (nginx, haproxy, exponential backoff, etc) but don't know the problems that necessitated the solutions. A lot of junior training is teaching juniors which solutions to apply to which problems, because unlike us they didn't watch the field evolve to where it is now.
I remember when jQuery was first released.... I wish things were that simple again
> Some, probably a minority, of student web devs may get conditioned to reach for libraries for every problem they encounter

I teach an online web development course for a university as a side gig. Our students are forbidden from using any third party code, libraries, frameworks, etc. They have to do everything with native html, css, and JS.

This is such an interesting perspective. I feel the exact same way as a video producer/editor. The tools we are getting are incredible, and tasks that used to take literally days can be done now in minutes. It’s kind of baffling what we have in our toolbox. But it is also radically changing the expectations of our clients and I find I don’t get to spend as much time on the nuts and bolts I really enjoy - cut, color, and baking the best possible export for the situation - and instead have to find a plug-in to solve every little issue a client thinks up (or created for me haha).

On a somewhat related but tangential note: I also now have clients demanding certain programs and ecosystems, which is absolutely ridiculous to me. The software I use to give you a final cut should in no way be determined by you. Yet somehow we have ceded that ground!

The list of things we've added in last 10 years is just staggering: https://landscape.cncf.io/

The litmus test for abstractions getting out of control is if a KPMG consultant brings it up while sipping Gin and tonic in business class.

Another problem is explosion of DSLs. Everything is yaml and you spend ages learning things like Terraform and Docker compose yaml syntax.

The opposite of using yaml to provision infrastructure in a few minutes was a months long acquisition process for new hardware.

As far as Terraform/HCL and CloudFormation/Yaml, the alternative is writing code to do the same thing in your language of choice using the CDK with either CloudFormation or the recently ported Terraform/CDK.

I'd say DSLs significantly improve specialised tasks. Someone who is working on declarative infrastructure configuration all day really doesn't benefit from classic imperative languages.

But if you do "a little bit of everything" and infrastructure on the side, you're bound to become a master of none.

On the other hand, having to learn 17 different DSLs (from crontab to AWS policy) isn't that far fetched from reality and it puts a lot of burden on people. Every product has a specialized DSL with unique restrictions and just never general enough. Stack Overflow is overflowing with such questions. People are thoroughly confused by "127.0.0.1:9090" vs. "127.0.0.1:9090:9090" or "9090:9090" or "0.0.0.0:9090"... docker network configs. Good lord, it is terrible, sorry, not to shed bad light on Docker; but to exemplify that this is a common thing.

One of the worst experiences in programming is writing CI/CD pipelines. One wonders why...

In most cases (including your examples) it's not really the DSL that is the problem, but the domain specific problem. Portmapping in docker isn't uniform because there are many options available that are all equally useful and up to the user to select. Crontabs have to describe time periodic values, and pretty much any other application that tries to solve a specific problem will not be all that generic (since they are not meant to solve all problems generically at once).

Like I wrote in my comment, how much specific things you need to know will depend on how many specific tasks you perform. If you specialise in nothing, everything will have depths unknown. It will also dilute attention/focus which in turn means you'll never be able to fully understand a specific domain or application. This was reflected in https://news.ycombinator.com/item?id=33056052 where the path it took for many developers and engineers in general to find a fitting solution is unknown to newcomers and also simply not taught in favour of delivering "reviewables" in hopes of a positive review (https://news.ycombinator.com/item?id=33056705) .

Sidenote: mapping ports used to be rather verbose, you'd have to include the address family, the address and the port, on both sides of the mapping. That's 6 elements (excluding separators). So most applications including docker made various parts optional. You can map two ports to any interface, or opt to specify one interface but not the other one etc. A novice user of a new application might be best served by not using any shorthand forms and only using the fully qualified names everywhere. By spelling out every option explicitly (including optional values) there is no more guessing what may or may not have been configured.

> Information is readily available for free

As much as people decry the internet and it’s role in modern society, I’m glad that I generally have easy access to massive archives of knowledge.

Get rid of the assumption of "frontend first" and most of the complication of web development disappears instantaneously.

Something I am appreciating about Svelte/Kit and Phoenix is that they are admitting what was right about PHP and server-rendered webpages. I'm a frontend engineer and think that SPAs have their place, but frontend JS represents a kind of tyranny seen nowhere else in tech.

Phoenix, do you mean the Elixir web framework? I had thought it was Elixir's counterpart to Rails.
Phoenix liveview is server rendered interactive websites.
Its really hard to find proper learning materials to get started with the backend; its all a bunch of shortcuts glued together because the tutorial really wants to show you how to make a react frontend first and foremost.
> My friends and I would put together little toy websites with PHP or Rails in a span of weeks and everyone thought they were awesome.

Agreed, LAMP was just so damn fun in how you could go from zero to a fully functioning site in a day or two. Having to manage all the statefulness of fetching & displaying data asynchronously from the client adds an incredible amount of complication both in theory and in practice.

Also agree that the old tech wasn't necessarily better either - but it sure would be cool if someone could replicate the developer experience from back then and produce a result that's up to modern engineering and UX standards.

I think things are more complicated precisely because things got easier.

The more complexity we can now handle, the more complexity we will create.

If you think we're actually handling it. Seems to me there's a whole lot of "let's just glue all these black boxes together, cross our fingers and hope they do what we want, and still do the same thing after the next update" vs. in simpler times actually writing and understanding the code.
> Even business software felt simpler.

This made me remember how acceptable a developer designed utility used to be. Now, you can barely launch an MVP without finding or paying for design and high quality UX/UI. If you do it’s likely going nowhere in terms of traction. I’m sure this has only seemed to be the new rule and there are a few exceptions. But not many.

Even Stripe all those years ago really took off after investing in design. They’ve remained rather polished. But they’re also an exceedingly well funded operation.

> Information is readily available for free (I recall saving up a lot of money for a kid to buy specific programming books at the book store after exhausting my library’s offerings).

Gave me flashbacks to when I was younger. I would work on a problem until hitting a wall I couldn't get around then go into Books A Million with pencil and paper and copy concepts/algos out of CS books. I was too poor to spend $50+ on a book at the time. Now, anything a new programmer wants to know is just a Google search away.

But, there is so much more that just diving in can be hard. Even simple things are complicated I think mainly because expectations are so much higher.

> Salaries are much higher and developers are a respected career that isn’t just “IT”.

I agree the compensation is higher. I don’t agree the respect is any higher. Software engineer is highly associated with terms like neckbeard, redditor, incel, autistic, etc.

I’m extremely hesitant to tell anyone I’m a software engineer. If anything - I’ll lie and say I do product management just to avoid the association. People treat me way better when I say I’m a PM instead of an eng.

Dependencies are more complicated.

You used to know and a few basic APIs (your OS, your stdlib…). You’d probably spend more time implementing basic utilities. However now you have to manage a complex software supply chain of dependencies of varying quality and security risk.

Only thing I can think of is we’re so much farther away from the hardware now because of layers of virtualization. 20 years ago the code more or less mapped directly onto a physical reality and you could dig in to it intuitively if something went wrong.

Now with dynamic languages, interpreters, docker, kubernetes, AWS and layers of dev tools and frameworks it can be harder to know what your code is actually doing. But those abstractions can also give you superpowers.

I've been a hardware engineer for the past few years and I do think a lot of it seems greener on the other side. I use FPGAs and microcontrollers for a whole host of things, along with traditional electronic elements.

The tools more often than not want me to pull my hair out (coded mostly in Tcl...), the technical forums and support are often non-existent, and the technologies quite often haven't been update with QoL changes in 20+ years.

Setting up developer environments has become vastly more complicated than it was in the past. With language-specific package managers, ad-hoc installation processes (along with surreptitious editing of shell config files under the user's nose), variety of operating systems, library versions and instruction sets, trying to get reproducible builds and environments seems close to impossible without some unified tools such as Nix or well-written Dockerfiles. This is even before issues such as resolving dependency conflicts and trying to work with out-of-tree changes to dependencies and patched dependencies.
Security is harder.

Devices have become more complex and interconnected. Expectations for software are also higher, while there’s more resources poured into finding and exploiting vulnerabilities.

Keeping on top of all of that, isolating your memory access and permissions, etc… is a lot harder today than it was even a few years ago.

In every other way I think programming is easier now. Languages are more ergonomic, even the ones that are decades old. Libraries are more easily available and there are tons more resources today than ever before for learning.

The amount of software that needs to be maintained is far greater, therefore there aren't as many "quick wins" to be found anymore. Not to say that new software isn't being written all the time, but more and more of what makes up the typical software developer's job is to constantly fix bugs and sacrifice standards to get things done with to Eldritch horrors of codebases. We cope by installing tools like Eslint and telling ourselves it means we have "standards."
Years ago? Not very different. The 90s and before? A few ways.

1. Concurrency. Multiple cores are a completely normal thing now, so having to think about how different threads may interact went from a theoretical concern to a very practical one.

2. Dependencies. Back then you could just turn on the computer and start coding. Today many things have large amounts of dependencies that need installing, compiling or setting up. Weird problems can happen. I have an issue where VS Code just refuses to autocomplete in the test section of my project. Why? I have no clue, and VS Code is a giant of a thing. It's quite easy to spend days or even weeks trying to set things up and work out issues with things that aren't even the thing you were trying to write.

3. Teamwork. Modern computers allow for large programs, which require teams to develop. A lot of the work in building modern successful software is in organization, record keeping, documentation and working with other people.

4. Security. Pretty much everything interacts with outside untrusted inputs, and so it's far more important than before to treat every input correctly. Anything from image loaders to parsers to APIs may be exploited.

> Why? I have no clue, and VS Code is a giant of a thing

That experience is why I relentlessly bang on the drum of "do not swallow errors" because it makes troubleshooting indescribably hard

I would guess the more links in the call/dependency chain, the more opportunities for misplaced assumptions or laziness to sneak in, leading to your cited outcome

UIs are way harder. Back in the day, you could drag and drop form controls in VB and bind the data to a database without writing a single line of code. Today, every step of that requires boilerplate. Backend, fronted, rest api, and so on.

Distributing native apps has gotten harder in some ways with code signing required in order to share binaries without scary pop ups or the OS blocking outright.

Oh yes this. I wrote a timesheet system in VB4 32-bit back in the day in 4 days and rolled it out to 10,000 users. And it worked. And it stayed working for 15 years until it was replaced.

In 4 days worth of work now, I couldn't even do an evaluation of which UI tech is still going to be around in 2 years...

If you haven't been watching the low-code/no-code space you may be in for a rude awakening.

These tools continue to get better every day. The target is only "good enough" and once reached it presents an outsized advantage over custom builds.

I fully expect no-code/low-code to grow in nearly permanent ways within many organizations.

Any examples that are interesting?
For example Oracle APEX comes with their DB and has a lot of capabilities.

https://apex.oracle.com/en/

The demo video takes you through creating a full blown database backed app with maps and other geo features, from nothing more than an initial CSV file. The code backing the app is represented as database tables, so you can use queries to explore the app.

The core issue is really the same one the no-code/low-code platforms have always had, or even that VB6 had - the ramp isn't smooth. Eventually you hit the limits of the tool or there's a business requirement the tool can't meet and you get stuck. Often that requirement may be something indirect and non-obvious, like growing the team to the point where you start needing 'real' abstractions, or keeping up with some new feature the underlying platforms added that competitors are exploiting but which aren't exposed. Hence why so many companies have mobile apps that are just ordinary Android/iOS apps instead of written using low-code tools.

I've been through that "no code" cycle at least three times, ironically including Oracle in two of those cycles, and they always died on their ass. I suspect the same will happen again.

It's really hard to build something generic enough. MS Access was as near to it as was feasible I suspect.

Oracle Apex has been around for over 20 years and is still in use by many people who have Oracle Db or product installations so if it is dying, it isn't dying quickly. It's actually really good for a lot of use cases.
I worked with apex and I must say, the premise and structure are nice and you learn the basic architecture of web apps as a beginner.

BUT the performance is _very bad_ if you don't throw money at oracle. The final nail in the coffin was when customers want you to build something that the blackbox doesn't offer. You are in for a wild wild ride, because whatever happens in the backend is undocumented, you cannot debug it properly.

Code signing requires you to buy certificates, but that's the sort of thing you can delegate to a non-technical assistant as it mostly involves filling out forms, getting access to the corporate credit card and/or receiving phone calls. In very large organizations you probably have code signing certs already and will need to find who has access to them, although there's no theoretical reason why you can't have different departments independently buy certificates for the same organization.

The bigger pain, and one reason why desktop apps became less popular, is that with the rise of macOS and (to some extent) Linux, you need to distribute your app to three platforms all of which use different code signing technologies and approaches, none of which are portable/standards based or convenient. Also, software update was ignored by platform vendors.

Nowadays things are a bit different. Windows got MSIX, which is a real package manager and which can silently upgrade apps in the background on a schedule even if they're currently running. macOS has the widely used Sparkle framework for updates and of course Linux has had updating package managers for a long time.

Up until recently it was still a pain to actually use all those technologies, even though maybe developing your {JVM,Electron,Flutter,native,etc} app was itself quite pleasant and easy. My company has made a tool to fix that [1] and so you can now build self-updating Windows/Mac/Linux packages from your app files and all the signing is handled for you locally. It's an abstraction over the platform-native distribution technologies designed with an obsessive focus on being as simple as web app distribution is.

Making this stuff easy in turn opens up possibilities for (re)simplifying the dev stack. For example, in some cases you could now make an app that just logs in directly to your RDBMS. No need for a backend/frontend, REST, JSON, web server frameworks, giant JS transpiler pipeline etc. Just use a real GUI toolkit and connect it directly to the output of queries. Any privacy or business logic can be implemented this way using a mix of row-level security [2], security-definer stored procedures [3] and RDBMS server plugins (e.g. [4] or [5]). There are lots of nice things about this, for example, it eliminates a lot of nasty security bugs that are otherwise hard to get rid of (XSS, XSRF, SQLi etc).

[1] https://www.hydraulic.software

[2] https://www.postgresql.org/docs/current/ddl-rowsecurity.html

[3] https://www.postgresql.org/docs/current/sql-createprocedure....

[4] https://tada.github.io/pljava/

[5] https://pgxn.org/dist/plv8/doc/plv8.html

Programming is enormously more complicated today because modern development environments aren't designed for simplicity.

When I first started programming all of my tools had a simple workflow:

* Write a single text file

* run a single command to build (cc thing.c)

* Run the resulting file as a standalone command

People learning to program are often new in general. They're figuring out their text editors. Figuring out how to run programs. Figuring out so many basic things seasoned developers take for granted.

I became quite fluent in C, writing many, many useful programs with just a single text file. By the time I had a need to learn about linking multiple files in large projects I was already fluent and comfortable with the language basics.

Contrast this with modern environments: I need to learn whole sets of tools for managing development environments (venv, bundle, cargo, etc etc etc). These development harnesses all change rapidly and I am constantly googling various sets of commands and starter configs to get things running. These are all things that a seasoned developer will be constantly dealing with on a complex project, but it seems like little effort has been put into creating basic defaults to simplify things for beginners.

I agree 100%. Massive frameworks with massive complexity. I don't enjoy them at all. That's one reason I like Go. It's very modern, but I can still use vim and a simple Makefile to control it.
I started programming professionally in the late 1980's (almost a half century ago :-)... and we had IDE's, UI builders, databases, "resource managers", etc. One the UI side, we had to deal with windows, layouts, menus, event loops, controllers, graphs, etc, etc, etc. Pretty much everything you have to deal with today. It was, IMO, just as complicated (if in a somewhat different way).

Yes, most commercial software packages were written in C. They certainly weren't in one file. They were large systems that took hundreds, sometimes thousands of files and 100k's to millions of lines of code. If anything, we had to write more code to do things because pre-packaged libraries weren't as comprehensive back then. I still remember waiting hours and hours for our application to build. And the old timers told us that that was blazingly fast, lol.

I would agree with a previous poster that there are many more choices today. And I guess if you suffer from a fear of making the wrong choice, that is a problem. But the other side of that is that literally thousands and thousands of examples and even robust code libraries are now available for free that you can drop in and use. That is a HUGE plus.

Yes we had those things but my point is that they were optional and not commonly used except in large system projects. We didn't throw all that complexity at people learning the basics.

The interface for beginners scaled all the way down to a very basic single text file, and most beginners would program for months or even years without using those things. It wasn't necessary to teach these tools in school - you could complete an entire degree writing single-file C programs without ever using an IDE.

Many utilities were distributed as a .c file and a Makefile and that's it (before the rise of autoconf)

I agree with most of what you’re saying, but for me, the IDE was waaaaay easier than dealing with a Makefile (yet another programming language that has nothing to do with my goal), or worse, entering random hard-to-remember commands and options on the command line. Even if my program was a single file, it was usually just Cmd-R to build and run. No need to memorize that I needed to add “-l math” if I was doing anything with math functions, or whatever.
Makefiles for basic projects are typically just two to five lines long. It's really different than a large project system, or the absolutely crazy things that autoconf generates.

all: cc myprogram.c

clean: rm -f myprogram.o myprogram

They're extremely simple in simple scenarios. It's just a simple format for writing down the commands you run while working.

I agree with all of this, and then some. My recent lament was how one tool in my tool chain for a project managed by someone else in my company which, despite being in the same language, required a specific variable to be set in my environment.

Back in my day, being on the path was sufficient. And it is for all the other Java projects. I spent too long sorting that one out.

I mean, invoking rustc on a single rust file is no harder than invoking gcc on a single file. cargo adds other features, as do make, cmake, etc for c.
I still work like that 30 years after, thanks to Go... I would not like beginning today !
If you have a base familiarity with the command line, I think many build tools do have great basic defaults, e.g. `dotnet run`, `cargo run`, `npm run dev`, etc. Vite is another example of good defaults in frontend dev; it allows you to sidestep a lot of the difficulty one may run into with webpack.

But I think you're right in many ways though. For seasoned devs, cli tools give a lot of flexibility and allow dev tasks to be automated in pipelines more easily, but it requires one to read documentation or use the help subcommand to discover what else you can do. Which is not a big deal when you are experienced, but I definitely remember struggling early on with things like that when I was self-teaching how to program.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”
Expectations. If you look back at software 20 years ago, even the most popular websites had relatively low complexity, both in terms of UI and functionality. A single person could have built most of them and value came primarily from content. Even early versions of Google were not that complex to build. Now the entry barrier for a minimum valuable product has dramatically increased to the point where it takes a big team and years to develop a program/website that passes the expectations of a user for their primary website/program.
The weight of user expectations, and the tools created to meet them. In between this, the big tech companies have leveraged this situation to put large segments of software developers on a treadmill, by using open source projects and excellent marketing, to impose a 'soft' form of standardisation on common practices (best demonstrated by React / Typescript).

My tongue is in my cheek, but I often wonder.

When I started out, there was DOS. It came with a command you could type in: QBASIC.

Typing this one magic word brought up an IDE, including an editor with highlighting, an interactive help system, samples, an in-editor REPL, and single-key shortcut to run the program. I can't remember if it also came with a debugger and a way to create stand-alone executable, or if that came later.

It had built in commands for drawing, input and sound, all well documented. And the UI was straightforward and intuitive.

This doesn't really exist anymore.

> I can't remember if it also came with a debugger and a way to create stand-alone executable, or if that came later.

It didn’t, it came earlier: QBasic was (and is, it stopped being part of the default install with Win2k but is still available for current Windows OSs) a stripped down interpreter-only version of QuickBASIC, a compiled BASIC.

It seems like this could be a special website or something packaged with a browser like Firefox.

A plug-in or add on for the tutorial on how to make HTML/JS pages right there inside the browser.

Go back 25 years to 1997 and you'll find it. Netscape Composer was built right into the browser.

That's not quite like QBASIC was though. Making webpages is just a dim shadow of what QBASIC and controlling your computer was.

Windows comes with a command you can type in: powershell_ise

Typing this command brings up an IDE, including an editor with highlighting, an interactive help system, samples, an in-editor REPL, and single-key shortcut to run the program, tabs, step-through debugger, breakpoints, intellisense, snippets, extension system.

It has access to the .NET framework that C# uses such as System.Windows.Forms, System.Drawing, System.Console.Beep, System.Media.SoundPlayer, and the UI is straighforward with an editor and a console pane. Library is well enough documented if you can use MSDN website, but certainly not as simple as BASIC and SCREEN 12, LINE (10,10)-(20,20).

This does really exist, but it's deprecated despite being powerful, simple, convenient and useful. Instead the recommended path is to download and install a new PowerShell, VS Code and some VS Code extensions, to get a less integrated, more complex, not-bundled setup.

Complexity of the platforms and packages.