
Signs that you're a bad programmer - clawrencewenham
http://sites.google.com/site/yacoset/Home/signs-that-you-re-a-bad-programmer
======
scottdw2
I have to say, I really didn't like the document much. Not because of
substance. Some of what he says is true.

On style, though, I think the document is trash. Some of what I say is
probably even a bit ad hominem.

Most of the good programmers I know don't spend time worrying about bad
programmers. They just write good code and cleanup bad code when they see it.

If someone feels compelled to write up an essay about bad programmers, he
probably spends a lot of time dealing with bad programmers.

That experience should lead to humility, not arrogance. If you deal with a lot
of bad programmers, you might not be as good as you think you are. After all,
you work at the same place on the same project as a bunch of bad programmers.
They where hired under the same standards as you.

To me, the document just seemed like arrogant posturing. An attempt at
crafting a "negative identity" (define a group by vilifying the outsider). The
best way to "be", and to be recognized as, a good programmer is to write good
code. All the other stuff is just horse shit.

~~~
axod
>> "They where hired under the same standards as you."

The problem is though the hiring process for programmers is often completely
broken. Measuring good programmers is also broken in many companies, so bad
programmers tend to just stay there instead of improving, or being fired.

I think being a good programmer isn't too hard if you have the talent, taste,
time etc. Being _recognized_ as a good programmer, and rewarded as such is
harder.

~~~
timwiseman
Excellent point. Another to add to the list is that you may easily have been
hired under a higher standard as the team lead or "working/programming
manager".

I have been fortunate to never work with a bad programmer, but I have worked
with inexperienced programmers that were learning as they went. I was not
hired under the same standard or for the same reason they were.

------
nbroyal
Google cache for those who hit the "pageview limit exceeded" nonsense:

[http://www.google.com/url?sa=t&source=web&ct=clnk...](http://www.google.com/url?sa=t&source=web&ct=clnk&cd=1&url=http%3A%2F%2F74.125.155.132%2Fsearch%3Fq%3Dcache%3AA7_WaV28LBcJ%3Asites.google.com%2Fsite%2Fyacoset%2FHome%2Fsigns-
that-you-re-a-bad-
programmer%2Bhttp%3A%2F%2Fsites.google.com%2Fsite%2Fyacoset%2FHome%2Fsigns-
that-you-re-a-bad-
programmer%26cd%3D1%26hl%3Den%26ct%3Dclnk%26gl%3Dus&ei=G6p7Spq1CovYsgPg8KXvCg&rct=j&q=http%3A%2F%2Fsites.google.com%2Fsite%2Fyacoset%2FHome%2Fsigns-
that-you-re-a-bad-programmer&usg=AFQjCNHJJZpSR-zgzZoC-dz6oeOChaPpqA)

~~~
drusenko
wow, that's completely ridiculous.

searching through their help center, they won't even tell you what the limit
is, but it seems to be pretty low. just. wow.

~~~
davidw
Reminiscent of Geocities, isn't it.

------
sophacles
Oh man, I wish I had this at my last job half the team had over 50% of these
symptoms, one guy had 90%. They believed, and had somehow convinced
management, that they were great programmers! Some awesome practical examples
from those guys below:

Overheard statement "You know when I was in college I learned C. I just can't
get the hang of these objects, so I try to avoid them". The guy who said this
is now 34, and has programmed python for 4 years.

A guy who would copy and paste 100 line blocks of code, and then occasionally
thing "oh yeah, i need functions", and then finish out the current function by
passing 12 parameters of state to current_function_2(). If you combined the
func, func_2 and factored out the 100 line blocks it would be reverted with a
commit: "stop making this so complicated".

There was one guy who insisted that using templates was only for web
frameworks, to use them to write system/config files (done frequently due to
3rd party daemon limitations) was an abuse of the templating system, and we
should just use inline prints. The program was to be called with prog >
/etc/conffile.

One guy who decided that threads were so tricky, that he was the arbiter of
thier use. My idea of a job queue and worker threads was "too abstract and
hard to debug", so we stuck with the "tried and true" one thread per job
method, all spawned at once.

I could go on, but you're all prolly bored now :)

tl;dr: i worked with the guys the article was written about

~~~
jacquesm
ouch... I love the 'stop making this so complicated bit'.

While some people really don't get it I'm pretty sure that most people could
learn how to program with some competence.

