Ask HN: What's your unpopular tech, programming opinion

20 points by kbrannigan ↗ HN
I always like these type of questions because we get so much: impractical advice from dev due to changing times,

hyperbolic exaggeration or plain ignorance

What popular tech advice you wish you didn't follow?

60 comments

[ 3.4 ms ] story [ 108 ms ] thread
While it's valid to say that for most software jobs you won't be having to write tree search algorithms 10 times a day, you'll still need to use the intuition and body of knowledge that solving such problems requires more often than you think, even if it doesn't present itself as a whiteboard trivia problem.
I think it's a gate keeping strategy. Make the bar so high that only a few can get in.

They might filter out some exceptional candidate and let in some regurgitator.

But I agree of you can grasp those fundamental concepts you're a great programmer.

Some of these concept became clearer, years after college

>I think it's a gate keeping strategy.

I agree, but I think the widely accepted thought of "it's gatekeeping and shouldn't be interview-whiteboard trivia for most roles" sometimes gets extended to an attitude of "you'll never need this stuff"

>They might filter out some exceptional candidate and let in some regurgitator.

hah, we think alike, had the same scenario when I detailed this answer:

https://news.ycombinator.com/item?id=17059852

Docker doesn't actually save time.

The thinking is that with docker you can manage your dependencies in one place, and so you don't need to spend time and headache dealing with issues like incompatible packages.

In reality, you trade that time and headache for the time and headache of dealing with docker: did you mount all the files you needed? Did you start the container with the proper command to enable debugging? How do I attach the debugger to my process inside the docker container? And personally I don't like the extra "state" I have to maintain in my head that I'm in a docker container.

My overall argument is that if the dependencies are so crazy that you're wasting time on conflicting packages, take a hard look at those dependencies and see if you really need all of them, or if you can simplify.

To be absolutely clear, docker is still great for certain use cases. For spinning up new CI machines it's fantastic and really simplifies that process in a meaningful way. But for local dev I think the advantages/disadvantages wash out and makes it either a net zero at best or negative at worst, since that "state" will always be there.

My understanding is that the lower layer will outlive docker.

Some new dev with no understanding of how bare metal OS operates will be stuck within the limits of docker.

Like a goat who spent all it's life inside a fenced yard.

> the lower layer will outlive docker.

That's a good way to put it, I like it.

less "people engineering" and more "technical engineering"
What do you mean by people engineering?
People trying to add tons of process and “standards” that involve more promotion driven development and playing politics than.. providing value to customers.

Like no offense to other engineers but if people who call themselves engineers can’t understand new systems within a week of joining a team they should probably find other work.

I’ve worked on dozens of teams and projects and with the exception of a few where everyone was S tier (the best team experience let’s be real) the rest were mediocre people who somehow were able to spend more time coming up awful implementations (that waste everyone’s time) to get a promotion rather than actually doing their job. Over time nobody maintains these things or people naturally stop using these approaches because they suck, and the problem starts again because some new joker joins and shoots their shot.

It’s hard to describe unless you’ve been on the receiving end of it, but it’s pretty common at larger companies.

A lot of the complexity you see in code, tool or project are

Job-Security sub projects. At first you have a bright eyes junior dev who wants to do the right thing, change the world they said.

Little by little he realizes that documenting everything, writing easy to follow and bug free code is a great way to be out of a job.

Complex code is what gets you promoted because you have fire to put out, bugs to fix, getting pulled in meetings where you have to explain the intricate architecture.

I imagine there are people who face a decision like this at some point in their career, and maybe it seems like the right one at the time, but it feels like optimizing for a local maximum as opposed to a global one.

This may work to keep your current job, but should you need to find another job for any reason, how will you sell yourself to the next company, other than trying to bullshit your way in?

Well, we mostly interview by grilling people about obscure parts of computer science. One of the obvious ways to obfuscate your current code base is to rewrite it with obscure parts of computer science. So with a little ahead of time planning you should be able to practice leetcode and the like on your production codebase.
What is the alternative to bullshitting your way in ?

“I worked on this project, I did the right things, wrote all the documentation, there were no bugs, etc” Everyone will say that, how is an interviewer going to tell who’s honest and who isn’t ?

The things that make the difference between an ok and great engineer are things that never get published along with the product.

My unpopular opinion is that computing is stuck in a local maximum based on technology from the 1970s.

In particular, typing into an 80x25 terminal window with unformatted fixed-width characters should be obsolete; we don't need compatibility with punch cards any more. There was a thread a week ago about displaying graphs in your terminal using ASCII graphics. This shouldn't be necessary!

