The latter can easily be implemented by having a 'mem' command together with a command line interface.
Stepping through code sounds nice but for realtime processes (like on a microcontroller) it runs out of steam quickly. What I have been doing for the past 20 years:
- have a command line interface on a UART
- have status commands which shows stuff like character received, number of interrupts
- if available, implement hard fault handlers and make these print a stack dump
- add extra commands to query status or dump memories (think about an eeprom for example; how can you be sure the correct data is written to it?)
- write complicated routines on a PC first + use a test bench to verify
- allow to dump measured and status data in CSV format for analysis
Once you have a basic command line interface going you have a very simple eco system which is portable as well. There are debuggers which allow to read variables realtime over JTAG/SWD but these aren't very cheap. And they won't do you any good solving problems in the field. If you have a problem in the field (IOW: a board mounted somewhere in a machine far away from you) you can ask a field engineer to connect to the serial port and query the status of the device or just dump data.
That sounds like a very good way, as well!
Some people, actually implement, what amounts to small/light resource scripting/interpretive languages, such as tcl, lua or Forth etc. Allowing quick examination of memory (like you described), or even running small scripts, to check out I/O functionality.
But, there are (thankfully rare), highly complicated bugs, which can be very difficult, without the right debugging equipment.
But, yes. You are right. Once you are experienced enough at this, a full/proper debugger, is only very rarely needed.
Your method, as described, can even handle most or even all, of what I just said, as well. if done well enough.
But, if it was a very big and important project. I would still like to see proper debugging equipment used, where possible. But, as you say, it sometimes isn't possible or practicable.
E.g. A remote controlled, model boat project, where it will be in the water, 50 metres away, sailing at speed, when you are trying to debug the software. A 50 metre long ribbon-cable, would probably sink the boat, and collide with other lake users.