
Why Isn't Debugging Treated as a First-Class Activity? - dannas
https://robert.ocallahan.org/2018/07/why-isnt-debugging-treated-as-first.html
======
pdpi
One practice I don't think I've ever really seen properly discussed is
exploratory debugging. Given a large codebase I'm not familiar with, I've
found that this workflow is an incredibly fast way to get familiar with the
overall flow and structure of the code:

    
    
        - run the thing
        - grab an output string of some sort (either output proper or logs or whatever else)
        - grep for it
        - set a breakpoint where the string is generated
        - run again
    

From there, you can explore the stack, and you start to get your bearings. How
is this particular thing generated? Find the place in the stack where it first
shows up, set a break point, start over and debug from there. Repeat until you
have a sufficiently solid grasp of the codebase that you can just navigate the
source tree searching for where things are.

~~~
segmondy
To each their own, I use to enjoy such. I absolutely hate it now. Given a
codebase, I want to know the story. Why was the code written, what problem was
being solved, why did they decide to solve it in a specific ways, WHY, WHY,
WHY? I need to know the whys. I want the story, I want to know the domains.
How is the software layered, can I explore one layer without going into other
layers? I don't want to do so with a debugger. I want to do so with a document
reader.

~~~
dalbasal
The downside is that this assumes a "why" exists. Codebases are often evolved
rather than designed, and just are the way they are without persistent reasons
for things. A common reason would be "because it was this other way before."

Imagine all the stuff that's probably in MS office, for which the reason is
totally lost. There were reasons, but they're not really retrievable.

~~~
GrinningFool
> Codebases are often evolved rather than designed, and just are the way they
> are without persistent reasons for things. A common reason would be "because
> it was this other way before."

Yes and no, I think. Codebases represent a collection of point-in-time
decisions, and each one of those decisions had a reason. There's always a
'why' even if it's not captured.

> Imagine all the stuff that's probably in MS office, for which the reason is
> totally lost. There were reasons, but they're not really retrievable.

True - and that's Really Bad. That means you're stuck not able to improve or
change certain things, because you don't know why they were done that way -
and when you have a userbase the size of Office, you can't just say 'f it' and
break things - at least not lightly, as a code-level decision.

~~~
throwawayjava
The worst "why?" answers often go like this:

1\. Green field+0 years: This particular portion of the system was designed in
this way as a cargo cult.

2\. Green field+2 years: Because that portion of the system was designed in
that way, we had to modify this other portion of the system to achieve X.

3\. Green field+3 years: Because of the change in 2, and this new constraint
Y, we had to make this other change in a third portion of the system.

5\. Green field+(3 to N) years: repeat steps 2 and 3.

6\. Green field+N+M years: Wow 5 (or previous 6) has created a mess and
exposed a serious architectural flaw from step 1 or previous 6. All of the
logic in the various iterations of 2+3 are refactored as best as possible.

So, the "why" basically grounds out in "the refactoring we could afford to do
in order to correct a mess that resulted from a cargo cult or previous
refactoring of even older cargo cult".

Is that "why" functionally helpful? Usually not for me -- in either case, I
can't really assume a lot and I have to proceed with laborious "just watch
what the code does" debugging/logging that I would've done without the "why?".

But this is probably a ymmv situation.

~~~
sli
The worst why that I regularly hear is, "the client changed their mind and
it's the best we could do."

Which, of course, has two negative implications. Not just one.

~~~
throwawayjava
Yes, that's the root cause of 2+3.

------
josephv
The omission is interesting only in that it highlights that programming and
debugging are one in the same.

Us old folks that have been programming for 20 years don't even separate the
two, there is no meaningful distinction. Programming is not a write-only
operation (Perl excepted).

If it's an existing project/product, I get it running and find the entry
point. If it's new, I write and entry point and get it running. Then I change
something, or write something, and debug it. Is it working as expected? Maybe
the execution flow isn't what I expected. Why do I always forget to initialize
things right. Probably because every language thinks their version of native
v. abstract references are fancier.

