
Signs that you're a bad programmer (2012) - theunamedguy
http://www.yacoset.com/Home/signs-that-you-re-a-bad-programmer
======
stcredzero
One of the unstated, or subliminal purposes of these kinds of ideas is to act
as an emotional "vent." Its social purpose in the programmer community is to
present a target for the release of "justified" emotional aggression.

Other fields and other kinds of social groups have them in their own contexts.

One of the things that such sets of ideas produce, in sufficiently large
populations and sufficiently complicated contexts, are _false positives_. That
is to say, you will tend to hastily pattern match your object of justified
scorn. You will tend to detect more of them than actually exist. (This is how
human beings are wired up.) What's more, you will conflate highly salient
attributes with actual symptoms of such. Being female, or a member of a
certain ethnic group, or being "too old" then becomes a sign of the insidious
danger.

The thing to remember, is that extraordinary situations require extraordinary
causation. Such individuals do exist, but there must be something or someone
very powerful propping them up. They could be very good at manipulating
people. They could have been granted a sinecure by someone very powerful. Most
often, they are the unwitting beneficiaries of pathological organizational
policies.

So how is a diligent rationalist supposed to approach this? Remember that you
are wired up to produce false positives. Be self aware of your social animal
instincts that will tend to have you use the subject of your suspicions as an
object of scorn. Look diligently for "extraordinary" causation.

Most of all, don't judge prematurely.

~~~
davesque
Yep, agreed. There's an abundance of this kind of scornful thinking in the
tech world. I figure it's mostly a subliminal attempt by programmers to
convince themselves that they're smarter than other people.

That being said, the article seems to be pretty well-written and does have
some good info about anti-patterns once you get past its title. Also, it
proposes remedies to these anti-patterns and bad habits which are useful.

~~~
stcredzero
_I figure it 's mostly a subliminal attempt by programmers to convince
themselves that they're smarter than other people._

That's when you've let your social animal instincts get the better of you as a
sentient lover of knowledge. What will truly distinguish one as an exceptional
programmer is an ability to shed prejudices, analyze, and listen well, not
being on top in the geeky version of the primate dominance game.

------
FrankenPC
One time, I was helping a friend of mine work on Javascript (js) skills. We
cycled through all the basic sorting algorithms to practice js best practices
and help with understanding computation complexity issues.

On one sorting algorithm, Can't remember which one ATM, involved recursion. It
was pretty simple. My friend couldn't understand the nature of the problem
because he didn't have a instinctual comprehension of recursion. I threw
together a Visio of the process and walked him through the blocks one by one.
He still couldn't wrap his mind around it. He started to berate himself and I
could tell he was giving up on his dream. I told him to keep trying. To keep
spending the time on places like HackerRank. He did.

8 months later, he landed a job as a js full stack programmer. Not a senior
level position, but a damn good one. I'd seen his work before his interview
and it was good. He had a command of all the major frameworks and he was
observing all major js design patterns while avoiding idiotic anti-patterns.
His code was clean and easy to read.

IMO Pointing out that someone APPEARS to code like a loser is a petty
playground tactic of someone who has a serious ego issue. Taking someone by
the hand and helping them through the hurdles so they can become a better
programmer is the solution. I can't imagine how my friend would have reacted
if he had read this petty article while he was trying so hard to become a
decent programmer. He may very well have given up. That's not acceptable.

There are only people who give up and people who refuse to concede defeat.
Ranting on a website about bad programmers is giving up.