Also, code shouldn't be a sequence of 80-character lines like a deck of punch cards. It makes no sense to carefully organize the order of code in a file for things that don't matter. Chunks should float around and be displayed as sensible, not tied to an arbitrary location in a file. Code should be more like a database than a flat file. (Yes, I know the arguments that flat files are better for tools like grep.) We should get out of the 1970s editor model; Emacs is from 1976 and vi from 1978.

The whole command-line operating system approach is like being stuck in the 1970s, even using the same commands. Yes, small tools composable with pipes are nice, but there must be a better approach. We have powerful graphics, but we're typing into terminal windows that simulate a Teletype.

To summarize my unpopular rant, hardware and I/O is exponentially better than the 1970s, but our programming environment is still stuck with the approaches of the 1970s. Computing needs to get out of this local maximum. For a supposedly fast-moving field, computing changes at a glacial pace.

So instead of editing and compiling text files what should we be doing instead?
I don't have the solution; I just see the problem :-) Programs could be in some sort of database rather than a set of files, so the code you're interested in gets displayed without you caring about how it is broken down into a sequence of lines in a file. Sort of like how a database shows you the data you want, rather than needing to put entries in the right order. You shouldn't need to think about how your methods are ordered in the file or even what file they go into.

The display could be more like a smart word processor, where you can format code however you want. (A feature that the Xerox Alto provided.) You should be able to stick images in your code to describe things, rather than creating ASCII graphics. Tabs vs spaces shouldn't even exist.

Oddly that was how BASIC worked in the actual 70s. line numbers were virtual. Though I think the implementation left much to be desired.
Smalltalk basically did that. The code can be serialized to text (and usually is) but in the system it's just in a database. What file represents what source code, doesn't matter to the user. The system can create directories and files as needed to represent it in whatever the sane way to represent it is. You're just editing the code and not dealing with the mundane and tedious serialization bits. You don't have to get into nonsensical wars about what goes in what file or what directory, you just care about packages, classes, and methods.
The database analogy breaks down pretty quickly though. Instead of deciding what file to put something in, you have to decide which table. And you're not going to have a single database for all your code, so you'll have to decide which database to put the code in, and which table within that database.

And now we're created libraries and packages.

Not to mention that sometimes a database gets too big and performance goes down, so maybe we want to split it up or shard it or something. And I haven't even mentioned all the database types out there, relational, document, graph, time-series...

I'd want to be working in a system where an AST is the first class representation, exchange format, etc. That everything could be dumped to text format should be a private choice and unknown to the beginner developer, much like debugging with AST or assembly is today.
Win32 was a great step forward. A stable interface that has lasted for decades, despite Microsoft's best efforts to move on.

Programs written using the Win32 GUI and forms still work decades later. Its a shame there isn't an equivalent in the Linux world.

---

We should have rich source text by now. You should be able to freely time comments, include notes, links, images, etc. in the source code of a program, and still have it compile correctly.

---

We should be able to directly modify the Abstract Syntax Tree of programs, renaming as it is stored in the tree would cause it to correctly change the name of every use with zero errors. Refactoring this way would be much faster and more reliable.

