Coding in the Debugger (2007)(tidyfirst.substack.com) |
Coding in the Debugger (2007)(tidyfirst.substack.com) |
In programming environments with very powerful debuggers like .NET this is relatively common since it allows you to do a lot of stuff at fly.
Change values, evaluate expressions, change function's code, jump ahead and behind, etc, etc.
Once you try this you'll never want to go back to print-debugging (except for specific cases)
Want to check the content of a buffered image? Just run ImageIO.write(...) while the application is stopped. Want to check the current working directory? Paths.get(".").toAbsolutePath()
Heck you can even add code as breakpoint condition (which does not need to stop at the breakpoint), e.g. for some on the fly print debug. Changing values does not have to be a manual process but can also be injected as breakpoint condition.
This is why going from Python to Go can feel like going backward. IMO, even compiled languages should have an "interpreted mode" for development. Once the development is complete, the code can still be compiled to get the benefits of runtime performance.
Java, Scala, .NET (VB, C#, F#), C++, Haskell (Leksah/GHCi), OCaml
Just looked it up again since it's been so long. Looks like DataDog acquired them and are ending the product for an in-house replacement, quite a shame.
Exactly, that's what I meant
What’s also really neat is to be able to work “inspector-driven”. By that I mean to inspect an object and send messages to it directly in order to understand how to interact with it. This becomes even more true if you need some temporary global data that has no permanent reference to hang around for a bit longer.
Question: I want to make a tutorial about creating a Selenium scraper with Pharo along with some data visualization and post it on here. I have noticed that Pharo is really strong on those things. Does anyone have an idea which site I should pick? Perhaps Hacker News itself? Also, the tricks I will be showing there would also be really handy for Selenium web tests. I wonder if people ok HN would be interested in that.
TDD gives programmers a false sense of correctness. The temptation to "mess around with it until it passes" is far too great.
[1] https://ssw.jku.at/dcevm/ [2] http://dcevm.github.io [3] http://hotswapagent.org [4] https://www.jrebel.com
Here's an anecdote I heard once about Minsky. He was showing a student how to use ITS to write a program. ITS was an unusual operating system in that the 'shell' was the DDT debugger. You ran programs by loading them into memory and jumping to the entry point. But you can also just start writing assembly code directly into memory from the DDT prompt. Minsky started with the null program. Obviously, it needs an entry point, so he defined a label for that. He then told the debugger to jump to that label. This immediately raised an error of there being no code at the jump target. So he wrote a few lines of code and restarted the jump instruction. This time it succeeded and the first few instructions were executed. When the debugger again halted, he looked at the register contents and wrote a few more lines. Again proceeding from where he left off he watched the program run the few more instructions. He developed the entire program by 'debugging' the null program.
1. Greenfield new development, on unknown parameters (complicated APIs, data frames). I like to use Jupyter Notebooks for that. I use them like a really powerful repl, nothing lives permanently in a Notebook.
2. Type Driven Domain Driven development. Either as a result of building a running MVP through 1, or on a domain you control / understand well. You start from frist principles and model out the flow in Types (usually DataClasses in Python).
3. Debugger driven "Adding Features/ Debugging". Obviously, we use the Debugger to debug, but it can also be very powerful to add a feature to a large system.
If you mutate state all over a method it is harder to "restart" the method after changing it. Instead I tend to either not mutate state and return the result or work with local variables and just change the object at the very end of the method.
Or might start to more separate a lock/transaction from what is processed within because when "restarting" the method you don't want to relock it.
I was always doing stuff on windows/macOS/iOS/Android client libraries so I was always jealous of linux systems programmers who get to leverage Mozilla's rr tool. That's the coolest debugging tool I've ever seen.
Naturally similar stuff also exists in Smalltalk and Common Lisp environments.
That said, GPU rendering is one of the things that deterministic replay could be most useful for, so it's unfortunate that this doesn't work in rr for now.