Hacker News new | ask | show | jobs
by freyir 1656 days ago
New developers write simple but shortsighted code. It gets the job done, but it will be painful to work with in the future.

Intermediate developers, bitten by their past mistakes, decide to future proof their work. But they don’t just look one or two steps ahead, rather they try to look five steps ahead and identity problems that do not and may never exist. Consequently, they over-engineer, over-abstract, and over-complicate everything. Carmack’s recent “But here we are” speech resonated with me.

Advanced developers identify the right balance for each task between simple and complex, concrete and abstract, and pragmatic and idealistic. In my experience, they favor simple and pragmatic solutions, use abstraction effectively, and can satisfy near-term goals quickly without painting themselves into a corner. “As simple as possible, but not simpler.”

I try to avoid working for tech leads stuck in the second phase, which is not uncommon. If you suggest taking the “ifs and for loops” approach of solving a simple problem with a simple solution, they’ll assume you’re on the wrong side of the bell curve.

8 comments

Had a boss once who insisted that all if statements should be pushed out to factory classes, and all control logic should be done by constructing a different instance of an interface. It was a pretty rigid system, but at least it did force me to write small focused classes that were easy to test.

Debated for a long time whether that methodology was stuck in the second phase or if it was actually the third. Still don't have an answer, but these days I think having a plan is better than just letting engineers run roughshod, as long as the conventions are easy to follow.

That just sounds like enterprisey Java to me, which I firmly believe is closer to 2 than 3.
Programming alone vs programming in a team are very, very different occupations. A lot of what applies to one doesn’t apply to the other. I’m still painfully learning this, after all these years.
Could you elaborate please?
I think it comes down to there being two kinds of codebases...

In the first kind, all relevant developers have deep expertise in the system, or build towards having deep expertise. There's an expectation that flexible abstractions will be used, not abused, unless it's one of those scenarios where the use outweighs the abuse. The abstractions are tomato cages, and they're there to support the system as it grows, provide some structure, but not to strangle it.

In the second kind, the default expectation is that a developer will have little to no familiarity with the system, they will be isolated from it as much as possible, and they will be given such a tightly constrained sandbox that they can't break anything outside it. You will write your little plugin, or whatever, get in and out, and you're done.

These can both be useful kinds of systems/codebases in orgs of any size. The first kind of codebase can enable an experienced team to move really fast and be extremely productive. The second kind of system can help lots of different teams of different skill levels jump in and leverage your system with little required knowledge, and thus be productive that way. So there's really no way to say one of these patterns is good or bad.

But in general if you churn in and out a bunch of replaceable cog code monkeys, probably low-paid, the second kind of system just ends up working better. Giant "enterprise" software shops like parent poster aluded to typically end up in this kind of high turnover scenario after enough finance/MBA people have been brought in, hence their bad rap.

I have much more experience working alone, but: git alone is a breeze. I don’t need to impose myself some arbitrary constrain because I know (or think I do) I won’t abuse it. I can use the stack I consider best/am more productive on, instead of what’s fashionable this year. No linting, coding conventions, etc. Just the pure joy of problem solving.

On the other hand, on the right conditions, the amount you learn on a good team is ridiculous compared to what you’d do alone. Weeks vs years kind of thing.

The key insight to "at least destroying your architecture makes it easy to unit test" is that being able to unit test is not actually that important. There's other kinds of testing out there!
Q: What's the difference between a novice and an expert?

A: The novice thinks twice before doing something stupid.

I don't understand this saying.
Often doing the stupid thing is the right thing to do, instead of thinking hard to do the smart thing that ultimately wont be needed and will be harder to understand.

So juniors thinks twice before doing stupid simple stuff. Intermediates thinks twice and does smart stuff. Seniors only does smart stuff where it is needed and does the stupid simple stuff without thinking in most places.

well actually I am not familiar with the phrase before, so maybe KineticLensman knows the proper meaning.

That said for that specific meaning I would prefer something like - The novice fears simplicity.

Maybe throw in a - The expert loves it - at the end.

