Want to be an excellent skeptic? Learn computer programming

Next week's lesson: Proving that all horses have an infinite number of legs

How To Logic

I don’t go into a lot of detail about my work on the show, because it doesn’t necessarily interest everyone. But I do occasionally mention that I’m a software engineer, and work it into my discussions here and there. I had to take a break from the show for a year or so while I finished my Master’s Degree at UT in 2008. I have a second blog for writing thoughts about my profession; it’s called Castles of Air.

Occasionally people ask a question like the following: “I like your show. I’m a young skeptical atheist and I’m trying to decide what to do with my life. What should I study in school?” Some common answers are: Go into science. You will learn how to study the world in a naturalistic way and be better equipped to answer questions without resorting to supernatural answers. Or: Try politics. You can work to reinforce separation of church and state, and use your influence to advance causes you care about. Or: How about religious studies? You can get a real handle on how major world religions developed, and promote skepticism from the inside.

Those are all good answers, but I’d like to take a minute to speak in praise of the career track I picked.

First I’m going to toss in the most obvious practical recommendation: Programmers get jobs. The world is increasingly driven by the interaction between computers and people, as well as interaction between computers and each other to streamline tasks that make things easier for people. In some sense this has contributed to a difficult economic environment, because the more labor that is automated by sophisticated machines, the less of that is available for good paying human jobs. That’s an issue that I feel concerned about, but at the same time it means that some of the best opportunities are available to people who understand how computers work. That’s an economic fact that’s not going away any time soon.

A recent article in US News and World Report drives this point home, although you can find similar results from many, many studies released in recent years. This article ranked the best jobs of 2014 in terms of factors like salary, work availability, stress level, and growth. The number one job was “Software Developer.” Number two was “Computer Systems Analyst.” Number 9 was “Web developer.” This brings the number of computer related jobs to three out of the top ten.

Beyond that, there are some specific reasons I have for saying that computer programming is specifically a good tool to learn skepticism critical thinking. James “The Amazing” Randi has often said things like this:

A magician will instantly see the truth behind any colleague’s illusion. But we have a bit of an advantage: We know we are being fooled. Scientists are instinctive doubters who employ a rigorous method to zero in on the truth, but they aren’t necessarily trained to expect deception by subjects and collaborators.

Programmers are trained to expect deception. We have no choice, because computers and computer users lie their asses off on a regular basis. When you write a program, you have an idea in your head how it should behave under normal circumstances. But in the first place, the program never works the way you expect. And in the second place, “normal circumstances” are the least likely situation you will ever encounter.

Maurice V. Wilkes, credited in some places as the inventor of microprogramming, had this to say about his work:

As soon as we started programming, we found to our surprise that it wasn’t as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.

In some ways, debugging a program is a lot like being a detective. Often you run a program you wrote, only to discover that something has gone wrong. You don’t know what, you don’t know where, and you don’t know why. So you start narrowing it down: you think through the structure of the code, you isolate and identify pieces of it that are definitely working correctly, and gradually you rule out various possibilities until you can pinpoint the part that is broken, or poorly written.

Even when you have done this correctly, you’ll still wind up releasing a program that is eventually going to be used by other people. End users don’t always do what you want. They enter words when you asked for number inputs. They invent fake names and addresses. They set up impossible situations.

So the other part of your job as a programmer is to look at the problem from all possible angles and figure out all the possible ways that people will break your program, before they do it to you. Murphy’s Law — “Anything that can go wrong, will” — applies to computer programming in spades; therefore, you constantly have to be figuring out how to set up situations where nothing can go wrong.