~~~
kaybe
I find the article really helpful, to be honest. I am not a good programmer
(it's not my job, I am a physicist); my code runs and does all I need such as
automatically control my instruments so I can do someting else, evaluate my
data and make plots. I can also use other people's code, though I sometimes
code by google.

Since code quality is by no means a qualifier for our work and most people
don't really care, it's hard to become better beyond just knowing the
languages better. Programming patterns? Ha, I just use all languages the same
way. This article tells me where my weaknesses lie, which helps a lot, because
I can only google things I have some notion of.

It's not just ranting, there are detailed lists of what could be not-good and
how to fix it. The only thing potentially offputting is the title, really.
(Might help that it's not my job to be good at coding, just a bonus.)

------
pookieinc
I'm not a big fan of the language used, w.r.t. the dichotomies between a
"good" programmer and a "bad" programmer. There are certainly challenges for
junior developers that are mentioned in this article (and I agree with most of
it), but I wouldn't consider those people who do it "bad", rather
"inexperienced". This may be a mere nuance, but it's not something that should
be perpetuated. We all have our challenges and we are all learning to do
better in our work.

In reading this article, I don't think any developer purposely does any of
these things and if they do, they aren't "bad programmers", but just
developers who are still learning.

It seems that the intent of the article is good-natured in that it's pointing
out certain issues with code and how to remedy them, but calling people bad at
their craft so that they read the article is a bit strong.

~~~
muddyrivers
I would prefer to "inexperienced" as well.

Some junior engineers are apparently talented. They would make some of the
mistakes. Even if people point out the mistake to them, they might not fully
get the reasoning behind the better approaches. It is intrinsically part of
the growth, to experience, to learn from mistake, to understand deeper.

Some junior engineers are lack of potential. It is a fact, in every
profession. They are not good at programming, but might be good at other
things. If one can afford, one can help them to gradually transit to other
positions, like product managers, data analysts, etc. It could sound stunning.
Some of them are actually good materials to be managers.

One of the best product managers I worked with was an engineer before. He said
he was simply not good at it, and not interested, either. His contribution as
a product manager was much much higher than as an engineer.

~~~
collyw
My team leader doesn't think in sets, and it gets a bit frustrating when he
describes queries like and imperative program with lots of ifs, and no order
to them.

------
fsloth
Congratulations on fomenting that impostor syndrome.

While the the text contains valid anti-patterns its style is non-helpful.
People should not be put down but encouraged. People will notice sooner or
later if they are not fit for a field by themselves. The only benefit of
berating someone for lack of skills is a temporary catharsis for the one doing
the berating while the person at the other end pays a psychological cost of a
kind or another unless he's really mindful.

Berating command-voice is excusable in a heated argument but maintaining this
voice throughout a long writing is stylistically a very poor choice, IMO. This
just discredits the authors voice as that of an infantile jerk.

~~~
olavk
The problem is the article contains actually useful advice for
newbie/intermediate programmers, but it is framed in such a way it mostly
appeals to experienced programmers with a superiority complex.

~~~
VLM
If you're experienced but not superior, you haven't been learning anything
from your mistakes along the way. I thought the article was extremely
nostalgic. An experienced programmer who can't spin up a funny story about the
time he learned his lesson about bounds checking or implementing regexs the
hard way is either not really an experienced programmer, or what is known as a
"liar", or most politely has an extremely bad memory.

As a concrete example of #2 poor understanding of the programming model, in
the old days we had a saying that you can write fortran in any language, and
it was not exactly a compliment. I guess a modern politically correct analogy
would be the ability to write perl in any language. Any programmer who hasn't
made the mistake of writing code style from their language X in their new
language X+1 is either inexperienced or outright lying or at best is merely
forgetful of doing it.

The article is poorly formed in that the phases explanation from the second
"programming model" discussion actually applies to the entire article, with
most of the article being examples of "phase 1". If you're at "phase 0" it
could be helpful to see a roadmap, and if you're at a higher phase its going
to be somewhat nostalgic.

------
tmerr
In short this article looks at aspects of programming and says if you're bad
at each aspect you're probably bad at the sum of them. I'm not sure what the
purpose is... you can figure out more directly whether you're a bad programmer
by comparing the code you produce to that of your peers.

Aside from that the made up terms are annoying. It would be more readable if
he used

    
    
      voodoo code => dead code
      bulldozer code => high cohesion subroutines  
      pinball programming => unreliable code
    

I can't think of anything good to say about this article.

~~~
Osmium
> I can't think of anything good to say about this article.

Yeah, it certainly reads as very smug (at least to me). I think it's an
attempt at humour that just comes off as condescending; after all, we've all
been beginners at some point. I don't think it's very useful for 'bad'
programmers either, because it doesn't go into much depth or explanation, so
really what's the point? To make us all feel good that we don't do these
things? (some of which are debatable anyway)

------
mbell
> 5\. Difficulty seeing through recursion

It may be a function of the code I work on but I generally avoid recursion
unless I'm _really_ sure about the bounds of my input, which is rare. Few
other things can take a smoothly operating service and hard crash it because
the input got just a touch too big. Worse yet, there is usually no warning as
the problem approaches.

Yea, some languages have tail call optimization, but I've found it to be picky
even in languages that have it. i.e. an otherwise innocuous refactoring to a
method to make it look a bit cleaner, but logically identical, can all of a
sudden crash the process due to TCO not recognizing it anymore. This is also
the type of thing that doesn't show up in testing, but shows up immediately
under production load. Recursion can make some algorithms easier to follow,
but I'll take a slightly more complicated algorithm over being woken in the
middle of the night due to a 'stack level too deep' exception.

~~~
nmrm2
I _really_ want an IDE that puts a little yellow warning thingy on the screen
whenever the compiler can't TCO a function.

~~~
Zak
Clojure has a form of this in that the 'recur' special form is used for tail-
calls and self-calls are used otherwise. Using 'recur' from other than the
tail position is a compile-time error.

[http://clojure.org/special_forms#Special%20Forms--%28recur%2...](http://clojure.org/special_forms#Special%20Forms--%28recur%20exprs*%29)

~~~
Elrac
As someone who does not (yet) do recursion and looping-by-recursion in his
sleep, I deeply appreciate Clojure's hand-holding to make TC situations
completely explicit.

------
EdgarVerona
I agree with other's statements about not judging prematurely. I feel like
every software engineer I have ever run into (including and especially myself)
has done some or all of these things at one point or another. We all have bad
days, we all have poor judgment sometimes. Giving people the benefit of the
doubt in cases of lapsed judgment seems like it would create a far less
hostile work environment. If it's systemic, it's one thing... but let's try to
avoid a witch hunt mentality. Everyone's going to have off days.

The only one whose legitimacy as an antipattern I would question however would
be this one:

>"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 think it is useful to break up complex logic into discrete methods that
represent some logical step in the overall algorithm. If they're private
methods, I feel like that can add to the readability of the algorithm rather
than having it be in one monolithic chunk. I've seen two camps on this - keep
it inline vs. make private methods for discrete steps, and I find the latter
to be more readable when I look through code (my own or someone else's).

There is a limit to that, of course. If you end up with a tangled tree of
methods, that could work against readability... but even then, if you took
that tangled tree and made it a single monolithic method, how often would that
actually end up being more readable?

~~~
collyw
It depends. If the code doesn't not end up indented and reads like a script, I
prefer to read one long method, rather than jumping around a hundred small
methods and trying to keep the overall context in my head. I think this
preference applies more to higher level scripting languages and not all the
time.

------
bad_user
Not sure about the article, since it doesn't seem to say anything useful, but
one problem I'm having with beginners is that beginners are extremely
superficial in analyzing a problem and extremely superficial in coming up with
solutions and have to be told what to do in very precise words and even if you
give them a list of things to do, you still have to review their work because
they might have missed some of the bullet points.

This happens, I believe, primarily due to lack of experience - they haven't
suffered from superficial understanding of a problem with clients rejecting
their solutions, they haven't stayed too many times at 2 a.m. fixing
production issues, the haven't witnessed the proverbial big ball of mud coming
to life because of patched up solutions and they haven't had a project that
had to be rebooted in part because of technical debt created by them. We as
humans, only find out that fire burns badly once we get burnt a couple of
times.

And as a senior I'm completely out of my league when it comes to educating
other people - I'm totally incapable of compressing 5 or 10 years of
experience into a couple of months worth of education. And for example I have
initiatives, like lets do presentations on Fridays, lets do code reviews and
so on. And we do them for a couple of weeks, but then we observe that nothing
changes and that our productivity dropped, because communication represents
points of concurrency in the development process and concurrency represents
the death of parallelization, which is incompatible with really harsh
deadlines. And because these deadlines are a never ending story and the
seniors are overwhelmed, management kicks in to "solve the problem" and they
start thinking of hiring more people, which really means even more rookies to
train, because good people that have the required experience are rare. And the
problem to be solved by our project is so complex, that only seniors with a
deep understanding of the problem can come up with working solutions for the
core pieces, the number of seniors isn't growing and these seniors also have
to train people and to continuously fix the mistakes that rookies did. It's
enough to say that it's turning into a nightmare.

~~~
collyw
And I bet management have no thoughts about giving you a pay rise....

~~~
bad_user
Heh, that's an interesting discussion - management never has any thoughts
about giving pay raises, you have to ask for it, sometimes brutally.

Developers should learn a bit about marketing, have a couple of valuable
things on GitHub, have a blog, have an up to date LinkedIn, etc... then you
end up being contacted by recruiters, which is cool for an ego boost and as a
safety net. It's then much easier to go in and say "Hey Bob, I'm producing
twice the value you expect for this salary, work conditions have changed, so I
want a significant pay raise".

And sometimes you have to threaten with resignation, which doesn't really work
in big companies, because there you have the "cog in the machine" mentality,
with developers often being the bottom of the food-chain. But in smaller
companies or when working as a consultant or in general when the "stock
holders" have good visibility in the value that you bring, it's a very
effective tactic.

It's also very healthy getting a pay raise especially when the stress levels
are going through the roof, as it keeps you sane, because what's worse than
being stressed about deadlines is being stressed while you're not being payed
enough, i.e. compensation is a hygienic issue and when working in unhygienic
conditions, there's nowhere to go but down. But you know, fortunately we live
in times in which the supply and demand ratio is favoring us :-)

------
BuckRogers
My list is a lot shorter than this screed. A bad programmer is one who is
passionless. No concern over how poor his work is, who doesn't want or care to
improve.

For me, defining a bad programmer is as simple as this.

~~~
prostoalex
If you're good and work for a reasonably large organization, you'll be thrown
into a bunch of projects. It's reasonable to be passionate for some and
completely dispassionate for others.

Any project that spans over multiple stages (requirements gathering, design
and architecture, coding, testing, release, bug fixing, maintenance, support)
has some exciting stages (mainly design and coding) and some less exciting,
especially when you're brought in to fix somebody else's bugs or work on
somebody else's mess. It's also reasonable to not be super-passionate about
such "opportunities".

------
mhomde
If anyone hasn't read it I highly recommend the book "Antipatterns"
([http://www.amazon.com/AntiPatterns-Refactoring-Software-
Arch...](http://www.amazon.com/AntiPatterns-Refactoring-Software-
Architectures-Projects/dp/0471197130=)

... or just google antipatterns.

My personal pet peeve is that many programmers don't refactor nearly often nor
thorougly enough. It should be natural part of the developing process.
Especially with large programs you reach certain points where all encompassing
refactoring is needed to simplify the code, yet many power through leading to
a bloated mess.

I've found its not uncommon that even decent complex code can be shrunk
70%-80% using refactoring, code generation and config files.

~~~
a3voices
Or you could just code correctly the first time...

~~~
mhomde
That's like writing a book "correctly" the first time without drafting (there
are a few authors that does that, but not many). Or drawing a picture without
sketching.

Much of the coding process is gaining knowledge of the problem you're trying
to solve and discovering patterns as you go along.

Also typically features are tacked on over time, and it reaches a point where
new patterns are needed that wasn't needed before.

I agree with you in some sense though, some patterns are low-cost and high-
reward in versatility & maintainability. Like using events rather than
explicit references, and you should use them from the start as a matter of
"good habits".

Some more overreaching patterns like factories, modules, plug-ins etc etc only
make sense when the code reaches a certain scope.

~~~
Spearchucker
William Deming famously said that when focus is on quality, quality rises and
costs fall. And that when focus is cost, costs rise and quality falls.

We live in a time where we're encouraged to make mistakes. Refactoring, fail
fast and often... I get the impression sometimes that we can go on failing
forever and its ok. Everything is awesome. Because its fun writing code right?
Just jumping in there and not giving a thought to the step after the next.
Managing complexity? JAGNI. My tests passed, didn't they? And we can always
refactor.

Getting it right takes discipline, research and experience. I prefer to get it
right first time. Doesn't always work out as planned, but to me the need to
refactor is a sign to stop and reassess what brought me to that point. And its
always a result of having cut a corner somewhere.

Refactoring costs. And upfront design is about as fashionable as leg warmers.

~~~
mhomde
I feel like we're talking about different things...

Continuous refactoring IS focusing on quality, it IS managing complexity. I
think you've seriously misunderstood Deming if you think he stood for "Do it
perfect from the start". The whole Kaizen philosophy is built on continuous
improvement and elimination of waste (redundant code)

I'm not saying do a week/month/year of crappy coding and then "fix it later".
Refactor continuously and as often as needed. Writing code is research.

The cost of refactoring is the greatest when you've done it too seldom.
Otherwise with the right tools it's pretty efficient these days.

I see larger dangers in doing up front architect astronauting and make
decisions before you've internalized all the problems.

For complex project it's of course appropriate to gather requirements,
limitations etc and make a _rough_ design, but going into too much detail is
setting the cart before the horse... IMHO of course.

~~~
Spearchucker
One of the coolest things I've learnt after over 20 years in this industry is
to seek first to understand, and then to be understood.

We're talking about the same thing.

------
kazinator
> _" Yo-Yo code" that converts a value into a different representation, then
> converts it back to where it started (eg: converting a decimal into a string
> and then back into a decimal, or padding a string and then trimming it)_

I would add: "you designed a language that does these conversions implicitly
as part of its evaluation semantics, and thought it was a marvellous idea."

------
lazaroclapp
5.3 is actually _not_ bad code, if it refers to what I think it does.
Basically:

"Recursive subroutines that concatenate/sum to [...] a carry-along output
variable"

Is an accumulator pattern, which is useful in converting certain types of
recursive algorithms into tail recursive algorithms with can be handled much
better by most compilers (and unrolled into iteration behind the scenes, which
means you get clean recursive code that still won't ever run out of stack
memory).

~~~
59nadir
Initially this was the reason and I still do this, but it should be noted that
Racket, for example, will treat the following examples exactly the same and
will do just fine with the non-tail recursive example (as far as I can tell):

    
    
        (define (sum/recursive/opt lst [sum 0])
          (if (null? lst)
              sum
              (sum/recursive/opt (rest lst)
                                 (+ sum (first lst)))))
    
        (define (sum/recursive/non-opt lst)
          (if (null? lst)
              0
              (+ (first lst)
                 (sum/recursive/non-opt (rest lst)))))
    

I don't use any other variants of Scheme with any meaningful frequency, but I
still use the uppermost variant because I'm just used to it.

------
logicallee
signs you're too good of a programmer -

you use monads in object-oriented languages (like Python)

instead of the standard library, you get your algorithms from PDF's you have
to pay a journal access fee for.

you believe in good test coverage: so do the ten thousand people who have
downloaded your test suite from github.

you leave comments highlighting incorrect behavior... by the standard
compiler.

you don't always formally verify that your program is optimal- sometimes you
only formally verify correctness.

you're a full-stack developer, but wrote some of the layers yourself.

investors want to meet the rest of the team

~~~
EdwardDiego
> signs you're too good of a programmer - > you use monads in object-oriented
> languages (like Python)

Are monads a natural fit to Python, or is this a case of "when all you've got
is a hammer"...?

~~~
lmm
Python borrows list comprehensions from Haskell, but the syntax is used in a
less powerful way. I wouldn't want to use non-builtin monads in a language
without a compile-time type system (one of the usual advantages of monads is
they save you a lot of effort testing, but this wouldn't be true in Python),
but there's no reason you couldn't.

(If you want an object-oriented language with proper monads then use Scala)

------
bootload
_" To get over this deficiency a programmer can practice by using the IDE's
own debugger as an aide,"_

sign of bad programmer: relying on the IDE?

    
    
      'always have a security professional review the 
       design and implementation.'
    

At first glance it reads like a list a hypothetical programmer should do,
rather than what happens. For a dose of reality, read this article by Joel
about the job of the SDETs at MS. [0] I don't hold MS as an example of
security but Joel paints a picture of serious programmers trying to code then
verify commercial software used by millions. [1]

Commerce and software demand another set of skills beyond this article. Read
the counter-point: 'What Makes a Good Programmer'
[http://www.southsearepublic.org/article/2024/read/what_makes...](http://www.southsearepublic.org/article/2024/read/what_makes_a_good_programmer/)

ps: Is there a way to prove the output of complex regular expressions?

[0] Joel Spolsky, 'Talk at Yale: Part 1 of 3',
[http://www.joelonsoftware.com/items/2007/12/03.html](http://www.joelonsoftware.com/items/2007/12/03.html)

[1] Then there's the open-source way. How many in the OS systems community
really have _' security professionals'_ review their code? OpenBSD and who
else?

(various edits)

~~~
jimmaswell
Using the tools available to you to their fullest extent, rather than doing
things the hard way on purpose just to be more "hardcore", is not a sign of a
bad programmer

~~~
woah
Definitely agree, however I can also see the shortcomings of the "IDE
languages". One of the nice things about non-auto-completable scripting
languages is that they force you to write code that you can reason about
yourself. IDEs let you write really inelegant code that you can still continue
to slog through because of autocomplete.

Another big downside of IDEs is that they constrain your choice of tooling to
only the IDE. There's a rich ecosystem of editors, preprocessors, templating,
etc. for JS, but (for example) in iOS development you only get xcode's half-
working gee-whiz features like the interface builder. In my experience, the
more IDE features there are, the more of your program moves into hidden, IDE-
specific automagical stuff.

So resistance that you may see to IDE's is not because someone wants to be
"hardcore", but because they recognize that it is desirable for code to be
able to stand on its own and be understood by a human no matter the editor
used.

~~~
jschwartzi
I especially hate IDE features that don't have a corresponding plaintext
representation that you can edit. For example, a graphical layout editor which
saves data into a binary blob that then requires a special merge tool which is
only available in the IDE.

------
alexbecker
> 1.4 "Yo-Yo code" that converts a value into a different representation, then
> converts it back to where it started (eg: converting a decimal into a string
> and then back into a decimal, or padding a string and then trimming it)

An important exception: many abstractions for data passing end up creating
exactly this, but are good practice if you can afford them because it means
one side of the yo-yo can be changed without breaking the other.

~~~
wernercd
Likewise, 1.5 "Bulldozer" aka breaking up a function into subfunctions that
aren't "useable everywhere".

I can't claim I'm the best programmer, but I've used this to "simplify"
programs and reduce nesting to great success.

Add to that Aspect Oriented Programming in C# by using Attributes to
add/remove logging to functions is easier if stuff is broking down into parts.

Subroutines shouldn't simply be about reuse. I think that narrows their
purpose too much. There is a place for code reuse. There is also a place for
functions that only get called from one location.

~~~
cheepin
> There is also a place for functions that only get called from one location

Do it inline. If you need it to look separate from the other context try an
immediately invoked function or at worst some comment demarcation. No need to
spray functionality across a file(s) when you can do it all inline, especially
if it is only called from one place. I'll admit I didn't come up with this
100% myself, but having tried both ways, I really like inlining.

[http://number-
none.com/blow/john_carmack_on_inlined_code.htm...](http://number-
none.com/blow/john_carmack_on_inlined_code.html)

~~~
wernercd
Looking at that, and considering A/B/C, I've seen myself using B most often -
but I've not been afraid to use any of those.

I'm not a fan of A, because I want to see the "bigger picture" first and then
dive into details (minor 1/2/3/...) as needed.

The reason for doing B vs C, in my experience with C#:

* Logging. I can add, via PostSharp ( [https://www.postsharp.net/features](https://www.postsharp.net/features) ) ( or similar extension/addons ) something as simple as `[LogDebug]` to a function and get logging goodness without having to mess with lines inside the code. PostSharp and Log4Net are my goto's.

* Simplification - Partially included above (no need for a lot of logging code with the right tools).

* Mental Gymnastics - its easier to see Step 1, 2, 3 when they are next to each other instead of pages apart.

* Scope - only the parts that get sent in via parameters are worried about, and only a single return is normally needed.

* Nesting - I've used minor functions to remove 3-4-5 levels of nesting before.

~~~
yoklov
Aside from logging (and games don't typically do a lot of logging), everything
you mention is covered, and argued against, in the article.

------
bikamonki
Neither the good programmer nor the bad programmer portrayed here would make a
good employee/consultant, the former b/c things will break while the latter
b/c things will never get delivered. They say software is eating the world and
I believe this is true but not b/c genius/geek programmers abound but b/c
there are hordes of smart good-enough 'programmers' out there putting good
enough solutions, and yes, most will not be able to write a recursive function
but who cares: the solutions run and solve real problems. That being said, we
must thank the gurus who put up the layers that make it posible for the makers
to bring out such solutions.

~~~
EdgarVerona
I agree. It is similar to that old phrase "perfect is the enemy of good."
Sometimes what an idea needs is something minimal that gets the product out
there and tested, shipping and selling in the real world. Sometimes the most
financially effective programming isn't elegant, but rather something quick
and dirty, transitory and ugly: something meant to be used and improved on or
discarded for something better if and when time allots for it in the future.

------
hello_there
> 5.1 You don't use any ergonomic model when designing user interfaces, nor do
> you have any interest in usability studies

Oops - _almost guilty_. Any suggested reading?

~~~
TeMPOraL
I'm guilty and somewhat afraid of going there because of what I see. Most
websites and web-apps are the _opposite_ of ergonomics and I sometimes wonder
if that isn't the result of the current state of UX field, that focuses on
shiny things that you can sell easily instead of building tools that work. The
trend I see in UX is that of dumbing-down your software and enforcing one,
carefully-drawn user flow, that is pretty but not ergonomic.

I don't want to demonize the entire field - it's just a worry I have, from
observation.

~~~
dropit_sphere
In my small amount of experience, reasoned application of Fitt's Law goes a
very long way for ui design.

------
kybernetyk
>Incompetence with Regular Expressions

Well, method acting here I come!

~~~
krapp
I hope "being able to use an online tool" counts as competence...

------
henrik_w
My take on the opposite - what makes a good programmer:
[http://henrikwarne.com/2014/06/30/what-makes-a-good-
programm...](http://henrikwarne.com/2014/06/30/what-makes-a-good-programmer/)

------
FLUX-YOU
These articles always make me feel insecure and for some reason I continue to
read them.

------
venomsnake
_6\. Distrust of code_

PHP/C++/Javascript

 _4\. Dysfunctional sense of causality

Symptoms

When called on to fix a bug in a deployed program, you try prayer Your
debugging repertoire includes rituals like shining your lucky golf ball,
twisting your wedding ring, and tapping the nodding-dog toy on your monitor.
And when the debugging doesn't work, you think it might be because you missed
one or didn't do them in the right order_

Once again php ...

So it seems I am a bad programmer after all.

------
SeanDav
My definition of a bad programmer is one who does not want to learn and
progress. Everything else is just levels of experience.

------
kpcyrd
> Credit card numbers or passwords that are stored in an unsalted hash

What's the purpose of _hashing_ a credit card number? For passwords, please
use a proper KDF instead of reinventing salted password hashing. While it's
widely known not to build your own crypto, most people still write stuff like
sha256(sha256(password) + salt).

------
restalis
A lot of comments here take it on a political level, even if the discussed
considerations are (mostly) technical. (I am personally touched by a few
points in there and I understand the temptation to go that way myself.) The
reasoning behind these "signs" however, is worth its weight in gold and I only
hope people will remember and come back to it with cooler heads. Critique (and
especially that kind performed on oneself) is almost always necessary in order
to get better, even if it hurts. Seeing the objections raised, I was tempted
to recommend such kind of critique only if there wouldn't be any chance of
breaking you, but I can't anymore. If you are to fail - fail early, fail
often.

------
kazinator
> _Using whatever syntax is necessary to break out of the model, then writing
> the remainder of the program in their familiar language 's style_

Depending what you're breaking out of and into, and what your work looks like,
this could be idiocy or genius. :)

------
turar
Previous discussions:

[https://news.ycombinator.com/item?id=3131439](https://news.ycombinator.com/item?id=3131439)

[https://news.ycombinator.com/item?id=746873](https://news.ycombinator.com/item?id=746873)

------
afarrell
Working with HTML/CSS has made me feel like I've got a Chronically poor
knowledge of the platform's features. In 6 years I've not been able to form a
coherent mental model of how it works that lets me actually go "oh, I need to
do Foo? I'll just do Bar and Baz."

Is this a sign that I should stick to working with scheme, Python, Go, JS and
other actually Turing-complete tools and my mind isn't made for layout
languages? (I have the same problem with Tex.) Or is there something I can
read that will finally help this make sense? Or do I just need another 4
years?

~~~
olavk
I think you should teach yourself the fundamentals of HTML and CSS. It is not
magic and its not even that complicated. But if you have worked in frontend
development for years, with frameworks, browsers specific workarounds and so
on, you tend to miss the forest for trees. If you can program, you can
definitely learn to understand layout languages.

The problem is perhaps that we are aware that programming is challenging,
while layout languages are considered "easy" so never really studied in depth.

~~~
afarrell
Right, that is what I'm getting at: How does one actually teach oneself the
fundamentals of HTML/CSS though? Off the top of my head, I know I've read
through

\- [http://learnlayout.com/](http://learnlayout.com/)

\-
[http://www.html5rocks.com/en/tutorials/internals/howbrowsers...](http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/)

\-
[http://htmldog.com/guides/html/beginner/](http://htmldog.com/guides/html/beginner/)

\-
[http://htmldog.com/guides/html/intermediate/](http://htmldog.com/guides/html/intermediate/)

And long ago did the same with w3cschools.

But it feels like the box model only accurately describes how browsers work
about 70% of the time. How do I learn to be able to predict at least 95%? I
have suspected that the right approach is actually to take 50 or so layouts
sketched on paper and do them. Is that actually reasonable?

------
mathgeek
"Using whatever syntax is necessary to break out of the model, then writing
the remainder of the program in their familiar language's style"

This one really rang home with me, having previously dealt with developers who
worked in both .Net and PHP with frameworks that handled models very
differently.

------
GhotiFish
What's up with 5.5?

>Your program produces output to be read by another (eg: a browser)

This is a problem?

~~~
jayrhynas
> Your program produces output to be read by another (eg: a browser), or
> implements a network protocol, and relies on the other party's software to
> be significantly tolerant to spec violations

The problem isn't producing output for another program, but relying on that
other problem to catch your mistakes

~~~
GhotiFish
Ah. I parsed that sentence incorrectly.

I read it like this:

> Your program produces output to be read by another (eg: a browser), or
> (implements a network protocol, and relies on the other party's software to
> be significantly tolerant to spec violations)

instead of like this:

> (Your program produces output to be read by another (eg: a browser), or
> implements a network protocol), and relies on the other party's software to
> be significantly tolerant to spec violations

------
jroseattle
There's a difference between being a bad programmer and bad programming.

------
Vektorweg
_Inability to comprehend pointers_

 _Inability to determine the order of program execution_

I don't think that pointers or mutable variables are important, when you are a
pure functional or logic programmer.

------
wz1000
I'm just nitpicking here, but

> Recursive functions that don't test for a base condition

Base conditions are not necessary in lazy languages.

Example in Haskell:

    
    
        fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

~~~
tome
Ah but that's not recursion, it's corecursion ;)

~~~
wz1000
You are right. I had heard of corecursion before but never thought of it in
this context. Thanks to your comment I feel like I have finally groked it :)

------
dollar
The author of this piece should not fret. Soon enough computers will program
themselves, and they will be vastly superior in this task to their human
counterparts. Perhaps then the author will bask in the glory of programming
perfection while waiting to be processed in the unemployment line.

Seriously, get over yourself. If the programmers you hire fail at their task,
blame your lack of leadership, mentor ship, or hiring skills. They can't all
be the A-team, can they? Learn to win with the B-team.

------
quipp
What does homebrew "business rule engines" mean? Are there a bunch of them
already made? What would be an example of this?

------
deevus
Call me overly sure of myself, but it is painful reading this since I can
relate a lot of it to my co-workers.

------
fffrad
A bad programmer is one that has worked for many years in the field and fails
to help those less experienced.

------
elementai
Still fun to read. Could anyone shed some light on author's background that
led to this piece?

------
odonnellryan
(eg: calling the save() function multiple times "just to be sure")

Who else does this for apps with a UI?

------
reitanqild
Bonus points for including remedies.

------
soccerstar
Symptom: fears that the AI will (in the near future) be writing programs for
us, so why bother...

Remedy: ?

------
Kiro
Ok, time to give up my career. I just realized that I'm a useless programmer.

------
DenisM
Surprisingly good. I got a good chuckle recognizing myself in some of these.

------
smtddr
_> >4\. Inability to comprehend pointers_

I love C, it's my favorite language.... but there is no way that pointers are
important enough that not knowing them == bad programmer. There are plenty of
good developers who've never even had to deal with pointers, even in 2012.

~~~
0942v8653
Well, it's necessary to the small extent that you need to know whether
something is passed by value or passed by reference. And in order to
understand that, you need to at least know what a pointer _is_. I don't think
it's fair to say that "plenty of good developers" haven't ever needed to think
about pointers. Maybe in newer languages they won't fall victim to a few of
those "symptoms", but they at least need to know what they are.

~~~
smtddr
Ah, so the pass-by-value vs pass-by-reference is a different topic IMHO than
int *x or &x. The implementation of both I'm sure are extremely similar if not
exactly the same, but I agree that if a developer doesn't understand pass-by-
value vs pass-by-reference then that's a serious problem.

I'm probably showing my age that I consider the pass-by-reference concept in
modern languages something that hides the concept of pointers rather than
something that indicates the understanding of them. Get off my lawn, etc.

------
jgwynn2901
These posts are ironic.

------
filannim
Fantastic!

------
curiously
yup...and this is why I stopped. because of this kind of tone that I found
toxic in actual job settings but then again it's points are fairly valid to
filter only the strongest programmers.

Tell engineers to come up with their expected salary in a room and they will
fight and compete with each other to work for free. The rationale ones, or the
'bad' engineers seemingly walk out because they still have the sanity intact.

Interestingly enough, companies and employers know this about engineers, and
would be more than happy to screw you over what you actually deserve. All they
have to do is sit aside and watch the professionals sabatoge each other. They
are the perfect employee. Fire them once they build the pyramid, and find
slaves overseas to maintain it.

This is what I realized at the end of the day. All I care is that I turning
ideas into real products that work. If these are product that I can sell on my
own, even better. If my skill and experience allows me to do this over and
over, then it is good enough of a skill for me. Might not be a 10x engineer
but neither do I want to be involved in a gladiator matches anytime we have to
build something but end up arguing over irrelevant things, and end up
delivering late.

~~~
EdgarVerona
Yes, that is the worst part to me. I worked at a place once, many years ago,
where a Lead software engineer came in and started what I could only equate to
a turf war. He'd set people up to get them fired, call competent engineers who
made a mistake out as being idiots, etc.

One time, he assigned me work - and never mentioned that someone on another
team had been assigned the exact same work. He wanted to see me do it faster
than the other guy so that he could fire the other guy. So when I completed
it, and he used it as ammunition against the other guy (even though the other
guy had done a perfectly good job it turned out). I stood there helpless and
ashamed that I'd been used as a weapon for someone to tear another good
programmer down.

A couple of months later, the company began to lay people off and that lead
bolted for the door. I did too, but I was just glad to not have to work in
such a hostile environment anymore. So much anxiety.

~~~
curiously
That is revolting. I hear a lot of nightmare stories like this. Unfortunately,
I think as engineers, we are forever doomed to be treated like peasants,
unless you know how to play politics, kiss ass, and move up into a manager
position.

The concept of manager seems so old fashioned and backwards especially when we
are now dealing with a manufacturing industry that produces nothing physical,
where the concept of a product is actually just a vote of minds of all the
stakeholders, engineers, customers. Having traditional managerial that were
suitable for overseeing factories and suppress workers from rioting and
maximizing labor output in an information based product is nothing short of
censorship.

My idea of a dream team of software engineers is one where we have as little
technical and business censorship as possible. It would be sort of like how
day trading desks operate but we end up building one product that reflects the
demands of the customers, the future market. Instead of having a manager
telling you what to do or what to build, you act on information from a
customer directly. This might be a tougher hybrid to find but I reckon we'll
see more and more entreprengineers as traditional manufacturing corporate
structures lose their appeal.

Wishful thinking but I hope some people share the same ideas and values.

------
benihana
> _" 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)_

> _3\. Difficulty writing functions with low cohesion_

Is there some definition of cohesion I don't know, or is the author confusing
cohesion and coupling?

~~~
kornish
From Wikipedia: "In computer programming, cohesion refers to the degree to
which the elements of a module belong together.[1]", where [1] is Yourdon &
Constantine 1979.

It appears that author uses cohesion and coupling - and rightly so, by the
above definition - as synonyms.

~~~
Silhouette
Cohesion and coupling certainly are not synonyms.

Cohesion is about how much the code within a _single_ module deals with the
same or closely related concerns, so that behaviour "belongs together". High
cohesion is usually considered desirable.

Coupling is about how much _multiple_ modules depend on each other. For
example, do they communicate only via a clearly defined interface, or do they
have implicit dependencies like sharing memory or resources? Loose (i.e., low)
coupling is usually considered desirable.

------
hnprogfail
Point number 9: "using HN for programming advice or guidance" \- relying on HN
with it's fixation on the latest shiny (are we still hyping Go and React
today?) and it's endless pursuit of academically useless tools (big shout to
Haskell, any meta language built upon yet another interpreted and JITd
language).

~~~
mrits
Why would you say Haskell is academically useless?

~~~
atarian
Why would you respond to a troll?

~~~
hnprogfail
They were willing to debate my statements, it seems you prefer to throw labels
around in place of a single argument or rebuttal.

~~~
TeMPOraL
You're saying things that are not even wrong, from an account created one hour
ago with a name clearly tied to the topic. I'd say obvious troll is obvious.

~~~
Vektorweg
A troll you can argue with isn't a troll. Its just too easy to exclude people
because of there non-conformism ...

------
jkot
> _Using cut-n-paste code from someone else 's program to deal with I/O and
> Monads_

> _Failure to implement a linked list, or write code that inserts /deletes
> nodes from linked list or tree without losing data_

> _Difficulty seeing through recursion_

I would argue that using monads, implementing your own linked list or using
recursion is sign of bad programming... But I am just Java cowboy, so thanks
for the enlightenment!

~~~
cbd1984
> implementing your own linked list or using recursion

I believe I can salvage this piece of the comment, and make it into an
intelligent thing to say.

Implementing your own linked lists? Not good unless your language is stone-
knives-and-bear-skins land. You need to know what libraries are out there and
available to you, and if CS undergrad stuff is unknown to the libraries in
your language, pick a different one if you possibly can.

Recursion is an important skill, but implementing your own recursive functions
is low-level. It's error-prone and it's boring in precisely the ways that
cause errors.

Implementing your own map function is worse than implementing your own linked
lists; it's more like implementing your own while loops out of labels and goto
statements. It's an invitation to have bugs in your program's flow control,
which is the worst possible place for them to be.

Sometimes you need to write your own recursive function, because none of the
basic recursive patterns your libraries give you can fit. Sometimes you need
to implement your own foundational data structures, too. Both of these should
be done with skepticism, primarily of your own code, but also of the very idea
that you'd actually _need_ to do it in the first place.