Arent Jupyter notebooks the rich source text, are you looking for something similar to be natively supported by the compiler instead of the overhead of a Jupyter process.
Your "unpopular rant" (or one pretty much like it) has 376k views and 12k likes on youtube![1] (Recommended watch, not least for demystifying the origin of vi's navigation keys and the choice of ~/ for /home/you.)

1: https://www.youtube.com/watch?v=8Ab3ArE8W3s&t=1012s (link jumps to 16:52)

Wow, that video is exactly my thoughts, but expressed much better!
Text files are a meh proxy for ASTs, which is what we actually write when writing programs. I want a programming language in which I can edit ASTs.
80 character lines are a near-optimum for readability. And command line interfaces are convenient to use via keyboard over remote, possibly high-latency connections, where a more direct interaction becomes clunky. It's also easy to extend: you don't have to change anything in the UX, just add a new command. Moreover a CLI allows for the expression of complex behaviors that are all but impossible to render in a "user-friendly", interaction-based UX.
> 80 character lines are a near-optimum for readability.

Counterpoint: 80 chars is too short for writability. You need to make arbitrary splits and refactors all the time and it ends up hurting readability.

120 is a better sweet spot to strive for in my opinion.

There have been incremental improvements lately that might lead to code in a db instead of flat files at some point in the near future:

- rise of autoformatters

- language servers decoupling editing from editors

- all in one build tools (cargo, go)

This might be case of happens slowly then all at once.

It's not an insane jump from LSPs to new editor UIs and since the code is formatted on save, people care less about the minutiae of 80 char lines.

(comment deleted)
- I like data structures and algorithms interviews.

- Writing Rust is generally unpleasant - trying to figure out how to do something that you don’t yet know how to do is much more painful than doing the same in another language.

- Unit tests are overrated.

ASICs are cheaper and better than most people believe. Companies are unnecessarily scared of them due to costs associated with the newest processes.

Embedded linux is more trouble than its worth 6.5/10 times

A lot of PCB developrs pretty much refuse to perform proper V&V on their designs because they're allowed to push it off on firmware engineers.

The fact that (evidently) you can't have some kind of seamless end-to-end connection between a relational database and "front-end user interface" data display/entry fields, with some kind of uniform/standardized DSL in-between to manipulate & validate, strikes me as totally FUBAR.
Every time that I tried to implement something like this (logic/validation in DB via constraints/fks, postgraphile/postgrest in the backend, react admin/react-json-schema-forms in the frontend) all I got was new enemies.

People adore constructing <inputs> and writing @get("/users") and users.objects.findById(req.params.id).

I'm tempted to say that many people out there are not programmers, but boilerplate code janitors.

Minority Opinion: Computer security is a solved issue, and most people don't know about the solutions.

We need operating systems that enforce file selection, instead of deferring to the applications. This is known as capability based security, and most people think of "allow access to X" on their phone, which is NOT what I mean.

When you want to open a file, an application shows a system supplied dialog box, then goes ahead and opens whatever the heck it wants with the full trust of the OS, no matter how wrong that is.

All I'm asking for is the OS to handle the file dialog and pass a capability (like a file handle) to the app instead of trusting it blindly.

The downside is that unless there are clever shims, this requires rewriting everything.

---

The reason we have VMs then Docker then Containers is that our Operating Systems don't enforce capability based security, and we've been improvising a replacement for it in this manner.

Flatpak does something that looks like this with various xdg-open portals but the permission is implicit (hitting open is the user confirmation itself) which I don't get why it was implemented that way.
The madness that is overlay networking and other brainfuck networking stacks that are normalized now due to Kubernetes and Docker are horrific. Moving to micro-VMs with each one having it's own unique IP and leveraging basic networking has paid us off in spades.
Minority Opinion: Programming productivity peaked at VB6/Delphi/Microsoft Office 2000.

These tools allowed domain experts to get a GUI tool built in a matter of hours, and for the most part, those solutions just worked.

Microsoft Access 2000 managed tables and relationships automatically. You could have master/detail relationships multiple levels deep and it all just worked. It did queries well enough, hooked to SQL via ODBC, and did pretty good reports.

It was a pretty cool environment when you tied it all together.

- Then Microsoft got obsessed with .NET and Borland got greedy, and ruined it

On the Web side of things, there were WYSIWYG Web editors that worked in much the same fashion, with a whole stack to support it. You could lay out a Form, and have a CRUD app running on the web in short order.

- Then Ruby on Rails came along, and ruined it

The main thing we've gotten in the past decade is faster hardware, especially thanks to SSDs, and GIT. GIT is amazing, but don't be fooled into thinking it actually stores deltas, it just acts like it does. GIT is a snapshot tool, way better than stacks of floppy disks/USB sticks labeled Archive001 -- Date

Nobody seems to know what a data diode is, or when one should be used. Quite a few places where you want to monitor a system without being able to control it would benefit from the use of a data diode.
Don’t rewrite it.

Every time I hear someone wanting to rewrite something without a VERY solid reason is a flag for me. It is hard improving a system that’s already there, but can be super rewarding if you change your mindset.

Everyone is eager to go with a blank canvas and greenfield a project but ultimately we’ll end up with the same shit situation in 5-6 years after the original authors have bounced and the newer devs are side-eyeing the code.

During the last 15 years or so, I only rewrote large parts of the code from scratch three times, but it was absolutely worth it. Two of these refactorizations are now 12 and 7 years old, respectively, and they have proven themselves very well. They barely need any maintenance, on a level of "a one-liner change every two years or so".
Unpopular opinion: there hasn't been advancements in web app development for the last ~15-20 years. People are creating new tools/frameworks because they can, not because there is an actual need for yet another new shiny thing to build HTML+JS+CSS pages that do CRUD on database rows via HTTP verbs. To put it another way, some people thrive on solving problems that already have solutions with nuanced solutions because its their solution.
CRUD on database rows via HTTP verbs is solved. See Postgrest/postgraphile. Most backend programmers are obsessed with constructing lousy versions of those two programs.

With this said, I know I just made a few extra enemies.

Some backend programmers have been solving this problem since before postgraphile existed and before graphql became a solution. This is an example of what I mean, no offense, there are hundreds of example frameworks/libraries with ways to solve this.

I will counter my own unpopular opinion in that many of the newer ways are better or easier to use (if I used postgres this looks interesting) but as an industry we certainly don't need the countless variations that are out there.

Spicy take: Despite the amount of attention paid to code quality, it generally does not matter beyond some (extremely low) baseline. By contrast, data quality (consistency and sensibility of the data model, proper migration of old data to new schemas, alerting around anomalous data) is neglected but vitally important. Adding abstraction will usually improve your code quality metrics, but make it harder to tell where data is coming from, how it is being transformed, and where it is going. Copy/paste/modify will do terrible things to your code quality metrics, but frequently does not make your data flow harder to understand.

As such, abstraction for the purpose of avoiding copy/paste/modify is usually bad. You should just copy/paste/modify, and maybe extract out common functionality if the common functionality is obvious and well-contained.

Epistemic status: I don't fully endorse literally the above take, but it gestures in the direction of my actual opinions if you're starting from the viewpoint "Martin Fowler's Clean Code is approximately correct", which seems to be the majority viewpoint in my circles. As always, take into account the rule that you should probably reverse any advice you hear[1] -- if this take resonates with you, it is unusually likely to be bad advice for you in particular.

[1] https://slatestarcodex.com/2014/03/24/should-you-reverse-any...

GitOps (as in ArgoCD style workflows) is not nice. Deploying from code, and storing all infra, etc as code is great, but this pull based approach creates IMHO a really decoupled and inconvenient deployment pipeline.
We hit a local maximum in language design with Common Lisp in the 80's. I mean putting in the hard work to make a language be as powerful as you can imagine.

Today the market moves too fast, priorities have changed, and there seems to less of a willingness to "do the right thing".

>> Priorities have changed

My assumption is that, nobody knew there would be that much cash involved in this industry.

It's about making the most money the fastest way possible.

Compare the 10-year effort for the ANSI standardization of Common Lisp with the two-week, ill-considered marketing-directed creation of JavaScript, now one of the world's most popular languages, and the resultant decades of technical debt.
* It (usually) doesn't have to be perfect the first time. Programming is an interative process and your first attempt is going to have bugs, or make faulty assumptions about the problem.

* A design which can be generalised is inherently more complicated, and is often unnecessary (you probably won't make use of that generality, leaving you the burden of maintaining it), so you'll be glad you made a simpler first pass.

* I don't like working with docker/containers personally. It makes me feel so far removed from how services are deployed that it's basically magic.

Most DevOps technologies and teams are unnecessary. Things like app.logz.io, Prometheus, and Grafana provide no value. In fact I wish I could lay off the majority of our infra team @ every company i've worked, but I don't have that authority.
Software design is subjective. After years of professional work, I cannot stand anymore getting entangled in architecture/design discussions. Any competent software engineer (most of us are) can come with a reasonable working solution to common problems 99% tech companies face. So, it doesn’t matter if you use Date or DateTime, REST or gRPC, Postgres or MySQL, Go or Rust… In a commercial context, good software is software that brings money. Period.

In a more personal context, I do care about software quality… but this only applies to personal projects.

My assumption is that people need to pad their resume with the trendy stuff. The tech that will ensure future employability.

Can't risk working with old-timey tech. Gotta keep up with the fashion and the trends, because the industry encourages RDD

Resume Driven Development

Cloud IDEs are the future. Nobody will run code on their laptop/workstations in 10 years in a professional context.

There's no difference to a business between first-gen infra as code (terraform/cloudformation) and second-gen (CDK/pulumi/etc ...). They both should be replaced by a developer platform that runs in your own cloud

The best tool to build on is something that combines the two with one simple config, like what we're building at withcoherence.com!

I'm a professional Haskell programmer and have been writing in the language for almost 20 years. It's amazing and I love it.

Nix is the single worst thing that's happened to Haskell development tooling. The last 9 months at my current job have been Nix misery non-stop.

Nix in general is hot garbage.

I'd agree. Nix feels to me like the Lisp of build systems. Something that's going to be extremely influential but ultimately too flawed for me to want to use in practice. I'm still waiting for the Haskell of build systems.