I believe that being in this habit, and practicing the techniques of robust software development, can help train your mind to look for logical fallacies, inconsistencies, and logical consequences of situations you encounter often in your day to day life. Computer programming is certainly not the only way to develop these habits, but I find it a fun way to get there.


  1. Narf says

    I remember you mentioning something along these lines, on an episode of NPR, a few years back. Something about engineers being a lot more religious than scientists in related fields. Computer engineers were the one exception to that trend.

  2. Narf says

    And in reference to your comment about users lying … try help desk/desktop support. The shit we hear out of our users about the things they haven’t been doing with their computers, when the fingerprints are all over the system …

  3. Monocle Smile says

    There are a few reasons for this. Firstly, the population of people with the job title “engineer” contains a massive glut of military and ex-military folks. Not to trash our service men and women, but religion is pervasive among veterans. I work for a DoD contractor, and we have so many ex-military in our building of 700 that there are sponsored events every month to support military charities and other stuff. I generally don’t talk about my personal life at work at all, but I wouldn’t even consider mentioning my views on religion, even when out with coworkers or playing for the company sports teams.

    The other factor, at least in my mind, is the age gap. The “engineering” population is getting old. Lots and lots of engineering students go off to non-engineering or academic careers.

  4. lancefinney says

    I’ve seen another connection that you touch on, but don’t really explore – both computer programming and skepticism/science rely greatly on testing and falsifiability. In both contexts, you can’t really say you know something until you’ve tried to disprove it.

    In programming, it comes through unit and other tests, and many people will say that you don’t know your code works unless you have a test that proves it works. In science, an idea doesn’t become trustworthy unless it passes experiments that are designed to disprove it.

    In both areas, this They Might Be Giants song is appropriate:
    Put It To The Test

  5. Russell Glasser says

    I was referring to “The Salem Hypothesis”: http://rationalwiki.org/wiki/Salem_Hypothesis
    “…people who claim science expertise, whilst advocating creationism, tend to be formally trained as engineers.”

    I have mentioned seeing an exception for computer people, but the page I linked does say that CSE (computer science) is included. I can accept that the general notion of being an effective skeptic does not necessarily translate to having a solid understanding of science, any more than being a magician does.

  6. Narf says

    Ah, that’s probably what I was thinking of, yeah. And while those two things don’t necessarily lead there directly, there’s a pretty strong correlation, isn’t there?

    Personally, I always laugh my ass off when I see evangelists using magic shows as a backdrop from which to preach. Yes, you’re sawing a girl in half with a jigsaw and calling it “The Armor of God” … but God’s real protection isn’t an illusion. I mean fine, they’ve figured out a con to work their hobby into a way to fleece the sheep, so good for them. How do they actually find the congregations who can’t see the massive contradictions in the messages, though?

    Oh, yeah … churches who believe in the infallible Bible. That’s how.

  7. John Kruger says

    Math and logic are helpful in just about every endeavor, but they are step by step necessities in programming. All science is creating abstractions and then putting them to the test, programming just gets a very fast test and correction process that makes the process starkly obvious.

    I think about a lot of things very much like Russel does. I even worry that I am being a groupie and not challenging what he says enough because I hardly ever disagree with him about anything. I have long suspected that programmers tend to develop similar strategies when addressing problems, and I credit that idea to how similar in thinking I tend to be with him. And to be clear I am in no way in at the same level of programming that a professional like Russel is, the basics are enough to start the trend.

  8. reverendrobbie says

    I was thinking this very thing today, that programmers learn rational thinking through their study. As a CPA, though, I’m surprised how my field of accounting does not produce high rates of skeptics. I’m always talking to people about the dangers of following motivated reasoning, of getting duped into bad decisions by sunk costs, and of poorly identifying cost drivers. I wonder if dealing somewhat directly with our clients’ emotional topics like business ownership, employee relations, and taxation mitigate our field’s otherwise rational bases.

  9. JT Rager says

    Yes, Russel, but many computer programmers also have to talk to an imaginary friend to get their code to work, ie a rubber duck.


  10. CompulsoryAccount7746, Sky Captain says

    So the other part of your job as a programmer is to look at the problem from all possible angles and figure out all the possible ways that people will break your program, before they do it to you.

    For tips, search for the phrase: “Falsehoods programmers believe about”
    Article: Names

    Article: Time

  11. CompulsoryAccount7746, Sky Captain says

    Related: Confidence is often inversely proportional to experience, especially when excitedly talking about grand plans.
    The time for confidence is two days before release, after you’ve conquered all the tricky minutae that threaten the project… before any last minute fixes spring to mind… and before users flood you with new bug reports.

  12. deesse23 says

    I would consider engineers who advocate creationism to be just bad engineers. Engineering, like any other field of science is abot finding out “how” and not “who”. Thus anyone who is an engineer and claims to have found “evidence” for creationism or any other BS, has not undestood that he just left his professional field of work and stepped over into Philosophy or whatever. I am very much with L. Krauss in his debate with F. Tipler about that.

    Since there seems to be irritation about what and whom exactly to consider to be an engineer (let alone to be a GOOD one 🙂 ), i will provide you with a scientifically proven to be correct “engineer identification test”, so you can check yourself and people around you regarding this claim “i am an engineer” or “i learned science”.


  13. says

    I think being a preacher is similar to being a person selling insurance. The similarities are uncanny in regards to selling something that isn’t tangible and yet wanting them to trust you none the less. I just see the bible as being the policy that’s filled with all kinds of loop-holes and in the end you’re still damned because of a technicality and failure to read the fine print.

  14. says

    I’ll have to go with the apologetics for engineers* post above and hijack the idea that really good programmers might make good skeptics. If you are a skeptically-orientated person who wants to learn programming, I’d think you probably have a better shot at being a good programmer, certainly. (Assuming they are also allowed to produce good code, as well.) You’d probably also refine your skepticism. But I highly doubt it in most cases if you are not so orientated in the first place. Still, even great coders can make horrible skeptics.

    *I don’t actually believe this for 2 seconds.

  15. Monocle Smile says

    Eh, I think of it more like Amway. Or a Ponzi scheme, because the product isn’t real.

  16. says

    I’ve often remarked about how debugging is like the scientific method. If I go into trying to investigate a phenomenon (bug) with a preconceived conclusion, going in, I’m far less likely to actually solve it.

    Instead, I follow the evidence. I do a whole bunch of hypothesis testing, falsifying possibilities until I can zero in on the problem.

    It’s a very structured and methodological approach… and if I didn’t have the ability to be open-minded about the possibilities, and listen to what the evidence is telling me, I’d be incapable of doing me job.

  17. says

    For example, years ago, we were having a problem with a virtual host, where after awhile, the entire server would slow to a crawl, causing things like image download to time out (despite having plenty of bandwidth)… until the server was rebooted.

    My boss insisted that we go through our code, line-by-line, because the problem had to be with our code. I ignored this, and followed where the clues were leading me, and found that there was a memory leak with a Linux console command, for recursively copying files, we were using… once we (I) figured that out, the problem went away.

  18. Narf says

    Personally, I like Simon’s reformatting of the classic, a few posts back. GIGO: God in, garbage out.

  19. Narf says

    I’ve linked it in other discussions, too. Just look at Kent Hovind:

    (less painful version in which you at least have Logicked breaking up his inanity with snark (full original video linked in the About section of that video))

    How can anyone not immediately register the quick-talking, rapid-fire-before-you-can-examine-each-point-closely delivery of the con artist, in every talk the guy does?

  20. grumpyoldfart says

    I learned to program in BASIC on the Commodore 64 (self taught hobbyist).

    The one thing I learned that really surprised me (and took me several years to accept) was that it was always my fault. One hundred percent of errors could be traced back to mistakes in my program. Not one was caused by a hardware problem.

  21. Narf says

    Commodore 64?!?!? POSH! My Apple II+ only had 64 kilobytes of RAM after we upgraded it.

    And we were amazed by the new, fast 5 1/4″ floppy drive. The old cassette player that we had used previously should have been enough for any game, but the newer games were only coming out on floppies.

    Admittedly, I had a hand up on the BASIC programming because my father was a programmer, way back in the day. I wrote some of the most useless crap you could imagine. I got a little better once I learned PASCAL and assembly language, but I was never really at a professional level.

  22. corwyn says

    I remember learning the opposite lesson. My code was perfect, the compiler messed up. By that time, I had internalized your lesson so deeply, that it was a great shock. I have actually seen a persistent hardware bug as well, but those are even more rare.

  23. Dmgeek says

    As a software engineer of 30 years I’ve known many serious evangelical Christians (formerly one myself) in the profession. Of course this could be partly due to my location in the North Carolina Research Triangle which is part of the “Bible Belt”. I agree with Russell that learning to program (well) imparts solid logic skills; yet I think the intelligence required to program, (especially at the most rigorous levels) also provides religious believers with advanced abilities to rationalize their faith. During lunch conversation, I have encountered this several times since leaving the faith many years ago. It is also true that one can achieve very advanced computer science skills with minimal understanding of biology and the life sciences.

  24. says

    As a programmer, I have had deep insights into problem solving and design. It felt so true. I had *the* answer! Only to find out that as I pounded out the code on the keyboard that I had made wrong assumptions and the solution was unworkable. As programmers, we get to put our insights to the test. But I have met many a non-critical thinking programmer, including grand conspiracists and a Libertarian that has contemplated suicide from no longer being a useful cog in the wheel of capitalism.

  25. CompulsoryAccount7746, Sky Captain says

    Article: Coding Horror – Separating Programming Sheep from Non-Programming Goats

    “Despite the enormous changes which have taken place since electronic computing was invented in the 1950s, some things remain stubbornly the same. In particular, most people can’t learn to program: between 30% and 60% of every university computer science department’s intake fail the first programming course.”

    [A test is found which predicts programming aptitude…]

    “It has taken us some time to dare to believe in our own results. It now seems to us, although we are aware that at this point we do not have sufficient data, and so it must remain a speculation, that what distinguishes the three groups in the first test is their different attitudes to meaninglessness.”

    * In the test the consistent group showed a pre-acceptance of this fact: they are capable of seeing mathematical calculation problems in terms of rules, and can follow those rules wheresoever they may lead.
    * The inconsistent group, on the other hand, looks for meaning where it is not.
    * The blank group knows that it is looking at meaninglessness, and refuses to deal with it.

  26. A Kangar00 says

    I find it really interesting that there is not more outrage about supposed “scientists who advocate creationism” who turn out to be engineers but claim science expertise. I’m not from the US, so I don’t know if scientist and engineer are somehow interchangeable terms, but in Europe they are definitely not.

    Science training is about developing tools to understand the nature and behavior of the universe / reality whereas engineering is about solving problems by employing scientific knowledge or findings (I toss applied science in the same bucket for good measure). So for somebody to claim a scientific background without being trained to actually understand and use a scientific process seems to be misleading at best.

    From that perspective it’s no surprise to me at all that if one lumps scientists and engineers together the majority of creationists will be found among the engineers. Scientific training should by default predispose people to employ skeptical thinking processes, something which is not necessarily true for engineering.

  27. Callinectes says

    This immediately made me think of biology and evolution, which if I’m honest, most things do. Because it made me imagine trying to write a computer program able to handle anything that is thrown at it. It would be fairly complex, and would probably be optimised by having code with multiple functions for different situations as determined by simpler code. I have zero programming skills so that may not even work in principle, but it is how DNA works. DNA might be considered comparable to a computer program in principle, and one that has encountered all the stupid things users do and so has responses for them. I imagined a creationist or other skeptic of science presenting the challenge that noting we’ve designed is as brilliant as life and the way it deals with issues in ways our technology can’t. EXCEPT: that life also has bugs that turn up, especially now as we expose ourselves to novel substances. In fact, any extinction can be thought of as the encountering of a fatal bug. My favourite episode of the new Cosmos (the one about Clair Patterson) features a prominent bug: the vulnerability to lead. Lead, though natural, is never encountered naturally in our environment, so we have no appropriate biological response. When we do encounter it it takes the place of important heavy metals like Zinc or Iron in our metabolism without pulling any weight, and also blocks our neurotransmitters. We have no defense. It’s a bug in our biology, one for which a sensible programmer would release a patch. Evolution could do it eventually, but not with the same kind of urgency. Poisons are all classic bugs, and the venom of predators seem comparable in some ways to the efforts of hackers.

  28. bugmaster says

    @Russell (well, or anyone, really):

    Can you recommend any good online tutorials, online classes, or good old-fashioned books that teach debugging techniques ? For some reason they don’t seem to really teach debugging in college, and I’m having a hard time explaining how debugging works to my friends and junior colleagues. I would love to be able to simply say, “here, just read this, and then you’ll understand why I get upset when you tell me ‘oh noes, there was an error, help !’ when the stack trace is right there on your screen” :-/

  29. CompulsoryAccount7746, Sky Captain says

    Basic approaches when you get an error after adding code:
    – Read what the error is telling you. If it complains about a semicolon or an unrecognized variable, that’s likely the problem, near that line.

    – The stack trace is a list of breadcrumbs that immediately led to the error. A function may be getting bad args from the code that called it, so it may be worth investigating a few lines down the stack trace (into the past).

    – An extra/missing curly brace wrecks everything. that follows. (Try that deliberately sometime to see the havoc that results, so you can recognize it.) Good luck with that. : |

    – Gradually comment out recently added code until it the error goes away. The error had something to do with what was last removed.

    – Start with a skeleton or mockup of the program that marginally works; then gradually add copy/paste code into it until that breaks. The error had something to do with whatever was added last. If it never breaks, you’ve just rewritten the app without the error; congratulations!?

  30. CompulsoryAccount7746, Sky Captain says

    When an app compiles fine but crashes as it runs (or otherwise misbehaves), start littering the code with statements that print or log the status of important variables and moments key functions are called.

    * Add a comment beside those lines, if necessary, so you can find and remove them later when you’re done debugging.
    For finer scrutiny, use a debugger tool, which can pause execution at specific lines (“breakpoints”) and show what’s going on from moment to moment.

  31. CompulsoryAccount7746, Sky Captain says

    For large projects or libraries, it can help to write additional main() classes for testing/tinkering. Essentially mini programs that call shared functions – or construct and manipulate objects – from the project under simpler conditions.

  32. Peter Robertson says

    While I agree with the post, my decades of working in software have shown me that creationists and many programmers have one unfortunate trait in common: they love complexity.

    Creationists love it because they have been fooled into believing that it’s evidence for their beliefs; the programmers love it because of the equally false belief that “more visibly complex” equals “better”. I can think of no other engineering discipline that has this fatal obsession with complexity.

    Good programmers love simplicity, and that is the number one debugging tool.

  33. bugmaster says

    Right, this is all good advice, but I was hoping for a more systematic resource, like a series of step-by-step tutorials, a class, or a book.

    That said, I disagree about your comment 16.3, at least in part. Instead of all these main() functions, you should be writing unit tests; this way you can systematically check the correctness of your code at the push of a button. You can also configure CI to automatically do this for you.

  34. Narf says

    Could also be a generational thing. Almost every (and that’s hedging, because I can’t remember one that wasn’t) I.T. department I’ve worked in, in the past 5 or 10 years, has been majority atheistic. I’ve lived in either Raleigh or Durham, for the past 25 years or so.

  35. CompulsoryAccount7746, Sky Captain says

    I was hoping for a more systematic resource, like a series of step-by-step tutorials, a class, or a book.

    Sorry, can’t help there.

    Any detail beyond general advice would turn into discussion of the code in question. Imagine how frustrating a book on broken code would be if you made mistakes copying the examples! : P
    There was “Java Puzzlers: Traps, Pitfalls, and Corner Cases” to confound / inform veterans with examples that have counterintuitive results… Wiley published “Java Pitfalls” and “More Java Pitfalls”, but those were tips on handling really specific gotchas (meh).

    Instead of all these main() functions, you should be writing unit tests

    True. I was just describing what unit tests amount to – both to cover one-off troubleshooting, and to avoid dragging in discussion of build tools and further jargon.
    I tend to think of automated unit tests as routine checks to warn about regressions.
    On the other hand, on rare occasions I may tinker with a GUI component in a hello world window.

  36. Narf says

    Thus bloatware?

    And yeah, you can clean up any statement into something accurate, with the addition of a few adjectives. 😀

  37. Monocle Smile says

    There are some online resources available. Universities have gotten pretty good about the online stuff. The third link is from Microsoft.




    There’s really no one-size “tutorial” for debugging. There are recommended techniques, but you really have to feel it out for yourself. I typically do what Sky Captain recommends, like writing additional main() functions, or I just comment out chunks of code.

    I also sometimes try “emulated” functions; they take the same inputs and spit out the same types of outputs as the real functions, but it’s just hard-coded prescribed stuff and doesn’t actually do what the real function does. You can do process of elimination by using emulated code and replacing each chunk with the real functions one by one.

    I’m a bit rusty with this; I haven’t written anything lower-level than MATLAB scripts in a couple of years.

  38. bugmaster says

    Thanks, the first link sounds pretty useful, though the other two appear to be defunct. I’ll check it out.

    You are right when you say that there’s no “one size fits all” approach to debugging, but still, there are some basic fundamentals that are easy to say out loud, but are hard to internalize. For example, “before commenting out random chunks of code, look at what the exception says, then look at the stack trace, see if you can figure it out that way”, or “the computer does exactly what you told it to do, not what you want it to do”, or “if your exception says ‘x cannot be null’, then, before panicking, check why you are passing in null”, etc…

  39. Peter Robertson says

    One of the difficulties with debugging is that, surprisingly often, the place a program starts to display aberrant behaviour is far from the cause. You need to catch errors as close to their occurrence as possible. To help with this, you should make your code self checking so that you can report problems when they happen and not wait until their effects become obvious.

    From the very beginning of your project, wherever possible and practical, you should add consistency checks that can remain in the production version of your code; don’t wait until something goes wrong. Although users will always be annoyed when code fails, they tend to be less angry when it fails under control rather than simply crashing.

    Also, turn off all optimisation. Some compilers offer a checking mode, where things like array bounds, use of unassigned variables, and the like are check automatically. Because people running performance tests tend to run compilers ‘out of the box’, it’s common for the default state to be full optimisation, so make sure you disable it and enable all automatic checking.

  40. says

    Well put, very Kernighanesque. The code changes that really stoke my endorphin furnace are those with many deleted lines code.

    “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?”

  41. says

    To me, it’s also a two way street. Being a good skeptic/rationalist also makes you a better programmer. Being able to spot fallacies, faulty syllogisms and questionable premises can help cut through political middle management BS pretty well (I guess this benefits any profession, not just programming). Having epistemological awareness of what you’re working on also helps. The amount hours programmers pour into coding needless obfuscation optimization alone is just ridiculous, they’ve never asked “Why am I doing this?” or “Am I justified investing time in this?”

  42. Russell Glasser says

    Bugmaster, here are a few books I have found helpful:

    (This last one is specific to C++ but has many good general lessons. There may be other books that focus on other languages.)

    Based on Amazon reviews I suspect this is probably good too:

  43. Galakyllz says

    You hit the nail on the head when you said that “you constantly have to be figuring out how to set up situations where nothing can go wrong”. This is always true when your program interacts with general users who provide any input, always.

    I’ve been programming, just realized it, for over half of my life (late 20’s) and learning to debug is definitely the skill you come to master. In your post, though, I think you could go a bit farther and expand on the benefits of someone who is adept at debugging software. To state it for you: they will often find themselves in situations where a cool head and a determination to find the problem invariably lead to success. Too often has a calm, collected, and systematic deconstruction of a situation led me to solving a problem and I cannot help but credit my years of patient hours debugging code to that success.

    Stay Calm
    Keep Programming

  44. says

    I taught myself computer programming late in high school, and have been doing it ever since. I feel the necessary increase in rigorous logical thinking has helped me in several areas. Going back to higher mathematics, which used to give me trouble in high school, don’t seem as hard to grok.

    Also, dealing with pedants on Usenet, you gain an appreciation for wizardly experts and employing precision in your spoken language.

    I feel I’m glad I tried programming, because I really enjoy the problem-solving. I’ll sometimes drop what I’m doing just to work on an interesting problem. For example, the “Weasel” program in Dawkins’ The Blind Watchmaker was a fun little problem to work on.