Blah, I need to get to work cod... debug.... what am I doing today? Ah yea,
writing documentation. Fack

~~~
dsfyu404ed
>Programming is not a write-only operation

A lot of people would take issue with that statement.

Most devs probably wouldn't notice that their backspace key went missing until
they were fine tuning the phrasing of an email about why the best way to solve
their spaghetti is to make the same spaghetti slingers port the codebase to
$FAD_OF_THE_WEEK.

Edit: It should be obvious that this is a joke but if it's not you should
probably check if your backspace key still works.

~~~
commandlinefan
> check if your backspace key still works.

Back in the late 90's, when Java was still sort of new, my employer insisted
that I install an IDE to do my Java development that I had been doing mostly
in vi. The one they picked (for some reason) was Symantec's Visual Cafe. I
found that I could reliably, reproducibly, crash the IDE by pressing the
backspace key. Maybe that was their way of pushing a "no mistakes" philosophy?

~~~
hinkley
In that era no IDE ran stable across its whole feature set. Crashing debuggers
were very common. VisualAge had the most stable debugger but would crash just
typing in code.

Jetbrains was the first one that was reliable. Slow, but not as slow as VA.

------
reikonomusha
Debugging is an extraordinarily first-class, up-front, frequent activity in
Common Lisp, as the facilities are built into the language itself. While Lisp
gets a lot of flak for basically (up to a few daring power-user exceptions)
requiring Emacs, SLIME/SLY [1,2] are environments that will make you feel
closer to your program than you get in other environments, including graphical
IDEs.

Given that the normal way to develop a Lisp program is to do it incrementally,
your program (or someone else’s!) _will_ break, and it will break often, and
you’ll get launched into an interactive debugger. But it’s friendly, not
requiring a completely separate, foreign toolchain, and much of the
functionality works regardless of which editors/IDEs you’re using (though
Emacs makes the experience much more ergonomic).

I think this is perhaps a bigger selling point of Common Lisp than all the
great, oft-quoted things like metaprogramming.

[1] [https://common-lisp.net/project/slime/](https://common-
lisp.net/project/slime/)

