loading...
Cover image for No method too small

No method too small

amoenus profile image Romans Pokrovskis Originally published at amoenus.dev ・2 min read

This story starts with a call from the 1st line support that users were getting intermittent-production-only error in one of the key application my team were working on.

The problem was that the application was behind the hardened environment that we had no access to.

The only thing we could do is enable logging which in itself took a whole week to get approved. And the result the Developers favourite - NullReferenceException in one of the biggest methods, I've ever seen in my whole career. Needless to say, that was not very helpful and we were no closer to the solution.

What. A. Pain.

Frustrated with the issue and with business breathing down my neck I started slicing this Monster of a method into smaller and smaller chunks. Even if some action was just a one-liner that would not stop me to create a method. At one point I could no longer care for method names resorting to such classics like Method1, FooBar123 and DoStuff.

But. It. Worked.

After the next deployment logs were showing the same NullReferenceException but now the stack trace pointed me to some Method13.

The resulting stack trace finally allowed to pinpoint the issue. The fix then was just a simple null check.

While Dev team who did not appreciate my creative method naming it was obvious to everyone that even that was better than one big blob of code.

It might seem silly to separate the most obvious one-liners into their own methods and sometimes even whole classes but not living through that experience alone is worth it for me.

Did you ever found yourself in a situation where you wished your stack trace was just a little bit more in-depth? Tell me in the comments ^_^

So now go and look at your code and see if you can pepper it with smaller methods so that you stack traces can pave your way to your debugging success.

Discussion

pic
Editor guide
Collapse
moopet profile image
Ben Sinclair

Did you ever found yourself in a situation where you wished your stack trace was just a little bit more in-depth? Tell me in the comments ^_^

Yeah. Especially with PHP, where exceptions and error handling were apparently designed by some kind of moustache-twirling Disney villain.

I started off by adding this to my Vim config:

  autocmd FileType php nnoremap <buffer> <leader>dump Oheader('X-XSS-Protection:0');ob_get_clean(); echo '<pre>'; var_dump(); echo '</pre>'; die(__FILE__ . ':' . __LINE__);<esc>2F(a
  autocmd FileType php nnoremap <buffer> <leader>back Oheader('X-XSS-Protection:0');ob_get_clean(); echo '<pre>'; foreach (debug_backtrace() as $d) { echo $d['file'] . ':' . $d['line'] . ' ' . $d['function'] . "()\n"; } echo '</pre>'; die(__FILE__ . ':' . __LINE__);<esc>^

which meant I could use <space>dump to dump a variable regardless of the current state of the output buffering, and <space>back to give me a simplified backtrace. Why couldn't I just print out debug_backtrace(), I hear you ask? Because PHP usually dies when you do that, because recursive calls cause the process to run out of memory while trying to print your debugging message. Yes.

When that wasn't enough, and I couldn't step through with a debugger (happens more than you'd expect) I wrote my own entire backtrace/debug module which shows you context, lets you click through to bitbucket or github or wherever the code is, lets you open each line in your local editor, gives info about VCS branches, PHP versions, that sort of thing. I had to use a lot of hacks to get it to work because PHP is so unfriendly towards debugging. But it does clever things like detecting if the exception was from PDO and printing the faulting SQL. I was quite pleased with that.

Collapse
rushyotakha profile image
RushyoTakha

I'm a big fan of using expression-bodied members and writing methods in an almost functional style (ala F#) for this reason and more. It aligns well with SOLID design principles in general and it's not just more debuggable, it's generally far more testable.

As an aside, the library OneOf kills NullReferenceExceptions dead by adding the ability to use F#-style unions in C# - I hardly see them anymore. Finding that was another product of my time exploring F#!