The only metric I've found to measure programmer competence reliably is how
big a project you can manage to complete. Some people get stuck at around 100
lines, others in the thousands or tens of thousands, some can keep their
rudder straight across 100's of thousands of lines.

The latter takes extreme self discipline and organization.

~~~
blasdel
LOC is a horrible metric for this, given the degree to which morons can get
comfortable with copy-paste and IDE-generated boilerplate.

Gzip-bytes of source FTW.

~~~
nostrademons
"you can manage to _complete_ "

Implicit in the notion of completing a project is the certainty that the
project manager will change their mind, usually after you have written 95% of
it. If you copied & pasted those hundred thousand lines, you will have to
change something in at least 100 different places. At that point, you'll give
up in despair, proclaim the change impossible, and have the PM cancel the
project in a fit of frustration. Thus, not complete.

LOC actually sorta makes sense in this context.

------
JMostert
Funny that he has this under "Signs that you shouldn't be a programmer": "you
think the presence of code in a program will affect its runtime behavior, even
if it is never invoked".

Anyone who has written code in C can probably cite an anecdote where exactly
this was the case, be it from a compiler bug or as fallout from a memory
corruption bug.

Maybe we should add "does not understand the von Neumann architecture" to the
list of signs that you're a mediocre programmer... On second thought, let's
not -- the piece is bad enough to begin with. The "alternative careers"
sections are just odious, and the whole thing breathes an air of
inconstructiveness.

~~~
ewjordan
This happens in JVM languages as well. Most optimizing compilers will do
things differently depending on what happens elsewhere in a function, even if
it's "dead code" (and _especially_ if it's dead code that the compiler is too
stupid to _realize_ is dead).

Granted this _usually_ only affects runtime speed, but in some circumstances
things can get worse (multithreaded programs are particularly susceptible to
such optimizations, especially if they're not written correctly - yes, the
_real_ problem may be that you've written your code wrong, but there are very
real situations where the presence of dead code can change the optimization
path taken enough so that it either works or doesn't, which is a very real
effect).

And that's even _before_ we take into account compiler bugs, which just make
things worse.

------
sriramk
Here's a flaw which I've seen in several otherwise _good_ programmers -
forgetting that sometimes the core purpose of code is to be read and
maintained by other human beings. Some of those other human beings may not
have had the time to catch up on the latest/greatest language feature or
'trick' and may miss subtleties of your implementation.