[2] [https://github.com/joaotavora/sly](https://github.com/joaotavora/sly)

~~~
stcredzero
_Debugging is an extraordinarily first-class, up-front, frequent activity in
Common Lisp, as the facilities are built into the language itself._

Smalltalk is something like the ultimate debugger. The advanced Smalltalk
coders would often do most of their coding in the debugger. (It's very easy to
unwind the stack a few places, then resume execution.) The VisualWorks
debugger was so nimble, people would put expressions to be executed and
debugged into code comments! (The debugger would execute the code in the
context in which it was evaluated, so this could be absolutely awesome.)

 _Given that the normal way to develop a Lisp program is to do it
incrementally, your program (or someone else’s!) will break, and it will break
often, and you’ll get launched into an interactive debugger._

One of the most frequent demos we did in Smalltalk, was to write some empty
scaffold methods, launch into an exception, then fill in everything in the
debugger until the system was complete.

~~~
ben509
I think direct language support for "missing code here!" is a brilliant idea.
Even when you have types and documentation, you often need to dummy check that
values you'll get called with are what you expect.

~~~
corysama
I've heard Smalltalkers tell tales of starting an empty project by just
hitting "Run", letting the debugger take exception to that fact that there is
no startup function, then start typing code as it becomes necessary to
proceed.

~~~
stcredzero
That's what I just wrote!

~~~
traviscj
I read the GP as saying “you don’t even need to create the scaffold methods”
described in your post.

------
flohofwoe
I'm using IDE debuggers as integral part of my normal programming workflow,
not for actual "debugging", but for stepping through new code to check if it
"feels right". I hardly find bugs that way (that usually happens when the code
is out in the wild and several unexpected things happen at the same time), but
I add a lot of little changes based on the step-debugging... rename a variable
here, add a forgotten comment there, and also think about what to do next. I'm
quite sure I spend more time in the debugger then writing code.

I wish edit-and-continue, rewinding time, etc... would be better supported
across IDEs. Programming should be a "conversation with the machine", and
ultimately with other programmers. When I'm stepping through my own code, I
try to assume the role of an "outsider" and judge my code from the "outside".

The debugger is also the most important tool for me to understand code written
by others.

~~~
maaaats
Edit-and-continue works in several languages. Java can hotswap, for instance.
And you can to some extent rewind by dropping the current frame (unless your
code had side effects, but that's just another reason to avoid them ;) )

But I think my workflow is similar to yours. I often set a breakpoint in my
new code and just watch the state to see if it looks as expected, so small
tidbits of usage here and there.

------
greyman
From the article: > One thing developers spend a lot of time on is completely
absent from both of these lists: debugging!

I notice that times changed a bit. This was true in software engineering like
10 years ago, but in recent years there is much more emphasis on good
practices, constant refactoring, implementing lots of tests alongside the
production code, etc. I debug maybe 1-2 hours per month, as a full-time
programmer.

~~~
eksemplar
I agree on good practices, but often TDD is wasted time. Not on larger
systems, but on small systems with limited functionality where you build using
principles like SOLID so you always know where the flaw is, even without the
test.

We used to write an awful lot of tests on everything. When we stopped we
increased productivity by almost 60% at almost no cost.

As I said, we still work with TDD, but we only do it when it makes sense.

~~~
dtech
You don't have to do TDD for this to be useful or happen.

In my current project we follow a "bug -> reproduce bug in testcase -> fix
bug" method for some parts of the code. This has cause quite an extensive test
suite to develop for those parts of the system.

~~~
jnurmine
I'm curious... I can see the obvious value of having a testcase for a class of
bugs, but a testcase for a particular bug instance which was already fixed
earlier does not seem right, so I probably misunderstood something.

How often do the tests find a problem?

When it does find a problem, doesn't this mean that one hits a bug which
existed before?

Can you give an example of a case when the test was useful?

~~~
nhoe98thnuoe
This is known as regression testing, and it's extremely useful. For example,
you find some bug where, say, a calculation produces a nonsense result. You
fix it, then add a test for what you just fixed. 2 years from now, someone
refactors the code and reintroduces the bug because their refactor didn't take
into account all of the possible input cases. Your test now catches it.

Our regression tests have literally found hundreds of bugs over the years and
saved us a lot of time and embarrassment.

~~~
jnurmine
Thanks. Of course. I see what you meant now.

------
carusooneliner
More broadly, reverse engineering a codebase is a critical software activity.
If you can't reverse engineer a codebase you can't debug it or add to it.
Working with an existing code base is pretty much a given, unless you're
developer #1 on a startup. Your success as a software developer hinges on how
well you can work with an existing codebase.

One less celebrated but very valuable approach to grasp a codebase is the way
you document what you've learnt. While you can learn about a codebase through
exploratory debugging (mentioned by someone on a separate comment) you have to
persist that knowledge on "paper" in some way. My favorite ways to do that:

    
    
      - class diagrams (for static stuff like data structures, class relationships, etc.)
    
      - sequence diagrams (for dynamic stuff like which functions call which and data passed between them)
    

With good documentation for your own learning purposes, it'll become easier to
start working on a codebase and especially when you context switch, it'll help
you return to a codebase more easily.

~~~
JetSpiegel
Ideally, documentation would be written so that there is no need to reverse
engineer every project you wade into. Otherwise why share the source code in
the first place?

~~~
carusooneliner
There's various kinds of documentation of differing granularity. Typically the
high level documentation (coarse grained if you will) about architecture,
requirements, etc. stays good over time but finer grain documentation (the
kind I mentioned in my earlier comment -- data structures, order of function
invocation, etc.) gets stale quickly because source code is constantly
changing -- it gets refactored, plenty of bug fixes are put in, etc.

Reverse engineering is probably a loaded word, but in general digging in to
understand the codebase helps you work more efficiently and avoid introducing
bugs to the extent possible.

------
dboreham
Reading the comments here I get the impression folks are thinking about
"debugging MY code". In my experience when you are debugging you are almost
always looking at an issue in someone else's code.

------
acroback
I see a disturbing trend in industry especially in Bay area from my
experience.

Young engineers are bad at debugging, bad means real bad but good at
programming puzzles.

This points to the fact that people value puzzles over experience and in turn
miss the big picture.

Sure you can code up a balanced RB tree in 5 mins, but what will you do when
packets start showing up in bursts on your service? Can you find out that on a
live system?

I despise this new Bro culture of mugging programming puzzles from leetcode
and hackerank. Faltering at first real world challenge is not only
disappointing, but an insult to craft of engineering.

/Rant over

~~~
fancyfish
Echoing this and an earlier thread...interviewers could have debugging
exercises with an existing codebase. I have seen this ambitious approach at a
few startups. Instead of asking yet another sorting algorithm or HackerRank
brainteaser.

Until the application process changes, the applicants won't change.

~~~
convolvatron
interviewing is only a small part of the picture. mvp has so eroded the notion
of correctness that whole organizations don't even look for bugs anymore.

try upgrading the dependencies. wrap the service in a harness to make sure it
gets restarted when it fails. forget about proactively looking for bugs, wait
until they come in, and if you have time that week before they slip into the
'stale - never to be addressed' pile, spend a few minutes trying to reproduce
and mark 'works for me'

------
pjmlp
I use debuggers in anger since Turbo Vision based IDE for Turbo Pascal 6.0 on
MS-DOS.

If everything that one can do with a graphical debugger is single-step, step-
into and continue, then they are using like 1% of its capabilities.

Taking advantage of a graphical debugger, specially when the environment
supports code reload, is quite productive for interactive programming.

~~~
kjeetgill
One of the besting things about Java and having a strong IDE ecosystem.

When I was working in Java 7 + Eclipse the ability to hotswap in changes to
functions made debugging (even in production) a dream! Dropping a few new
lines of conditional logging into a service was crucial for those 3am war room
sessions.

Now, working in Java 8 + Intellij hot swapping fails constantly because
lambdas don't seem to compile is a stable fashion. Eclipse uses a more
development friendly compiler ECJ so I wonder if it has this solved.

~~~
pjmlp
I am yet to try out that scenario on Eclipse as I tend to refrain my FP
enthusiasm due to team members.

------
mjw1007
He writes « Perhaps people equate "debugging" with "using an interactive
debugger" »

I think it's useful to think of two independent 'axes' of debugging:

\- single-stepping vs reading traces

\- using specialist debugging software vs modifying the code

Most of the time I much prefer reading traces, and IDEs often have decent
primitives for setting sophisticated tracepoints, but the UI support for them
is often very weak (while adding a breakpoint might be a single key press).

So I've often found myself using 'printf'-style debugging because (until
compile times get very long) it's more ergonomic then using the debugger's
tracepoints.

I haven't tried rr yet. Does anyone know how good it is at this? I'd like to
be able to do things like define a keypress for a given tracepoint and toggle
its output on and off while I'm scrolling through a trace.

~~~
abhishekjha
> using 'printf'-style debugging

And the horror that descends upon you once you commit+push those statements.

~~~
pjc50
Either "don't do that then" or have a logging framework that lets you leave
enough printf in to diagnose crashes in the field.

~~~
abhishekjha
I used to debug using print statements earlier and that was because we were
not allowed to use any IDE. Now that I know hoe to use IDEs properly, things
have been better. And there is always logging and `git diff` to help you out.
Those colouring schemes really come handy.

------
stcredzero
There were Smalltalk server processes that would catch an exception, snapshot
their memory image. A developer could then come along, and open a full
interactive debugger on a live, running version of the system, which they
could then modify then run as a quick dev test.

------
azhenley
The academic Software Engineering community certainly does put a lot of
attention on debugging.

See my list of publications for a number of empirical studies on debugging and
tools to support more efficient debugging:
[http://austinhenley.com/publications.html](http://austinhenley.com/publications.html)

------
spenrose
I worked on petabyte-scale data at Mozilla. Here is a talk I gave on the
history of debugging and the ways in which doing distributed large data
analysis requires moving beyond printf() and STEP:

[https://www.youtube.com/watch?v=QHJBPzfrokU](https://www.youtube.com/watch?v=QHJBPzfrokU)

------
henrik_w
I agree with the author that a debugger is a poor fit for many systems.
However, debugging is essential, and I think debugging by checking logs works
very well in many cases (provided that the logging is good). Some of the
advantages (over debuggers):

\- Anybody can look at the logs, not just developers.

\- The logs show the sequence of events, not just a snapshot.

\- Feasible to do in a live system.

[https://henrikwarne.com/2014/01/01/finding-bugs-debugger-
ver...](https://henrikwarne.com/2014/01/01/finding-bugs-debugger-versus-
logging/)

~~~
M_Bakhtiari
A debugger that doesn't support those three things is just a lousy debugger.

~~~
seanmcdirmid
There are many different kinds of debugging, and a debugger optimized with an
interface for pinhole inspecting and stepping isn’t the best tool for logging
and log processing, it is ok for them to be separate things.

~~~
M_Bakhtiari
I never said not to log or look at logs, but a good debugger should be
possible to attach to a running process, and reverse debugging can give you
access to past events.

~~~
seanmcdirmid
Sure, but you are still dealing with a pinhole even if you can move that
pinhole around. It isn’t a complete debugging experience, nor was it meant to
be.

------
dm03514
I feel like it has a lot to do with the ambiguity involved in debugging, and
the fact that it is hard to teach.

I have found debugging to be fuzzy and largely based on experience, mental
models, and internal (scientific method based?) approaches.

There seem to be a relatively few debugging methodologies or frameworks. (ie
in performance/systems realm there are USE, RED, ...?). I have only started to
recently create a formal framework (a google doc I update after each incident)
after 9 years of engineering experience! Not because I wasn't interesting in
debugging, but it literally took 9 years worth of debugging incidents for
patterns to start to become apparent to me (i work devops/system so when there
is a general feeling of a problem I'm usually tasked with finding root
causes).

On a side note: so far the framework has been successful within my org and I
hope to formalize it enough to write about it in the near future :)

------
paulsutter
"90% of coding is debugging. The other 10% is writing bugs” - Bram Cohen

------
LargeWu
Somebody once posted in a Slack channel I was part of asking for things they
should include in a course they were teaching for new programmers. My #1
recommendation was how to read a stack trace. The second was how to put a
logging statement into your code to capture state.

------
busterarm
Just get them working on some mess of a WordPress project and you'll get them
all reaching for xdebug right quick :D

------
lolc
The result of debugging will be summed up in a commit or a ticket in Gitlab.
Why should Gitlab care about the process?

~~~
Mashimo
Maybe he wants something like a log analyzer similar to splunk?

Or something mobile clients send their exceptions?

Sadly the post is not very clear, so we can only guess.

------
erik_seaberg
I'm afraid of building a habit of making haphazard tweaks until it seems to
DTRT in one case. I don't like the idea of needing the machine to explain to
me how my own code actually works. The feeling of complete understanding is an
important motivator to me.

~~~
akerro
If you had a bug, then you didn't know what machine is doing. You think you
have an idea it's doing X, while it does Z. If you have ever written a bug
because you should have written ++x instead x++, then you need the machine to
tell you what it's doing, because it's not doing what you think.

If have never ever written a bug, contact me for a job offer, I'll pay you
300% of my salary.

~~~
comboy
> If have never ever written a bug, contact me for a job offer, I'll pay you
> 300% of my salary

I know just the guy. He was interested in learning how to code.

------
vfc1
I used to spend my days in the Java debugger, stepping through framework code
to troubleshoot application-level errors, as the stacktrace we had obfuscated
the error, or everything was simply broken.

Depending on the situation, I might spend most of my day debugging, as a way
to better understand the program and as a code analysis tool.

This was especially useful if dealing with a code base that I was not familiar
with, while in code that I wrote myself most of the time logging is
sufficient.

I'm not sure why the author thinks that debugging is not a priority for tool
makers, the debuggers that we currently have are awesome and have been so for
years.

------
watwut
Debugging is hidden here:

Bug handling is easy, fast, and friendly Information on “code flow” is clear
and discoverable

I use interactive debugger inside IDE or inside profiling tools. Debugging is
something I do alone, so it does not need special process support.

------
eftychis
I think the approach we should take is to pour more effort into minimizing the
risk of debugging being necessary. Good practices, better type checkers and
logic models (e.g. there was an article posted in the front page here about
using linear logic to push the boundaries of file systems). Debugging can be a
time sink and can become a painful task for fast distributed systems.

We should learn and hone that skill of course, as it does not only offer a
solution when lightning strikes, but a way for the developer to gain
comprehension of the "internals".

------
nhoe98thnuoe
In my opinion the reason that debugging isn't treated as a first-class
activity is that it isn't taught at all in schools. Or at least it wasn't when
I was in school. We were given about 2 sentences that said, "the debugger is
at /usr/bin/gdb. It can help you step through your code to find a bug." And
then we were thrown to the wolves with what is arguably one of the worst
debuggers in the world with no documentation and no help.

------
wilun
While we probably will always have to debug, and if not the "code" it will be
a specification formal enough so that it can be considered code anyway, there
are different ways to approach its role within the lifecycle of software
development: on the two extremes, one can "quickly" but somehow randomly throw
lines without thinking much about it, then try the result and correct the few
defects that their few tries reveal (and leave dozen to hundreds of other
defects to be discovered at more inconvenient times); or one can think a lot
about the problem, study a lot about the software where the change must be
done, and carefully write some code that perfectly implement what is needed,
with very few defects both on the what and on the how side. Note that the
"quick" aspect of the first approach is a complete myth (if taken to the
extreme, and except for trivially short runs or if the result does not matter
that much), because a system can not be developed like that in the long term
without collapsing on itself, so there will either be spectacular failures or
unplanned dev slowdown, and if the slowdown route is taken, the result will be
poorer as if a careful approach would have been taken in the first place,
while the velocity might not even be higher.

Of course, all degrees exists between the two extremes, and when going too far
on one side for a given application is going to cause more problems than it
solves (e.g. missing time to market opportunities).

Anyway, some projects, maybe those related to computer infrastructure or
actually any kind of infrastructure, are more naturally positioned on the
careful track (and even then it depends on which aspect, for ex cyber security
is still largely an afterthought in large parts of the industry), and the
careful track only need debugging as a non-trivial activity when everything
else has failed, so hopefully in very small quantities. But it is not that
when it is really needed as a last resort, good tooling are not needed. It is
just that it is confined to unreleased side projects / tooling, or when it
happens in prod it marks a so serious failure that compared to other projects,
those hopefully do not happen that often. In those contexts, a project which
need too much debugging can be at the risk of dying.

So the mean "value" of debugging might be somehow smaller than the mean
"value" of designing and writing code and otherwise organizing things so that
we do not have to debug (that often).

------
nicostouch
I often wonder why it's not treated as a first class citizen when teaching
programming. I think there should be a full CS course dedicated to it.

I put together [http://www.debug.coach/](http://www.debug.coach/) because a
guy I used to work with had better debugging skills than anybody and I noticed
it was because he always knew the right questions to ask.

------
codedokode
I think that is because there are no good free open source debuggers? In
Visual Studio you just set a breakpoint and examine the variables; it works
great. On Linux you are left alone against a command-line monster with
outdated weird command syntax.

gdb has an awful interface; it requires you to read a long manual and learn
outdated command syntax before even using it; it is often faster to add
logging and rerun the program. It is not a debugger for humans.

For comparison, JS debugger in Chrome devtools works pretty good and is easy
to use. It is really helpful and allows you to identify a problem very quickly
(faster than reading an introduction page for gdb). But it has problems
sometimes, when you try to set a breakpoint and it is set in another place or
is not set at all without any error messages.

I saw some comments here against visual debugging; maybe their authors had
experience with some buggy or poorly written debugger?

I also tried to use Firefox developer tools in several versions up to FF45 and
almost every time something didn't work. And when they work, they choke on
scrolling large minified files or heavy sites with lots of ads.

~~~
flukus
> In Visual Studio you just set a breakpoint and examine the variables; it
> works great. On Linux you are left alone against a command-line monster with
> outdated weird command syntax.

You're comparing an IDE to a command line environment, Linux has various IDE's
that are more comparable and I believe some standalone front ends to gdb,
windows also has windbg and dotnet mdbg that are the command line equivalents
of gdb that VS is interacting with for you.

Gdb (and windbg for that matter) is much more powerful than visual studio
debugging though, much like vim and similar tools it's not easy to learn but
it's easy to use once you have learned. Stop expecting instant gratification.

------
deepaksurti
Because most languages treat edit, compile, test, debug phases. No organic
evolution of your idea to code to running app all the while tweaking it
without restarts, which are pit stops that completely break your momentum.

That needs languages designed upfront with debugging etc as a first class live
feature.

------
cuddlybacon
One thing that may be relevant is that I was never introduced to debugging in
university at all. You were expected to just invent useful techniques on your
own. Without any exposure, it is hard to justify learning that over any other
topic you feel like you aught to be learning.

------
enriquto
Because debugging is not a first-class activity.

If you are careful when you program (assertions, tests, logging) you rarely
need to use a debugger. Time spend on a debugger is invisible and lost. It is
much better to spend time adding assertions, levels of logging, and writing
tests.

~~~
jlg23
Depending on the capabilities of a debugger, developers might have test
failures drop them into an interactive debugger that allows reloads/re-
execution of code units.

Debuggers can be I instrumented to do a lot of dev-only logging for you.

I _do_ write tests and assertions, but if those fail, I am dropped into a
debugger (if prog is executed interactively), I can immediately inspect the
state of my program and more often than not fix the problem on the fly.

~~~
mirceal
I think that, while this might work, the approach to managing state and
writing the tests is not ideal. For one, your tests should be fast (ie you
should be able to rerun them with almost 0 time penalty and see the results
instantly). Second, if it’s easier to stop the flow and look at the state /
modify the state than looking at what the state should be via the test setup
it’s possible that the abstractions you’re using are not quite right and/or
the code is tightly coupled.

~~~
jlg23
> I think that, while this might work, the approach to managing state and
> writing the tests is not ideal.

I strive to not manage state but to write purely functional code, it makes
life so much easier - see your second point as an example :)

------
yitchelle
If you needed to debug, it is a sign that you have made a mistake. Who wants
to admit to making the mistake? :-)

Seriously though, I imagine that the junior devs would have such a view of
debugging. But the matured devs would plan for it as they know their
limitations.

------
logfromblammo
For the same reason that the water treatment plant gets more respect than the
sewage treatment plant.

Everyone would prefer to provide something fresh and clean than to wade
through other people's poop.

------
bionsystem
Ask Bryan Cantrill. He is a first grade debugger.

------
fierro
has anyone written intelliJ plugins that deal with the debugger? I have an
interesting idea wrt to this, but writing an IntelliJ plugin has so far been
extremely painful. If anyone out there is interested send me a message and
let's chat

------
hannofcart
I would go so far as to suggest that if you need a debugger, you're probably
doing it wrong.

I have found that code that needs a debugger is code that is written in an
extremely stateful fashion.

The very reason why debuggers exist is to deal with code that has a dozen
variables book-keeping complex state that you need to track closely to figure
out how something works (or why something doesn't). Debuggers even have
"watches" to track something closely so that it doesn't change underneath you,
when you aren't looking.

To me this is a code smell. I would suggest that instead of using a debugger,
we ought to be composing small functions together.

Small and pure functions only need an REPL to test.

Once you make sure the function is behaving right, you can almost just copy
paste over the test cases you ran in your REPL into unit tests.

The simplest way to enforce this discipline is to do away with assignments,
and instead constrain oneself to using expressions. This forces one to break
code into smaller functions. Code written this way turns out to be much more
readable, as well as reusable.

I suggest that we eschew the debugger in favour of the REPL.

~~~
kitanata
This is perhaps one of the most harmful statements I’ve ever read on Hacker
News. You’re not doing it wrong if you use a tool to help you understand what
your program is doing. Should you follow good design patterns, like using
small functions when writing your software? Yes. Should you minimize complex
state? Sure. Should you use tools to help you understand what your program is
doing? Absolutely. The two are not mutually exclusive.

There are a LOT of different ways to write software. Some more stateful than
others. Some lower level than others. Some more asyncrounous than others. Some
more functional. Some more object oriented.

Your experience with the software you write in your day to day, is not the
same stack and may not even be in the same universe as what others are
attempting. Writing a React app is very different from writing a game in
Unity, which is very different than writing a game engine in C++ which is very
different that writing large scale services that talk to clusters of computers
and hardware devices, which is different than writing some low level library
in Rust or Haskell or doing data science in R or Octave.

Please fucking stop with this “one right way”, “you’re dodging it wrong”
dogmatic bullshit. Your limited worldview does not apply to ALL of software
development.

Use a fucking REPL if you want. Use a debugger if you want. Use logs and
traces if you want.

Just try to write good software, try to understand your code, and ignore
dogmatic and valiantly bad advice and opinions like the parent comment on
Hacker News.

~~~
hannofcart
> This is perhaps one of the most harmful statements I’ve ever read on Hacker
> News.

And here I thought I was writing an innocuous comment on debugging code.
Hyperbole much?

> There are a LOT of different ways to write software... Writing a React app
> is very different from writing a game in Unity, which is very different than
> writing a game engine in C++.

It's interesting that you brought up these 3 use cases. I started my career
working for a shop that wrote a game engine in C++, then moved to Unity. I now
write React apps for a living. Do I know you? :)

With the exception of a few corner cases, like portions of code that does
rendering, and HFT software, where performance concerns trump everything else,
what I have seen in that time is the following:

1) decomposing your code into smaller functions is objectively better than NOT
doing so. 2) writing functions that don't mutate its local variables is
objectively better than writing functions that DO.

