A lack of self-confidence can be incapacitating. Frances Buontempo considers why it’s important to acknowledge your doubts and remind yourself of the things that you can manage.
Do you ever freeze up and fail to get something done, because you’re not certain how to proceed? For example, writing an editorial. I suspect you have noticed I frequently don’t know how to proceed, making excuses every time for the lack of editorial. Imagine if you never had this problem. You could carry on with no stumbling blocks. Nothing would stop you. If you found yourself in a deep hole, you would carry on digging forever. If you were ‘refactoring’ a code base you would plough on for days, without wasting time trying to build the code and run the tests. Nothing could possibly go wrong, right? Hmm, maybe some self-doubt from time to time is a good thing. Perhaps a balance between freezing up and continuing regardless is what’s needed.
I got stuck while writing my talk for ACCU. I mentioned my grand plan in the last Overload [Buontempo25a]. I intend to get my machine to play Snake, learning how via reinforcement learning. I revisited my proposal to see what I promised. I said will “start with a std::vector
and progress from there” [Buontempo25b], so previous me had been helpful to current me. Starting simple is a good idea. I have managed to get a blob to move right or left, corresponding to a position in a vector. It can learn to go to the end, and get a reward. With the one-dimensional case working, I could move on to the two-dimensional case. Pleased to report I have a mini-game of snake working on a five by five grid. I represented the snake with a +
, an apple with an O
, and show a *
when/if the snake crashes. It can manage to eat a few apples, but still tends to crash into itself:
| ++*+| | ++ | | O | | | | | -------
In this example, instead of going down and eating the O
, it went up and hit itself. But, the snake had eaten a few apples first. Finding a simpler starting place made the problem seem less overwhelming.
Andrew Drakeford spoke at CppOnline [Drakeford25] the other week. He talked about Data-Oriented design, using data layouts and better algorithms and similar to optimize a program. He reminded me about George Pólya’s book How to solve it: A new aspect of mathematical method. Pólya gave four steps:
- Understand the problem,
- Devise a plan,
- Carry out the plan,
- Look back and check your work.
If this fails, Pólya suggests [Wikipedia-1]:
If you cannot solve the proposed problem, try to solve first some related problem. Could you imagine a more accessible related problem?
Trying a one dimensional version of snake first helped me to start thinking. Well, I say snake. There was no snake, and no apples to eat to make the snake grow. However with no apples, I can claim the single square is a hungry snake, and it does move from side to side. I still have doubts that this will extend to a proper game, but I might just about have enough to wire together to give a talk. I still have lots to learn about reinforcement learning. But I have managed something. You may well have found yourself in a similar situation, not being sure how to achieve a task. If you can break it down into smaller steps, or try a simpler proof of concept, you might manage to progress. As a Chinese proverb reminds us, “A journey of a thousand miles begins with a single step” [Wikipedia-2].
Now, solving a different problem is no guarantee you will actually be able to solve the harder problem. And a proof of concept doesn’t prove much, at least in mathematical terms. Both can be helpful, at least by giving you more information, and maybe sparking a few thoughts about the wider problem. We often don’t get much proof in code. We can write some tests, but might not think of all the edge cases. We can use property-based testing, getting your computer to generate values for you. If you’re not familiar with property-based testing, listen to Steve Love’s talk [Love24]. On the face of it, the testing framework generates random values to try, but the randomness is actually guided, trying to flush out the smallest possible examples that fail tests. The tests are written as properties, like “nothing is negative”. You can regard property-based testing as a subset of fuzzers, though these are often used to try to code, looking for potential vulnerabilities. Maybe the property tests are not certainty, but they can increase confidence.
You can use other tools too, like sanitizers and linters to try to find potential problems. Recently, many people have been advocating use of constexpr
and similar to attempt to eliminate undefined behaviour in C++. I believe the standard [C++] says:
An expression E is a core constant expression unless the evaluation of E … would evaluate … an operation that would have undefined behavior.
Of course, there is a ‘but’. There is an example on Stack Overflow of calling a library with a core constant expression that did not get a diagnostic [stackoverflow]. Although this example was actually a bug (now fixed) in GCC [GCC], using constexpr
can find problems. Šimon Tóth wrote a ‘Daily bit(e) of C++’ on Medium and posted about this [Tóth24]. He gave an example of a naïve attempt at midpoint:
constexpr int midpoint(int a, int b) { return (a + b)/2; // can overflow, // int overflow is UB }
With input just smaller than std::numeric_limits<int>::max()
, this can overflow. His example uses:
constexpr int a = std::numeric_limits<int>::max(); constexpr int b = a - 2; constexpr int c = a - 1;
Using a static_assert
:
static_assert(midpoint(a, b) == c);
gives a compile error:
error: overflow in constant expression [-fpermissive] 5 | return (a + b)/2; // can overflow, // int overflow is UB
The constexpr
has helped find UB. Nice. As warned by the Stack Overflow link, there will be exceptions, but the use of static_assert
can provide less doubt.
Eliminating uncertainty is a great aspiration. However, sometimes you can’t remove all doubt. There are always unknown unknowns, and often known unknowns. Making these more apparent can be useful. Seb Rose talked about this in his ‘User Stories and BDD’ series. In particular he said [Rose23]:
We feel deeply uncomfortable with uncertainty and will do almost anything to avoid having to admit to any level of ignorance. Rather than focus on what we know (and discreetly ignore what we’re unsure of), we should actively seek out our areas of ignorance.
Kevlin Henney dug into this in ‘The Uncertainty Principle’ [Henney13]. He encouraged us to see uncertainty as part of the solution rather than a problem. He suggested structuring your code so the decision doesn’t matter. For example (my example), you can introduce an interface and switch between a database or lookup table. The code using the data won’t need to change, then. Having more than one idea can be a good thing. Being certain there’s only one solution is suboptimal, at least, and delusional at best.
Is confidence overrated? Maybe. It is often misunderstood. You may be familiar with confidence intervals from statistics. If someone claims to be 100% confident, they are either analyzing a simple problem, like the probability of a coin toss being a head or a tail, or they have missed the point. Claims are sometimes made that, assuming a normal distribution, a hypothesis is valid at a 95% confidence interval. This means an observation falls between the mean minus 1.96 standard deviations and the mean plus 1.96 standard deviations. If the data is normally distributed, and the mean and standard deviation have been calculated accurately, 95% of the observations would lie within these bounds. Confidence might be a misleading word to use at this point. Sometimes other disciplines use different words, for example medicine might say a ‘reference range’ [BMJ], which allows you to talk about ‘normal’ or ‘abnormal’. Be careful with the word ‘normal’, though. I’ve previously written about this being misleading too [Buontempo21]. Saying ‘abnormal’ to refer to measurements is useful, but be careful when discussing anything non-numeric, like people.
Statistics are fundamentally imprecise. Actually, they are very precise, but always start with phrases like ‘assuming a normal distribution’ or similar. If you provide stats, for example when benchmarking, it’s useful to provide a mean as well as a standard deviation or variance. This provides more information. The sample size can be useful too. If you use n=1, I’ll doubt your results. This is equivalent to saying, “It works on my machine.” OK, fine, but it might not work elsewhere. Providing more than one number is important for statistics, and having more than one result or perspective is useful. In fact, getting someone else to run your code often reveals potential improvements, or might help pin down the cause of a problem more quickly. Sharing is caring, as they say.
Now, my title, ‘self->doubt’, could suggest a member function. Whether it is a getter or setter is unclear. In fact, you can cause yourself doubt, calling your own setter as it were, if you’re not careful. And that can become a negative feedback loop. On a computer, you would get a stack overflow. For a human, you can end up in a state of despair or burn out. If this chimes with you at the moment, take a moment if something doesn’t seem to be working. Remind yourself what’s gone OK – maybe you have some tests that pass. If you can narrow down the problems, either as tests or as a TODO list, you might end up with smaller, easier to solve problems. Or maybe you won’t, but you have still learnt something. It’s OK to abandon a problem. You might be able to form a Plan B and solve the actual problem in a different way. Experiments that fail are still informative. However, sometimes the self-doubt comes from imposter syndrome [Wikipedia-3]. Despite evidence that you can do something, or are knowledgeable about a subject, you might feel like a fraud. Knowing you still have much to learn is a good thing. The Dunning-Kruger effect reminds us “people with limited competence in a particular domain overestimate their abilities” [Wikipedia-4]. Conversely, people who know their stuff may underestimate their abilities. Imposter syndrome goes beyond this underestimation. It can lead to anxiety, neurotic behaviour and depression. If you find yourself feeling like this, find some good friends to talk to. It’s OK to say you need support.
If you find yourself doubting your knowledge or ability, don’t panic. Some self-doubt can be better than overconfidence or downright arrogance. Some things are hard, and we all get stuck from time to time. A maths lecturer once told me to relax and enjoy a problem if I got stuck. He was probably quoting someone. However, the point is reframing feeling stuck as having something challenging to think about is helpful. It’s much better than saying “Keep calm and carry on.” If you’re digging a hole, don’t carry on. Stop, think and consider sharing the problem with someone. It might help. Maybe write a blog or article about a problem you are stuck on. That might help you get your thoughts straight and reveal what you do actually know. Doubt yourself from time to time. But allow yourself some confidence too. You’re doing great.
References
[BMJ] ‘Statements of probability and confidence intervals’ at https://www.bmj.com/about-bmj/resources-readers/publications/statistics-square-one/4-statements-probability-and-confiden
[Buontempo21] Frances Buontempo, ‘It’s not normal’ in Overload 166, December 2021, available at https://accu.org/journals/overload/29/166/buontempo/
[Buontempo25a] Frances Buontempo, ‘All the information is on the Task’, Overload 185, Feb 2025, available at https://accu.org/journals/overload/33/185/overload185.pdf
[Buontempo25b] Frances Buontempo, ‘An introduction to reinforcement learning: Snake your way out of a paper bag’ (abstract), available at https://accuconference.org/2025/session/an-introduction-to-reinforcement-learning-snake-your-way-out-of-a-paper-bag
[C++] ‘Constant expressions’ in Working Draft: Programming Languages – C++, available at https://eel.is/c++draft/expr.const#5
[Drakeford25] Andrew Drakeford, ‘Date Oriented Design’ (abstract), available at https://cpponline.uk/session/2025/data-oriented-design/
[GCC] GCC bug report: https://gcc.gnu.org/PR105844
[Henney13] Kevlin Henney ‘The Uncertainty Principle’, in Overload 115, June 2013, https://accu.org/journals/overload/21/115/henney_1854
[Love24] Steve Love, ‘Beyond Example Based Testing in .NET (dotnet), nor(DEV):con 2024, available at: https://www.youtube.com/watch?v=RgDGsZXPK3Y
[Rose23] Seb Rose ‘User Stories and BDD – Part 2, Discovery’ in Overload 178, December 2023 available at https://accu.org/journals/overload/31/178/rose/
[stackoverflow] ‘Undefined behavior allowed in constexpr -- compiler bug?’ at https://stackoverflow.com/questions/72494618/undefined-behavior-allowed-in-constexpr-compiler-bug
[Tóth24] Šimon Tóth ‘Daily bit(e) of C++ | Constexpr vs Undefined Behaviour’ available at https://medium.com/@simontoth/daily-bit-e-of-c-constexpr-vs-undefined-behaviour-39330bd42906
[Wikipedia-1] ‘How to solve it’: https://en.wikipedia.org/wiki/How_to_Solve_It
[Wikipedia-2] Chinese proverb: https://en.wikipedia.org/wiki/A_journey_of_a_thousand_miles_begins_with_a_single_step
[Wikipedia-3] ‘Imposter syndrome’: https://en.wikipedia.org/wiki/Impostor_syndrome
[Wikipedia-4] ‘Dunning-Druger effect’: https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect
has a BA in Maths + Philosophy, an MSc in Pure Maths and a PhD using AI and data mining. She's written a book about machine learning: Genetic Algorithms and Machine Learning for Programmers. She has been a programmer since the 90s, and learnt to program by reading the manual for her Dad’s BBC model B machine.