Hacker News new | ask | show | jobs
by ChrisMarshallNY 1207 days ago
I worked the majority of my career at an "elite" Japanese corporation. It's one that has a brand pretty much synonymous with "Quality." Many of my peers were among the finest engineers and scientists in the world.

I was often the dumbest guy in the room, and I'm smarter than the average bear.

Dealing with these folks could be infuriating. Every time I would suggest orthogonal approaches (because, like, software is different from hardware), I'd be called "lazy," or "sloppy."

It made me write good code, though.

If those folks saw the way I work now, they'd be horrified. They'd call me a "reckless cowboy," or something to that effect.

But most folks in today's software industry think I'm a stuck-up prig.

I work quickly. I leave good, highly-documented code, that lasts a long time (For example, one of my C SDKs was still in use, 25 years later), and I don't want to toss my cookies, whenever I look at my old code (sometimes, though, I shake my head, and wonder what I was thinking).

I'm my own best customer. I'm the one that usually needs to go into my old codebases, and tweak them, so I write code that I want to see, in the future.

I've come to realize that the term "over-engineered" can mean a couple of things:

1) This code is too naive, complex, and byzantine, which makes it prone to bugs, inflexible, and difficult to maintain; or

2) I don't understand this code. That makes it bad.

I used to have an employee who was "on the spectrum."

Best damn programmer I've ever known. Crazy awesome. Had a high school diploma, and regularly stunned the Ph.Ds in Japan.

His code was written very quickly, was well-designed, well-structured, well-documented, bug-free, highly optimized, and an absolute bitch to understand.

1 comments

I think the other thing that "over-engineered" can mean is code that's unnecessarily good for its purpose.

If you're building a quick demo of a product to get user feedback, and you write perfect code that's highly maintainable, you've wasted time - better to throw together something as quick as you can and rebuild it if it's actually going to be used by/sold to customers. That's really overengineering in my mind - doing a poor job with the quality/speed tradeoff given the purpose of the thing you're building.

> If you're building a quick demo of a product to get user feedback, and you write perfect code that's highly maintainable, you've wasted time

In my experience, this is a trap.

The demo almost always becomes the product, because upper management sees the demo, and says "Hey! It's almost done! Let's ship!"

This is how you end up with these gigantic Frankencodebases.

These days, my test harnesses and demos are generally "ship quality." It also means that I can mine them for snippets, without holding my nose.

I have spent a great deal of time, however, practicing, so that I write top-shelf code, by habit. These test harnesses are often churned out very quickly.

This is why some people will make the demos rough in some obvious ways before presenting them.
> If you're building a quick demo of a product to get user feedback, and you write perfect code that's highly maintainable, you've wasted time

Any time I thought I could shortcut my way to a demo by relaxing on perfect code/maintainable code it has always ended up taking just as much time and often longer.

Almost every time I've thought to myself "I will probably need to refactor this later", I did indeed need to refactor it later. But I think a lot of those cases I still made the right decision.

The initial version took M hours to develop, and the refactor took N hours. If I had done it right the first time, it would have taken L hours, where M < L < N + M. But it's not hard to construct legitimate business scenarios where the "N + M" solution is better than the "L" solution in terms of meeting the business goals.

I expect M ≈ L, though. All you can ever gain by relaxing code quality is some keystrokes, but I'm not sure typing is a bottleneck to begin with. The bulk of the work required is the same no matter what the code looks like. I've often believed that M < L when I've tried to take shortcuts, but in hindsight I'm not sure it has ever ended up being meaningfully true.
It's not about code quality in terms of variable names and things like that, it's more about architectural decisions. What assumptions do you make, what edge cases do you cover, how much flexibility you build into the design, how extensible is it, what kind of tests do you write, etc.?
> What assumptions do you make, what edge cases do you cover, how much flexibility you build into the design, how extensible is it, what kind of tests do you write, etc.?

This what I was referring to. I'm not sure there are shortcuts here beyond saving some keystrokes.

As you've mentioned tests, this is one place I see a lot of people thinking they can save time not writing them out, even opting for no tests. I expect a good test suite for the average application easily doubles the number of keystrokes required, at very minimum. The code doubling in size sounds like a lot more work, but is it really in the grand scheme? You still have to put in all the same amount of thought into those tests in order to write the code (and again if you choose to manually test it). All you've saved is the effort of typing out the tests, which I don't find takes all that long.

Maybe there are some slow typists among us? If you spend most of your time clacking on the keyboard then, indeed, the number of keypresses required could become significant. But that's not my experience.

My advice to younger engineers is ALWAYS to remember demos don’t get rewritten. if a demo appears works, some one will want to ship it as is.
At the same time, not everything you ship needs to be a master work. "Working well enough to ship" is not the same as "flawlessly architected".

It also depends a lot on the business context, whether you can trust leadership to respect technical debt or not.

Absolutely, but be careful about the corners you take when making a demo, or as someone else suggested, make it clear in the demo that something isn't done.

My first big assignment on my first job I presented a demo ~1mo into a 3 mo project. It didn't persist data, or work on more than one host, and it saved state to a json file on the one server I manually copied the executable to. Everyone is the demo doesn't see that, they see it working as expected. The first question I got was why can't we ship this today, it appears to work as expected?. PMs, SDMs, etc care a lot less about the "it takes a while to set up something that scales, and stores data in a safe encrypted database, etc" when they see something that works.

Now whenever I do a demo like that I append "DEMO DATA:" to any visible string, and ensure I demo at least one failed behavior, just to guarantee that no one thinks it can be shipped that day (if I know it can't).

> whether you can trust leadership to respect technical debt or not

Most C-suite folks, these days, are running leveraged up the yin-yang, financially; so I suspect that "tech debt" is almost meaningless.

I'm trying to remember if I have ever known an [American] manager, that gave the slightest damn about tech debt...

...

Nope. I got nothing.

There isn't really an excuse to intentionally write crap code though. You'll normally be the one who ends up working late to fill in the gaps later.
This has been my experience.

I’ve just developed good coding habits, so even my lashups are better than many people’s final ship code.

“We are what we repeatedly do. Excellence, then, is not an act, but a habit.”

I have come into serious conflict with one of my coworkers over this. He thinks everyone (except him) is either overengineering or underengineering everything all the time, but usually he just doesn't understand the problem context and is making assumptions that turn out to be incomplete or incorrect. It's a great lesson in humility to realize that no matter how smart or capable you are, you don't know what you don't know until you find out that you don't know it. I used to be a lot like him until I got slapped around pretty hard (metaphorically) as a result of my arrogance.
School of Hard Knocks alumni, here.

“Good judgment comes from experience. Experience comes from bad judgment.”