By "objectively better", I mean that the code written conforming to the above
have the following characteristics: \- more readable than code that does not.
\- more testable than code that does not. \- more re-usable than code that
does not.

It's on these two assumptions that I build my case for eschewing the debugger
altogether in favour of the REPL. If you write code conforming to the above,
you have absolutely no need for a debugger.

Having said that, it is possible that you need a debugger to wrap your mind
around code bases that you inherit, which were written poorly (or
equivalently, in a very "object oriented" fashion).

~~~
kitanata
I don’t disagree with your principals of good code quality. I disagree that by
following those principals you no longer need to use a debugger or to develop
debugging skills. Your post is harmful because it suggest to junior developers
that if they must use a debugger they must be developing their software in a
poor fashion. This is not true. There are many good reasons to use a debugger,
including to develop software or to explore a codebase and to debug your code.

~~~
hannofcart
> I disagree that by following those principals you no longer need to use a
> debugger or to develop debugging skills.

Using a debugger (as in, software where you step through code) and developing
"debugging skills" are entirely different things. I was only commenting on the
former.

> Your post is harmful because it suggest to junior developers that if they
> must use a debugger they must be developing their software in a poor
> fashion.

Would it be better if I said: "if you need a debugger, you have are either
mucking around in poorly written code that you inherited or you're probably
doing it wrong"?

> There are many good reasons to use a debugger, including to develop software
> or to explore a codebase and to debug your code.

I concede that exploration of a codebase is a valid use of a debugger.

------
thecodeboy
Prejudice. The same reason NASA janitors aren't glorified as the astronauts
are.

~~~
coldtea
Well, the astronauts could always wipe the floors themselves, or just work in
a dirty building.

The janitors probably lack the skills to go to space and command a spaceship.