when the expert thinks twice they don't do something stupid?
That's not how I interpreted it at all.
"It's common to become very good at doing it badly"
There is another important difference: the expert thinks twice before doing anything at all.
And that's also why a lot of Architecture Astronaut that looooved Java, didn't see Python coming.
Funny, I took over a modern python service and I was pretty shocked at what I inherited. Long gone are the days of "There's one way to do things".

Instead, this thing would give the most "enterprisey" Spring JEE application a run for its money with its endless annotations, dependency injection magic, all sorts of pseudo-types - both the "built-in" Python 3 ones like Set and List, but also the libraries like Pydantic. But unlike Java, these types aren't even really guaranteed by the language at compile time, so even if your IDE plugin can successfully detect them, things will still (silently) slip through at runtime.

The async functionality that's been bolted on to the language is worse than even the old and confusing Java multi-threading primitives, and the funny thing is it still doesn't actually run things in multiple threads. For that, your simple Rest API is running on layers of C programs like Uvicorn which itself is then wrapped by another few processes running Gunicorn which in turn is probably running behind NGINX. LOL, and we thought the Servlet stuff with Tomcat and JBoss was clunky - this is insane.

To be honest, if there ever was a sweet spot for Python, it would have been for smaller code bases that weren't complex enough for big "enterprisey" langs like .Net or Java, but were more permanent and complex than shell scripts or (back in the day) Perl could handle.

But nowadays, I don't think modern Python fits any use case real well. It's still dynamically typed, slow, single-threaded, and has a poorly managed ecosystem and hodge-podge of tools like virtualenv, pyenv, poetry, etc. that never quite become standardized and stable.

So unless you've got a bunch of Python experts who aren't interested in moving to a better lang, I'd find it hard to go with Python for new projects.

> ...endless annotations, dependency injection magic, all sorts of pseudo-types

This sounds like what happens when a bunch of Java/C# developers jump over to python without learning the "python way" - this is more related to the developers than the project

> But nowadays, I don't think modern Python fits any use case real well

Python has effectively taken over the data science / machine learning space. For most use cases, the algorithms are massively more important than the language.

> poorly managed ecosystem and hodge-podge of tools like virtualenv, pyenv, poetry, etc. that never quite become standardized and

This is true, but Java and C# also have many issues in this respect. The move from Java 8->11 is particularly painful - many fundamental libraries related to security or connection handling were not backwards compatible. Many libraries now require multiple branches for different JDK levels. Maven and Nuget are about as good as pip - they all have weird edge cases.

I use both Java and Python on a daily basis - each has their strengths and weaknesses. Java is great if need long running processes with weeks/months of uptime, Python is great for backend data manipulation and analysis.

Long gone are the days when Python was a hacker tool. It’s been an enterprise thing since startups got wind of the fact that it could be used to attract programmers, to attract VCs.
Recently posted this, which wasn’t well received.

https://motherfuckingwebsite.com/

Where does this fall?

In going too basic. We can go to simple and elegant without going all the way back to crappy stone tools.

http://bettermotherfuckingwebsite.com/

https://evenbettermotherfucking.website/

It’s interesting that on mobile the original one is actually nicest (to me).
right, the problem is that on wide displays we really aren't meant to read, say, 27 inch-wide columns of text.

The silly thing is that it's literally one CSS property, max-width, that takes care of that problem.

Thanks for that link! I actually like the other one much more. I really appreciate JS free sites, Amazon can be used without JS for example.
That site is a piece of shit, because it uses google analytics, thus snitches to a big brother.
You’re right, I didn’t notice! Gonna link to evenbettermotherfucking.website from now on.
I'm currently working with a team of Advanced developers for the first time in my career. Nobody is padding their CV with fancy shit. Everyone has gotten the "new shiny" out of their system.

Everything is as simple as it can be, no simpler and no more complex. Sometimes a bunch of flat JSON files in an S3 bucket is enough of a database, you don't need a 42 machine Aurora cluster.

All fancy "Machine learning" stuff really is just a bunch of ifs and for loops internally :D

> Carmack’s recent “But here we are” speech resonated with me.

Watching this right now and all I can think about is Microsoft Bob.

Well said, this hits home. Also constant refactoring and maintenance of the codebase without adding any new features.
Bull's eye.