Hacker News new | past | comments | ask | show | jobs | submit login

Excellent article! Thank you, Monica. You just put into words a whole bunch of stuff that I always "sensed" but never "said".

After spending 7 million years (it sure seems like it) cleaning up the most vile garbage code you could possibly imagine, I'd like to elaborate on this:

Architecture is more important than nitpicking. While a small line of code could be improved, the stuff that tends to cause bigger problems down the line are usually architectural. I should’ve focused more on the structure of the application than tiny bits of code early on.

Architecture = the sum of all those seemingly unimportant "tiny bits of code".

It seems like every time I have to refactor or (heaven forbid) rewrite, I have to start deep down in those tiny bits. I've worked places with all these "genius" architects, but when I dive deep down into the code, I find a sewer than couldn't possibly support software life as we know it, no matter how brilliantly it was conceived.

Fellow programmers, you probably know exactly what I'm talking about, all those cancerous tiny bits that kill even the strongest patients:

  - variables so horribly named that no one could ever interpret them
  - 800 line iterations surely destined to be broken by a maintenance programmer
  - conditionals so illogical that no one can tell if they ever worked
  - early exits to hell that can only be fixed by rewriting
  - double negative logic that could not never fail to break
  - 8 lines of code where 1 could do
  - <add your own>
Great architecture comes from both directions, "above" and "below". From my experience (unlearned as a junior developer :-) ), 90% of the problems have always seemed to come from below.

Get good at the trees and the forest will flourish.

From my experience of working at Fortune 100's for over 10 years as a senior engineer, I would say I have seen what you described, but rarely if ever are they the architects fault. There are usually just a few of them and usually hundreds of developers constantly shoveling garbage into the codebase. They rely upon processes and such... but they all fall apart in practice.

I've come to the conclusion good is good enough and working is even better. Usually the business agrees.

> - early exits to hell that can only be fixed by rewriting What do you mean by that?

  if (a) {
  } else if (b) {
    if (something_else() == -1) {
it has similarity to frequent `goto label` type of coding

I'd argue that this sort of thing is fine, as long as the `return` is not nested deeply. A function which starts with a list of 'early exit' simple conditions is fairly easy to deal with, compared with one where you need to read the whole thing to check that the value assigned to the returned variable isn't reassigned later in a different condition. Early returns can significantly reduce cognitive load if used correctly precisely because they exit directly.

Once you have complex bail-out scenarios, the function needs breaking up or insanity follows... but that's true of any sufficiently confusing decision tree.

Generally I have found `else` to be something of an antipattern. I usually find it cleaner to write the code as 'this special early bail-out with a return, and the other case is just the rest of the function'. A bit like pattern-matching in Haskell, or a `switch` block in which the default case is the usual one. I also try to avoid reassigning variables, eg. in Typescript everything would be `const`.

But like all generalities, these have exceptions!

GOTO return(); is the droid you're looking for. :)

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact