176 comments

[ 2.0 ms ] story [ 206 ms ] thread
Sounds quite arrogant to me. And didn't get the biggest problem: Not finishing stuff.
I must admit I'm bad at this. However, in my defense it comes down to: bad management.

I'm forever being told to work on the next MOST IMPORTANT THING EVER only to be told after a few days that I need to work ON THE NEXT MOST IMPORTANT THING and that the MOST IMPORTANT THING EVER that I was working on is no longer important at all.

le sigh

"Hey, FuzzyDulop, we're a day before deadline but I've been thinking, we could do SUPER BRILLIANT IDEA THAT CHANGES EVERYTHING and it'd be amazing! What do you think?"

...

"You can forget about your deadline if you want that in, boss."

* skip forward a week *

"Hey, FuzzyDunlop, we're a day before deadline but..."

Ha! Old memories. We usually skipped forward 3 months and changed everything again.
And then getting chewed out for missing the original deadline. Usually from the boss who just drop the SUPER BRILLIANT IDEA THAT CHANGES EVERYTHING in your lab.
We get the sort of unsure, passive aggressive criticism, full of ifs and maybes. The sort that actually makes you feel worse because the boss appears to be personally disappointed.

Get chewed out proper and at least you know it's just because jobs have to be done.

Dealt with this from an asshat running a semester-long school project. Solution: Drafting my own spec doc, sharing w/ rest of team, asking for comments, saying it would lock in two weeks.

Followed that doc for the next month or two.

Of course, the asshat was ticked off when the semester was about to close and tried to edit the doc (for the first time). I just said no.

I consider it a success even though even Those Kids who contribute nothing got As and I got a B+ despite working quite a bit.

The opposite approach is much simpler. There's only one sign that you are a great programmer:

Clients and fellow programmers are still happy with your work two years after you've delivered it.

(Of course: "still" implies that they we're happy at delivery, which includes actually shipping working software in a timely fashion.)

I would definitely stipulate that the clients applied to this metric need to be "clueful". You might give them exactly what you asked for, only to have them discover that what they asked for wasn't really what they wanted; "clients from hell" might ask you to re-write it for free, or at least be cross with you for not reading their minds. In any case, they won't be happy.

Ignore those.

(comment deleted)
"Clients and fellow programmers are still happy with your work two years after you've delivered it."

Disagree. The first system I wrote kept the client happy for years. It was a mess, but it was literally millions of dollars better than not having any system.

If what you mean is something like "focus on doing work of long-term value, and consider programming skill as such an input", then I'd agree with that.

"and fellow programmers"

Did your client ever hire programmers to maintain and improve the first system you wrote? Were those programmers happy with your work?

I guess if no one is ever going to maintain your code it doesn't matter as much. I wouldn't ever be so bold as to predict ahead of time whether that's going to be the case.

It also assumes those fellow programmers are also good programmers.

Can a mediocre programmer tell the difference between mediocre code and good code?

To the original point, the happiness of the client and other developers is a good indicator, but not the only.

  Can a mediocre programmer tell the difference between mediocre code and good code?
Maybe not directly, but they can probably tell how well they understand the code and how hard it is to change. Not as well as a good programmer, since they'll have more trouble with both regardless, but somewhat.
My bad; thanks to philwelch and saraid for flagging the error. The resulting discussion is interesting, as is 13 upvotes for a post based on a misreading :-). FWIW, my favorite bit on programmer's understanding each other's work is Yegge's Done and Gets Things Smart.
That's true. It's not so much about other programmers being a passive critic of your code so much as it is about the maintenance programmer down the line being able to understand what your code is doing and either fix bugs or add features to it.

The maintenance programmer should be competent, but shouldn't have to be brilliant to understand what's doing on (except in the rare case that your code actually is doing something brilliant). If the maintenance programmer doesn't understand a basic language feature, it's his fault if he doesn't understand your use of it (be it ternary operators, blocks, list comprehensions, regular expressions...). If the maintenance programmer does understand ternary operators but you do something like nest them four layers deep, it's probably your fault if he gets lost.

I wonder if the test is closer to one writers face: you're probably a decent writer if people value your work enough to read it. Likewise, whatever else one can say of programmers, you might be a reasonably decent one if someone else values your work enough to use it. "Reading" and "using" in this case might be similar.
Well, I wonder. As the neighborhood bookclub's pain in the ass (I did not seek the vocation; it found me) I see quite a number of books with great blurbs, and even the occasional award, that I think are very sloppily done. A large number of best sellers seem to scratch an itch widely but briefly felt. Will anybody read _The Da Vinci Code_ in 2025?
This is the only metric that matters. Ability to achieve. Everything else is a tool.
(comment deleted)
(comment deleted)
This article stands out from many that point out common errors. This one also provides great* tips on how to improve -- even a "contrapositive" link: http://www.southsearepublic.org/article/2024/read/what_makes...

* Disclaimer: maybe I've seen so many "you're doing it wrong" posts that I see something in the opposite direction and get too excited.

But then, that's what makes something like PG's "Great Hackers" (http://www.paulgraham.com/gh.html) rare. It takes a lot of things: education, some innate ability, good habits, work environment -- including a good team...

Innate ability isn't a huge factor, but writing wonderful code definitely isn't for everyone. So then, what is to be done with all the mediocre code being produced? I don't see the world overrun by it, long term: code is too expensive. But to get there, something definitely needs to be done.

This is a ridiculous assertion. I believe it's the kind of attitude that keeps our profession from gaining respect among other professional groups.

I've cooked meals for people that were impressed and happy, does that make me a great chef? Perhaps the people I fed are easy to please, have a simple tastes, spend most days eating unflavored oat meal.

If i'm capable of changing a car's spark plugs, and it continues to run well does that make me a great mechanic?

People having low or incorrect expectations does not change the overall quality of something you create or deliver.

That could also be a sign that you work in an industry that doesn't change very much.
I'm not sure being a great programmer (as in being great at the craft) is the same as ship on time & be sucessful. It's quite possible to write crappy code but still have a usable product that satisfies the customer much more than the previous pile of crap.
I think the very first judgement you should make about a piece of software is whether it works or not. After all the user will never care about anything else.

That being said, if you are in a team and you know you all will have to extend or maintain the code at some point, then discussion of coding style, program features, choice of data structures, etc, is healthy. These things are important for a growing application, getting them right will make the software more robust and make maintenance more efficient.

A lot of these make sense, but I would caution against being discouraged if you show any of these symptoms. Like another front page article that says IQ is not static, I think this also definitely applies to programming ability.

I hope this isn't used by some to push the mantra that 'not everybody can code'.

Yeah, I think the title should have been "Signs that you are a mediocre programmer", which would have been less discouraging. I'm sure most good programmers have started out making many of these mistakes. At least it has a "Remedies" section, so it's not a total downer.
I completely agree. Several of the mistakes listed, particularly thinking in sets, were things I had issues with until that "aha" moment when the paradigm shift in my thinking about the problem occurred.

On the other hand, I doubt the author was trying to discourage bad programmers, but rather bring common deficiencies or mistakes up to help programmers avoid them. To me, many of these are signs that you are a new or inexperienced programmer, not a bad one (although if you've been a programmer for a decade and are still making them, you may have something to worry about).

Especially symptom #2 - "Executing idempotent functions multiple times (eg: calling the save() function multiple times "just to be sure")"

That could just be OCD rather than bad programming.

I would say that's OCD causing them to program badly. That there's some underlying condition behind the erroneous pattern does not excuse it's presence in the code base.
> "Bulldozer code" that gives the appearance of refactoring by breaking out chunks into subroutines, but that are impossible to reuse in another context (very high cohesion)

I feel like this might give people the wrong idea. Surely some amount of cohesion is desirable. Also, I'm not quite sure how one "gives the appearance of refactoring" without actually refactoring. Whether it's useful or not may enter into it, but I would usually consider the breaking out of chunks into subroutines refactoring.

Not only that, the purpose of refactoring isn't simply for reuse, but also for readability. If you break out chuncks that aren't reusable, but enhance the readability of the code then you've likely improved the code.

Given the choice between reusability and readability I'd say that readability should usually win (although it is a false choice).

I would contend that if you're having code readability issues, it'd be better to fix it by sprucing up your whitespace and comments, instead of saying "Well, let's chunk it into more functions" and have method(), which returns method1(), which returns method2(), which returns method3()...

Chunking for the sake of itself doesn't seem like a viable strategy to me.

When you add a new-line or two into a section of code, you're usually saying:

"These two blocks of code do something different"

Thats what is normally called a method. If it's only for one class then by all means make it private and name it well, so the caller remains readable.

I agree that that strategy's pretty feeble, but IMO it's still better than e.g. a thousand-line function. If nothing else it forces you to break out the parameters explicitly, instead of just having a thousand lines of intermingled state transitions.
Chunking out in more functions is good in itself, because there's usually a well defined interface for what can get in and out of a function.

Whitespace and comments can suggest that some pieces of code don't interact that much, but chunking into functions lets the compiler prove it.

Fully agree and I want to add, that it is also a requirement for writing good, simple, small unit tests. Clean code means, a function should only do one thing and that's the thing you can test.
I find this is one of the things I struggle with the most. I definitely "refactor" code by moving it to a subroutine sometimes purely for readability's sake. I also try not to stress out about how reusable something might be until I actually NEED to reuse it. Otherwise it often seems like "premature optimization" trying to generalize a routine that I'm not even sure will ever get used anywhere else.
In my experience, the drive to make things reusable from the start ends up delaying projects to a point where they might just not get done.

I also refactor for the sake of readability (and urge my co-workers to do the same). Of course, this might mean I'm a bad programmer and I shouldn't ever get 6 levels deep in logic in the first place...

I once dealt with code that looked like this pattern (sorry for the giant vertical size of this post):

  DO_F() {
    A;
    B;
    C;
    D;
    B;
    C;
    D;
    E;
    F;
    A;
    B;
    C;
    D;
    G;
    H;
    I;
    J;
    A;
    B;
    C;
    H;
    I;
    // a bunch more
  }
So I suggested, "hey perhaps you should break this into functions" and got back:

  DO_F() {
    A;
    B;
    C;
    D;
    B;
    C;
    D;
    E;
    F;
    A;
    state.a = a;
    state.b = b;
    // ... for other state
    return DO_F2(state)
  }
  DO_F2(state);
    B;
    C;
    D;
    G;
    H;
    I;
    state.a = a;
    //...
    return DO_F3(state);
  }
  DO_F3();
    J;
    A;
    B;
    C;
    G;
    H;
    I;
    // a bunch more
  }
When I suggested blocks such as B; C; D; or G; H; I; could be functions, and perhaps a loop could be useful too, the guy looked at me like I was trying to do voodoo and got really defensive about how that couldn't possibly work.

I think that is what the OP meant by bulldozer code...

I paused for a bit when I read, "A programmer can't acquire this kind of knowledge without slowing down." It seems that many businesses that rely on programmers are unwilling to give them the time to be better.

I have seen coders with CS degrees from top-tier schools believe that they couldn't code anymore when placed in environments that do not mentor them, that treat them as horses to be run until their backs break.

If you feel this way, take a part-time job and focus on becoming a better coder. If you are a business that does this... no wonder you waste money on recruiters.

I'm in this position now. I'm not a great developer, and I love learning new tricks, but because I'm billed hourly, am constantly interrupted, and get brought in to useless meetings, I'm left with zero time to learn.
The other problem with this is that you never have the opportunity to improve the business, either. Often, management wants the rank and file to improve processes ("because they know them best") but it's hard to find the time for that when you're already working full time (and more) on your deliverables.
No doubt. In fact, this is exactly what happened to me today. I'm supposed to have great ideas, but when trying to implement them, told that I need to focus on paying the bills. I don't know how people manage this long-term.
By jumping ship and landing at a less-dysfunctional workplace.

If their business plan doesn't include time for improvements of the processes it's a failure. Leave now. Don't try to make up for their mistakes. They won't see it (positively), let alone reward you for it.

Do good for your old co-workers by recruiting the good ones into the more-functional company.

This. Don't ask me to make process improvements when you are expecting me to be billable 115% of the time.

Fortunately, my group typically allows for 10%-20% of my time to be used for either training (learning new tech/languages) or process improvements (mostly internal tools). Other groups at the company don't have it so lucky, and those are the groups that desperately need improvements.

Depends on what process you are talking about. If you are trying to improve a process which will hurt the time to deliver of a major project costing a company money, then is it really right to call the company a failure?

Every company/division/organization has priorities and while there maybe inefficiencies in their processes, they maybe a minor cost in relation to the other priorities. (I can't believe I actually just played devils advocate/defended this).

No, I stand by it. If a company doesn't include time for process improvement they have failed. Maybe they haven't tanked yet but the first bend in the road will finish them.

This doesn't mean they have to stop and fix every non-problem, but if there's no time budgeted to fix what comes up the first real problem will ruin everything.

There is one surefire sign you're a bad programmer: faced with a problem, your reaction is "pshaw, I see how I can solve this..."

Whereas a good programmer has the reaction, "uh-oh. I see how I can solve this..." And knows that this is just half the battle, and what he's getting himself into.

Oy, I used to do this all the time... till I stared sitting down to solve some of those problems. That was about the time I started saying "uh-oh". I (think) I have moved on from this phase fortunately.
Well, that's just experience. After a while, you lose your confidence that you are the new hawtness, and you start seeing all the ways things can go wrong... and ways you can avoid them.
my ruleset is much more liberal

signs that you are a good coder: you enjoy coding, you enjoy a good piece of code

signs that you are a bad coder: you don't enjoy coding, you can not appreciate beautiful code

if you enjoy coding it jut doesnt matter if anyone else thinks that your code sucks. you will get better. if you hate your job (programming) then you code stinks and will get worse.

in my careere i went from good to great to bad to i dont code anymore to good

How long have you worked as a professional software developer? Have you ever worked at a large company? There are plenty of people with a decade of experience who enjoy writing code who are just bad at it. Some of these people work on software that is much more important than Facebook.
My first thought was, "wow, infogami is still up?" I guess I left it in a good state. :)
Looking at the homepage, it says that the most popular pages were converted into static form, and now they're trying to sell the domain.
Yeah, we did that a long time ago. I'm just surprised it is still running! I don't think I even told the other reddit guys about infogami or where it runs or anything.
I guess I can't log-in and add a link to its new home, eh?
Nope, it's static only. But if you ask the reddit guys real nice, they might be willing to edit the file manually for you.
"You're not reading this article."

But seriously, it probably never occurs to bad programmers that they should be finding articles like this.

Perhaps a better title/approach would be "A Bad Programmer Taxonomy, And How You Can Help."

I don't need an article to tell me I'm a bad programmer.
"You seriously consider malice to be a reason why the compiler rejects your program"

Of course it's malice.

I agree, most of these are hilarious!

But seriously, until programmers are paid $100/hour or given royalties, deal with the result of bad programmers...

... or do it yourself!

the compiler in many simple cases could have tried to repair the program, like attempting to insert(remove) missing(extra) ';' or '}' for example. While it may be not a malice, it is definitely an absence of a good will.

Note: i did work on a real product which had parser inside that had such style of repair implemented, and such approach is also quickly mentioned in the dragon book as well

It's possible that such automatic repair would create a bug. Much safer to have a human check and ensure that the ; goes in the right place.

A better point is that the error messages from many compilers can be very obscure. This was particularly true 10-15 years ago.

Yeah, if a compiler only compiles the code you actually wrote, it's still your fault. If a compiler tries to infer what you meant and compiles that instead, then it might genuinely be the compiler's fault when something breaks. Plus, the original code should still be fixed instead of relying on the compiler to compile the same broken code the same "right" way each time. We spent the last 20 years trying to convince web developers of that idea.

Clang does something like this. If it notices a simple enough syntax error that it can correct, it still generates the error message but it makes the correction internally and continues the compilation far enough to generate useful error messages about the rest of the code. But it doesn't output anything or change the code.

Someone has never dealt with incompetently written scripting languages or tragically wrong documentation for the same. Sufficiently advanced incompetence is indistinguishable from malice.

I remember having to test exactly how a bunch of different predicates actually worked, when the documentation thereof was a complete lie and the predicates just evaluated to false instead of creating an error when fed data they supposedly accepted (but actually couldn't).

(comment deleted)
A sign that I found missing from the list: you are totally devoted to a particular programming language and believe it's a silver bullet. All good programmers that I know understand that languages are just tools and all have tradeoffs of some sort.
I'm pretty sure I saw the "everything is a nail" type listed, which might well cover the folks that think Technology A is the be-all and end-all.
Good point. Being overly attached to a language means you end up choosing the wrong tool for the job at some point.
I think this stuff comes from someone who has a colleague with these "symptoms", and is either frustrated because they can't educate them into better techniques, or is a subordinate with no power.

In any case it's pretty unforgiving.

I have had a colleague who fits the bill here, but actually I just let them get on with their work and I got on with mine. Sure, it was hard when he delivered something that was excruciatingly poorly conceived and executed and I had the task of taking it to the the next stage. But you know this isn't a life and death business, he was a really nice guy, and I wasn't going to rock the boat. The next project, I was working with someone else and everyone was happy.

Contrast that with making an issue of it, and you might find yourself being labelled as a trouble maker, even if you did have the best intentions for the development.

If you run the show however, don't stand for it, because it's your business, and it calls for the best at all times.

I'm presently repairing a project that violates nearly every one of these principles. Literally, it's like they had a checklist made from this post and went down it to ensure they did everything wrong.
To me, everything in that article can be addressed with a little experience.

My one indicator that someone is going to be a bad programmer actually has little to do with technical skill sets, but rather personality. As my sanity check, I make sure to examine the open-mindedness (willingness to research and use unfamiliar tools) of programmers. More often than not, you find programmers who are very comfortable in given languages, environments, tools etc, but once you take away their comfort blanket, they keep reaching back for it.

An extreme example would be a scenario such that a programmer who knows C very well decides to do a decent amount of parsing in C instead of researching better languages for the job such as python or perl.

I'm a student in the third year of my CS degree and I constantly worry about not being a good programmer. There's things on that list I need to work on.
oh my! I love when you recommend specific career base on specific issues. You made my day! I can't stop laughing. "Bag Lady" seriously looool
I agree with joe_the_user. I found the article snide and condescending. I suggest alternative careers for the author:

- Leader of a high school clique - Movie reviewer who concentrates on who's "in" - Coiner of demeaning nicknames

I wouldn't want to work with this person.

I agree too. I found it arrogant and very condescending.

But his alternative career section is humorous.

Is it odd that any tense of the word "ship" does not appear in this article?
Believe it or not, sometimes we code for purposes other than selling stuff.
But you still have something to ship, even if it's just to your buddies on github.
What you give to someone else may not be code -- it might just be the code's output.
I guess "ends justify the means" would be another article.
It's probably written by a CS professor.
I wish articles like this would namespace their assertions by telling us what they mean by "good" or "bad", so we could avoid the perennial echo chamber debate that goes like this:

    A: GOOD MEANS SHIPPING AND PLEASING YOUR CUSTOMERS
    B: NO YOU FOOL! GOOD MEANS WRITING CLEAR CODE THAT OTHER HACKERS CAN READ
    C: NO YOU FOOLS! GOOD IS A HAPPY MEDIUM BETWEEN BOTH OF THOSE THINGS
    D: DEBATE IS HARD, LET'S GO SHOPPING!
God forbid we agree on what words mean before we talk about them...
"Good" already has a meaning, you can't arbitrarily redefine it. You have to actually figure out what the most "good" tradeoff is between shipping and writing maintainable code.
"Good" is also arguably subjective and relative to the subject's perceptions of "bad"(and vice-versa).

So of course that "good" tradeoff to one programmer might be a "bad" one to another.

I'm not bad. I'm just drawn that way.
Good has a meaning, but it is a meaning that is highly context sensitive.

When talking about "Good cars" for instance, what makes a good car for a mother of 5 is likely different from what makes a good car for a single person who is very worried about the environment and both of those are different from a "Good car" for drag racing.

Yes, and likewise someone can be a very good web programmer while being a crappy embedded programmer. But there's common factors involved: likewise, a car that doesn't run probably isn't a good car regardless of your requirements. (OK, maybe you're a hobbyist that likes working on cars when they break down, or maybe you enjoy having broken down cars on your lawn for decoration. But by the same token, maybe you're a hobbyist who enjoys the IOCCC.)

Defining the word "good" is a philosophical rabbit hole for sure, but if someone comes out and says "a good programmer is someone who writes maintainable code", and someone else comes out and says "a good programmer is someone who writes fast code", and someone else comes along and says "a good programmer is someone who writes code that pleases the customer", you're still having a meaningful discussion about which "good" is better, so to speak.

Except this is sort of a cop out isn't it? In the sense that for any type of artist there are good artists and bad artists but while the good artists may be highly differentiated bad artists share a common set of deficiencies.

The article is almost in the 'you might be a <foo> if <bar>' style (most common instantiation I am familar with is 'you might be a redneck if <insert denigrating attribute of redneck>' And in the spirit of that humor I liked it.

That being said, if you ask me as a hiring manager what I consider 'good' programming, its 'readable/understandable', it does what it is supposed to do, and it has tests.

Anna Karenina would have you believe that there are more ways to fail than to succeed, but I would argue the opposite in most cases involving creative endeavors:

Bad programmers are all alike; every good programmer is good in his or her own way.

Props just for the Anna Karenina reference :-)
Not sure this relates 100%, since the article is mostly talking about your understanding of concepts.

If programmer A understands recursion and programmer B does not programmer A will write better code regardless of deadlines.

Thanks dude... everybody has their own evaluation criteria in their mind (which is not disclosed) and people start calling things good or bad. Most of the debates end up being a very unscientific way of evaluating something!
I found the "Alternative careers" hilarious.

My version:

  Your code sucks.
  Alternative careers: "Do you want fries with that?"
OP's version:

  1. Inability to determine the order of program execution
  Alternative careers: Electrician, Plumber, Architect, Civil engineer
  
  2. Insufficient ability to think abstractly
  Alternative careers: Contract negotiator, Method actor
  
  3. Collyer Brothers syndrome
  Alternative careers: Antique dealer, Bag lady
  
  4. Dysfunctional sense of causality
  Alternative careers: Playing the slot machines in Vegas
  
  5. Indifference to outcomes
  Alternative careers: Debt collection, Telemarketing
So the real test of a good programmer is one who can write a routine that crawls the source code of a bad programmer and tells them what they should really be doing.
I'm glad that as a purely functional programmer I don't have to worry about order of program execution so much.
Unless you are using a magical computer, you still have to worry; there are resources you must manage that depend on the underlying OS and von Neumann architecture.

An example that bites Haskell programmers are space leaks due to too much partial evaluation and not enough full evaluation. Other problems include keeping a file open for too long and leaking the fd. An ideal computer has infinite space and no files. A real one... nope :)

The advantage of functional programming languages is that you get to write part of your program as though you have an ideal lambda calculus evaluator. But at some point, you still have to realize that there's a grey box under your desk that doesn't know what a lambda or fixed point is. (But this is better than programming languages that say "hey, you've got a heap, a stack, and some registers! well, so long!")

Yes. Notice my choice of words. "Not so much" vs "not at all."
In fairness, "so much" fits the "weasel words" category (https://en.wikipedia.org/wiki/Weasel_word). You and jrockway placed different values on the phrase because it is a "numerically vague expression". I admit to making similar expressions. :)
I have to wonder if someone who can't determine order of execution should be an electrician or plumber either -- those aren't static systems!
I guess the point is that there's no "privileged" position in these systems which changes with time, like the point of execution in programming.

What is the proper name for the bit of code that's currently being executed? I've suddenly realised that its a concept you think about constantly when coding, but its so much a part of the scenery so to speak that you never consciously consider it.

At the hardware level it's called the program counter, which is a register containing the address of the current operation the processor is running. After the operation is finished, it increments itself and moves to the next step in the program.

Edit: just realized I didn't really answer the question, I believe what your actually talking about is a statement.

I usually jump at the chance to talk about stuff from my old EE days :)

The program counter isn't the only element of that "what the program is doing now" state though. The context in which the current instruction is being executed makes a world of difference.
inclusive of that, the best term is probably "machine state" or similar.
I consider the "context" the scope. What is the scope in which the current statement is being executed...
And the ability to save all of that into a variable so that you can pass it around to other parts of your program means that your programming language supports Continuations.
Current instruction or active instruction (at the processor level)

Currrent statement or active statement at the code level

That's an interesting point.

I know that when I'm in the flow coding, there is a sort of Tick:the-program-does-this, Tock:the-program-does-that stepwise execution of the code in my head.

There are many answers as to what the hardware is actually doing with the instructions, but more generally what exactly is the name of an imaginary discrete state of a program that currently only exists in a coders head?

>but more generally what exactly is the name of an imaginary discrete state of a program that currently only exists in a coders head?

This is what I'm trying to get at. There isn't one is there? It's weird.

What is the proper name for the bit of code that's currently being executed?

I would have used 'Cursor' or 'Program Cursor'. But I'm now convincing myself that that a database term.

On the amd64/i386 platforms, the Instruction Pointer CPU register points to the executed instruction. Its name is IP for 16-bit code, EIP (extended) for 32-bit code, or RIP (register) for 64-bit code.
Why is "Performing atomic operations on the elements of a collection within a for or foreach loop" a symptom of mediocre programmer "inability to think in sets"?

How should one do that if your "thinking is sets"?

(comment deleted)
That particular symptom is built under the assumption that your language supports map/filter/reduce or some equivalent functionality. These are generally preferred when available because there are fewer places to make mistakes.
(comment deleted)
The best part is at the very bottom... if you think it's TL;DR, you could have missed a lot of points.
I'll admit, when I was a C programmer, I was victim to "Dysfunctional sense of causality."

I remember taking a C class in my undergrad, nailing the code to perfection, and getting an F because I had written the code in under different architecture and compiled with a different compiler (not specified in the prompt by any means). It ran well on my computer (and I proved it), but since it wouldn't run on my professors computer or TAs computer, I still received an F.

So yes, I still maintain strong malice towards C :-)

Whooops... One of the symptoms is:

"(Functional) Manually caching the results of a deterministic function on platforms that do it automatically (such as SQL and Haskell)"

Isn't that what memcached is doing?

I suspect that people who don't "get" pointers (#4 in the article) actually have a much harder time with the pointer declaration and manipulation syntax in C than actually understanding how pointers work and what they let you do.

For instance, in C the * character is used both to declare a pointer and to dereference one and they can be stacked to dereference nested structures. Then & references a variable memory location but is also used in method signatures to change the semantics of calling a function into pass-by-reference. To complicate & further, & is often seen alongside const declarations, which are a whole other thing that people have to keep in their heads.

On top of all of this, * and & have their own operator precedences and associativities that you have to memorize, which is a whole discussion about binary versus unary operators and precedence tables. And I didn't even mention [].

I really don't think that people fail to comprehend pointers because their mental models need updating nearly as often as they just haven't fully internalized all the hoops that C makes you jump through to mess with pointers.

> For instance, in C the * character is used both to declare a pointer and to dereference one and they can be stacked to dereference nested structures.

This problem can be solved by thinking of * as always dereferencing a pointer. So:

  int *a; /* "*a" is an int, thus a is a pointer to one */
  int *b, *c; /* *b and *c are both ints */
This also has the nice side effect of explaining why good C programmers write the * next to the variable name and why multiple variables declared on the same line all require a * next to the variable name.

> Then & references a variable memory location but is also used in method signatures to change the semantics of calling a function into pass-by-reference. To complicate & further, & is often seen alongside const declarations, which are a whole other thing that people have to keep in their heads.

Now it sounds like you're talking about C++ moreso than C. In C, & is pretty much always the "address-of" operator (except in contexts where it's clearly logical- or bitwise-AND).

From your post, it seems that the problem is more one of poor teaching, poor explanations (metaphors), or poorly-designed extensions (C++) as opposed to shortcomings of C.

I second the remarks about poor teaching (though C type syntax does sucks hard). The main problem probably comes from the fact that ordinary variables are themselves an indirection of sorts, and programming courses do not make that clear (we tend to confuse the variable and the value it holds). Excerpt from my article on assignment[1]:

[The pervasive use of the assignment statement] influenced many programming languages and programming courses. This resulted in a confusion akin to the classic confusion of the map and the territory.

Compare these two programs:

  (* Ocaml *)        │    # most imperative languages
  let x = ref 1      │    int x = 1
  and y = ref 42     │    int y = 42
  in x := !y;        │    x := y
     print_int !x    │    print(x)
In Ocaml, the assignment statement is discouraged. We can only use it on "references" (variables). By using the "ref" keyword, the Ocaml program makes explicit that x is a variable, which holds an integer. Likewise, the "!" operator explicitly access the value of a variable. The indirection is explicit.

Imperative languages don't discourage the use of the assignment statement. For the sake of brevity, they don't explicitly distinguish values and variables. Disambiguation is made from context: at the left hand side of assignment statements, "x" refer to the variable itself. Elsewhere, it refers to its value. The indirection is implicit.

Having this indirection implicit leads to many language abuses. Here, we might say "x is equal to 1, then changed to be equal to y". Taking this sentence literally would be making three mistakes:

(1) x is a variable. It can't be equal to 1, which is a value (an integer, here). A variable is not the value it contains.

(2) x and y are not equal, and will never be. They are distinct variables. They can hold the same value, though.

(3) x itself doesn't change. Ever. The value it holds is just replaced by another.

The gap between language abuse and actual misconception is small. Experts can easily tell a variable from a value, but non-specialists often don't. That's probably why C pointers are so hard. They introduce an extra level of indirection. An int* in C is roughly equivalent to an int ref ref in Ocaml (plus pointer arithmetic). If variables themselves aren't understood, no wonder pointers look like pure magic.

[1]: http://www.loup-vaillant.fr/articles/assignment

Thanks for the informative reply and the excellent blog post!
I'm actually astonished by the hero-worship surrounding the inventor of C. Its got so many embarassing flaws, or had at any rate; its been patched and bandaged for decades.

Sure, say that hindsite is 20-20, but I knew C was busted long before I learned anything about objects or monads etc. Syntax is goofy, backward as you say (I thought that the 1st time I ever saw a C program decades ago); its promise as an expression-based syntax was botched and mortgaged, resulting in generations of hacks; its fundamental expression evaluation syntax was broken to begin with, and as patched its cumbersome and baffling at times. </rant>