I get worried when I see someone take a mainstream language (C#, Java, Python)
and try and twist its idioms into whatever their favorite language is (lisp,
the ML family, Perl, etc). Or if someone wants to be on the bleeding edge and
use the latest language syntax/library trick. This is a pain because

\- Someone new to the codebase may not have as much familiarity with all these
nuances of the language. For example, I've seen crazy things done with C++
templates. I don't think there was ever a justifiable reason for doing any of
them.

\- The esoteric, cutting edge features often have bugs and/or don't have great
tool support. Fact of life is that the more some feature gets used, the more
the bugs found and fixed. If you're on the bleeding edge, you're going to hit
weird language/runtime bugs which you need not have inflicted on everyone.

\- Debugging. Often, the only thing you have after a weird bug is a crash dump
and caffeine. You want to give yourself all the chances you can of tracking
down that issue. Esoteric language features rarely lead themselves to great
crash dump debugging. I'm not suggesting writing C code but the closer the
mapping from code you write to x86/64 code, the easier it is for you

~~~
jongraehl
Sometimes use of advanced facilities is a way of elevating your status over
the uninitiated. Now that you've shown weakness, I'm really going to pour it
on!

------
cturner
I'm skeptical of these lists because people can work through things. For
example, the stuff listed under "Inability to determine the order of program
execution" is something that many people will get jammed on eary on as they
try to take their brains (which is honed on the syntax of school level maths)
into the programing world (where equals is an instruction rather than an
assumptions). Another one is "Lisp is opaque to you". It's very sweet for MIT
types to make these declarations from mount olympus, but lisp is something
that can take time to acquire. If someone isn't a natural programmer but is
happy to work at it to overcome hurdles then there's nothing wrong with that.

One of the examples of bad technique is:

    
    
        Homebrew "Business Rule Engines"
    

Can anyone give examples of the sorts of things the author means by this? What
sort of systems have people seen, and why is it necessarily a bad thing?

~~~
ardit33
"It's very sweet for MIT types to make these declarations from mount olympus,
but lisp is something that can take time to acquire."

Don't worry. In the Valley, people from MIT don't have a good reputation as
great programmers. For some reason, their education is a lot of 'theory' and
less practice.

Apart from Standford\Caltech, Some of the best schools that produce great
programmers are your average state school.

I have a theory behind this, which may be correct. Learning to be a great
programmer takes years, and school is just the start. People that do well
enough go to something like MIT, think they are already very smart, and don't
try hard when they come out.

But if you are hungry, and smart, and just happen to go to your average state
school, you probably will do better, as you probably are humbler to begin
with.

It seems when the rubber meets the street, in startups, building products,
that's where the great programmers are made, and lisp is not a requirement to
know to be a great programmer, or actually build great products. Having an
idea of what functional languages are is a must, knowing them is not.

~~~
carterschonwald
nope not the case, I know a bunch of people at these various schools, and the
crux of the problem is that theres a huge culture at MIT (and moreso than many
peer schools) of celebrating herculean last minute efforts that get the grade.
This is great for experimental hacking on a weekend, and "good enough" for
research, but it does not encourage an incremental design sensibility, owing
to its last minute nature.

This is not to say that any of these people are bad at what they do, they just
have bad habits that they need to walk off, but first someone needs to tell
them!

~~~
rdouble
_the crux of the problem is that theres a huge culture at MIT (and moreso than
many peer schools) of celebrating herculean last minute efforts that get the
grade_

That's a very astute observation. I work and have worked with many MIT people,
and even TA'd an MIT course. The "all nighter" hazing ritual culture was very
prevalent. To this day, my friends who went to MIT prefer to work 24 hour
shifts, late nights, and on weekends - even though they've been out of school
for a decade. In addition, MIT had a culture of boot-camp style negative
reinforcement. "You suck, are not smart enough and are lazy, work harder" was
the driving attitude. (at least it was in the late 1990s)

In contrast, when I moved to the west coast, all the Stanford people I met
were more about basking in their obvious awesomeness and mastering time
management. Get the project done early, schedule everything around ultimate
frisbee team and rock climbing club, go to the outdoor concert on Friday night
and still make it up to Tahoe for the weekend.

------
tjmc
I love the insight that lacking critical thinking "originates in both lazy
thinking and egocentric thinking". The latter is very true. I have never met a
great programmer who thinks they are at the top of their game. Being aware of
the trade offs in any solution requires a degree of humility.

------
gojomo
Signs that you're a bad web host: "pageview limit exceeded"

If Google can't figure out a way to monetize popular content targeted at a
professional technical audience, something's very wrong.

The best idea I've seen for such situations is to let people trying to view
the page buy an instant traffic upgrade on the site's behalf; I'd chip in 100x
the costs to serve my single hit if I knew it would restore visibility for me
and some others.

The help link is also uncharacteristically inept for Google -- it doesn't lead
to an explanation of pageview limits, and searching [pageview limit exceeded]
in the help area turns up only user questions, no official article on the
topic. The third hit is this unanswered gem, from a popular site _with
AdSense_ that keeps going down due to the limits:

[http://www.google.com/support/forum/p/sites/thread?tid=08f19...](http://www.google.com/support/forum/p/sites/thread?tid=08f19dca3ab69764&hl=en)

------
wglb
This is a very good article, and hits lots of very good points.

However, it seems that there is a little bit of a self-diagnosis problem. For
example, if you write "voodo code" (great description), unless there is some
one to tell you, how do you know? And if you write voodo code, do you know
what idempotent means? There is maybe a bit of the "Blub" effect here.

Perhaps between "Symptoms" and "Remedies" there needs to be "Diagnosis" or
some hints at self-evaluation or tools for self-assessment.

------
blasdel
This is absolutely amazing and comprehensive! I can't think of anything he
really left out.

I've seen articles like this before, but they're usually super-parochial, and
I've never seen one that offered 'remedies' (much less the hilarious
'alternative careers' in the last section).

------
dkersten
Signs that you're a bad programmer: 1) You think you're an amazing programmer.

------
mfukar
Just reading that made me a bad programmer. :/

------
rw
Pageview limit exceeded

We are sorry, but this site has exceeded its page view limit at this time.
Please try again later. For more information, see Google Sites help.

~~~
mshafrir
Does anyone have a mirror for this page?

------
elai
He's missing the third part, signs your a decent programmer, to differentiate
the good from the great.

~~~
blasdel
That's ridiculously difficult to do at all, much less in pithy universal
checklist form.

~~~
sophacles
For starters howabout: 1\. you read the bad list and thought "oh crap!" 2\.
the oh crap is no longer a problem for you, but remembering the code with that
problem makes you wince.

------
jongraehl
That was mostly high quality except for the wannabe "you might be a redneck"
(shouldn't be a programmer) section at the end.

> (Functional) Manually caching the results of a deterministic function on ...
> Haskell

You still have to explicitly memoize at times in Haskell.

> refactor his old code with the goal of reducing its instruction count by
> 10:1 or more

What a loser! I go into my old code with a goal of 10000:1.

> Recursive subroutines that concatenate/sum to a carry-along output variable

This can be justified.

> Using strings/integers for values that have (or could be given) more
> appropriate wrapper types in a strongly-typed language

Not always worth it.

> Unit Testing, which you use at design time.

No, I don't.

> You don't use whitespace or indentation

If I'm not using whitespace, what am I supposed to indent with?

------
russell
Seems to be a good source for creating interview questions.

------
ivank
It's down, but it sounds like a copy of <http://badprogrammer.infogami.com/>

~~~
clawrencewenham
Just moved it to another host. Not like Google was any better >:|

~~~
sjf
I noticed when one of your articles was posted to reddit that there was no
signature on it, it's nice to know who is behind them. Do you think you will
ever publish these in book form? Your tips are blindingly accurate, it could
definitely be a Code Complete III, updated to include functional and
declarative programming.

------
jonke
"Phase 5: "By letting a constraint solver figure out the mundane details, I
can write programs by describing what I want, rather than how to give it to
me""

This is one of the best arguments for why anyone should bother to learn
Haskell (or likewise language)

------
tuukkah
1\. (Haskell) Propagating the myth that Haskell would do some automagic
caching of function results.

(Haskell simply does call-by-need: square (x+1) evaluates to (x+1)*(x+1), but
there's still only one (x+1) that gets evaluated.)

------
olliesaunders
Some praise for this article: Identifying a set of patterns for sub-quality
programming practise is useful in order to set about correcting those things
esp. if you're in a mentoring position. I think it would have been nice to
have given these names (like design patterns perhaps) and fleshed out their
definitions further.

Yes, the author is more arrogant than desirable in his delivery but don't let
that blind you to the good stuff. Some of the teaching analogies, in
particular, I thought were good.

------
NoHandle
High cohesion is bad in exactly which programming environment? Functional or
procedural?

I've always understood high cohesion to be related to low coupling. Also,
writing util classes before you need them (where low cohesion may be
necessary) is a nothing more than a time sink. Do something when you need it,
not before. You are not omniscient and will not be able to account for
everything no matter how hard you try.

------
aschobel
FTA: "Signs that you shouldn't be a programmer

1\. Inability to determine the order of program execution

Symptoms

a = 5 b = 10 a = b

print a You look at the code above and aren't sure what number gets printed
out at the end"

The answer is not always obvious. If the above code were in Java and print a
was running in a different thread then it very well print 0, since a or b
could be 0. JMM can really bite you if you don't understand within-thread as-
if-serial semantics.

~~~
olliesaunders
That's a pretty extreme case don't you think? You're certainly playing devil's
advocate here. We all know what the author meant by this.

------
jcapote
This is spot on:

    
    
       5. Lisp is opaque to you

~~~
rjurney
I can't learn LISP. I can get reasonable work done in imperative functional/OO
languages like Perl, C, Java, etc. and took the time to learn Erlang to get a
look at functional programming and I can drop the SQL bomb like nothing else
(so I can do declarative too) but every time I've sat down to learn LISP
because people say it will make me a better programmer, I've gotten distracted
and haven't finished.

I don't think this makes me stupid, or a bad programmer. I think it means I
have different tastes and limited time. Learning LISP feels like learning
assembly: a great exercise, but there are other things I'm more interested in
doing - like building things I enjoy with my limited free time.

That being said, maybe I am stupid, or a bad programmer. I don't think not
being into LISP means this is the case. I like building things people use,
more than I like writing elegant code for code's sake.

~~~
derefr
I don't think Lisp being _opaque_ has anything to do with your ability to
learn a particular PL such as Common Lisp, Scheme, Arc or Clojure. Rather,
opacity is usually a term levied at a _syntax_ , when it makes it hard to
understand what the underlying semantics of the program are. Lisp has the
least "syntax" of any programming language I know of, so if it's opaque to you
(e.g., you can't take a guess at what "(+ 2 3)" means), you probably shouldn't
be programming.

~~~
copenja
I don't understand the following point you made:

"so if it's opaque to you...,you probably shouldn't be programming"

So your saying that someone should not program if they haven't learned basic
lisp ( 5 )?

Or are you suggesting that there should be some time limit... like if you
program for X months but don't understand it you are forced to quit.

But.. further... What is the purpose of forcing these people to quit?

And.. What is the purpose of belittling these people?

~~~
derefr
I'm not talking about _learning_ programming. The reference in the article was
to people that already _were_ programmers.

To put it another way: if you _call_ yourself a programmer, and _sell your
skills_ as a programmer, but can't mentally decompose "(+ 2 3)" into an AST
(basically the first, and easiest, step to understanding), _even after Lisp's
general syntax is explained to you_ , then you _aren't_ actually a programmer.

~~~
copenja
Above, you said whether they could guess it, not whether they could understand
it after explained.

"you can't take a guess at what "(+ 2 3)" means"

I can see your meaning if it was explained to someone and they still didn't
grok it. But I would still kinda feel like encouraging them.

------
brown9-2
I'd been looking for a name for what the author terms "yo-yo" code. I've often
wondered if others have to deal with such head scratchers too.

------
tholex
Great doc to make screeners with.

------
ardit33
After reading it twice, there are many points that are good, but there also
some points that are not so clear cut, or plain bad. Maybe I am a bad
programmer, but I disagree with some points:

# (OOP) Writing lots of "xxxxxManager" classes that contain all of the methods
for manipulating the fields of objects that have little or no methods of their
own

I guess they keyword 'lots' make this ok, but having plain objects (scruct
like), passed around in the application, and having some managers is fine. eg.
if you have an application that passes around contacts, you can have a
ContactsManager, taking care of all the messy bussines (local peristence,
remote persitence, deleting, etc., while contacts remain simple objects.
ActiveRecord pattern goes the other way, where this logic is placed in the
objects. Both are fine.

# (Relational) Treating a relational database as an object store and
performing all joins and relation enforcement in client code

\--I guess all those programmers in the "NOSql" movements are idiots. (they
are not, some of these people are really smart). Don't take this statement too
seriously.

# Re-inventing or laboring without basic mechanisms that are built-into the
language, such as events-and-handlers or regular expressions

\--I think regular expressions are evil, obscure, and performance is highly
depended on the implementation. Practical example, checking if an email
address is valid. While some people go all the way crazy with regular
expression, All I do is check that there is an '@', or a '+', at least one
'.', and minimum/maximum lengths. You don't regular expressions for that, as
no matter how smart you think your expression is, there is a great chance
somebody that edits it will fuck it up just by changing a character on it.

# Re-inventing classes and functions that are built-into the framework (eg:
timers, collections, sorting and searching algorithms) *

Done many times. If you are doing mobile, most of platform implementation (at
least in J2ME) just suck ass. You can't rely on them. Heck, in my previous
company we did even font rendering, thread worker queues, etc. as the
scheduler was unreliable, etc.

#Recursive subroutines that concatenate/sum to a global variable or a carry-
along output variable

\--For some problems carry-along variable are needed.

eg, in a binary search tree, trying to print only the nodes in a certain
level. printTreeLevel(tree, 2) -- will print only the nodes at level two

print(node, level)

    
    
      if level == 0
    
         print node.data
    
      else
    
         printTreeLevel(node.left, level - 1)
    
         printTreeLevel(node.right, level - 1)
    
      
    

# Writing business-logic functions with tragically compromising side-effects,
such as updating a user interface or performing file I/O

\--I guess it depends on the definition of what "business-logic" is. This guy
thinks it more as the transactional/model part and not a controller. For some
apps, the business logic is the main controller. Plus, "bussines logic" is
more of a managerial speak anyways.

#Homebrew "Business Rule Engines"

\-- Maybe I am not old enough, but I had to look it up what a "Business Rule
Engine" is. Seems stuff from the Dot Com era/enterprise world.

#Code that tries to prevent an exploit from working by searching for the
exploit's signature

\--Haha. That's the whole Antivirus industry. I agree with him, and I don't
have antivirus software, but it seems that those companies made millions by
breaking this rule.

~~~
mgreenbe

      Recursive subroutines that concatenate/sum to a global 
      variable or a carry-along output variable
    

Wow...I didn't see this in the article. That is downright boneheaded. Is
accumulator-passing style forbidden for a reason? It's a cheap way to make
functions tail-recursive---much cheaper than CPS!

~~~
clawrencewenham
I'm still looking for a good way to express what was meant by that symptom
description.

You know about tail recursion, but I'm trying to get at the uses of
accumulators that have nothing to do with tail recursion.

That and I got fed up with listing all of the exceptions to every rule.

------
321abc
The author lists the following as a symptom of being "unable to reason about
code":

 _"5. '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 disagree with this. The purpose of breaking out code in to subroutines isn't
only for code reuse. If you don't break out code in to subroutines, at some
point your code is going to become unwieldy and difficult to read.

I try to stick to the rule of having each subroutine consist of no more than a
page of code (so that each subroutine can be seen all at one time, without
needing to scroll). Often that leads me to break up the subroutine in to many
other subroutines. This improves readability greatly and makes it much easier
to reason about the code. If any of the subroutines I break my code out in to
happen to be reusable, that's just icing on the cake, not a necessity.

~~~
dionidium
Sometimes the (seemingly) simple act of trying to come up with a name for a
subroutine helps me reason about what it is I'm trying to do (whether the
chunk is re-usable or not).

~~~
kevindication
I don't know if you've tried this, but if you write down some pseudocode
before you really get started, the logical chunks of the program will take
their names straight from the pseudocode.

~~~
jamesbritt
Or do comment-driven development: write the comments for the method first,
then convert the (hopefully!) plain English into code, ideally so that no
comment is needed.

------
torpor
How to avoid (if you're a C programmer) writing utterly terrible code - always
include these WARNINGS in your build step:

WARNINGS := -Wall -W -Wunused-parameter -Wmissing-declarations

WARNINGS += -Wstrict-prototypes -Wmissing-prototypes -Wsign-compare

WARNINGS += -Wconversion -Wshadow -Wcast-align -Wparentheses

WARNINGS += -Wsequence-point -Wdeclaration-after-statement -Wundef

WARNINGS += -Wpointer-arith -Wnested-externs -Wredundant-decls

WARNINGS += -Werror -Wdisabled-optimization -pedantic

CFLAGS += $(WARNINGS)

Note: -pedantic is pretty good if you really wanna learn how to write code
that will work properly.

Also: Treating Warnings as Errors is a good thing. You'll learn a lot, and the
most important thing will be: handle all warnings. Do not release code until
it builds clean.

~~~
sfk
Good advice, but compilers often issue warnings like "x may be used
uninitialized" even when it cannot happen.

~~~
torpor
Erm, wut? Not really. If there is a warning, its there for a reason. Fix that.

~~~
sfk
As everyone who has written a C program of sufficient complexity knows, these
warnings are _not_ always correct. Google for "spurious warnings
uninitialized", e.g:

<http://kerneltrap.org/node/6591>

An unrelated example where gcc (and icc) emit needless warnings about integer
types is this:

    
    
      int x = foo();
      unsigned y = (x == 0);
    
    

Don't get me wrong, I'm in favor of cranking up the warning levels, but there
is a reason why not everything is included in -Wall (yes, "uninitialized" is
included, I know).

~~~
torpor
As a professional C coder for 20+ years, with well over a million lines of
code under my belt, I can tell you that anyone that is ignoring warnings
because of a buggy compiler is _using the wrong compiler and should fix that
immediately_.

I work on SIL-4 rated systems for life-protection applications. Absolutely
_ZERO TOLERANCE_ for warnings is a requirement in this job, and every single
time it has been addressed, the warning gave us a clue how to fix something.
Whether it was the code that needed fixing, or the compiler - either way, the
alert is there. Ignore at your own peril.

------
polos
Oh, you can put it as simple as:

If you think you are good, you are not. If you think you have to improve,
chances are you will become _better_.

(Life is baby steps; ask a baby...)

