Live data from Hacker News

The Grug Brained Developer (2022)

grugbrain.dev

531–540 of 603 posts

Re: The Grug Brained Developer (2022)

#531
post #519

Earlier quoted context omitted.

How many people actually write exhaustive tests for everything that could possibly be null? No one I've ever met in my mostly-C# career. I can confirm that at least 30% of the prod alerts I've seen come from NullReferenceExceptions. I insist on writing new C# code with null-checking enabled which mostly solves the problem, but there's still plenty of code in the wild crashing on null bugs all the time.

> How many people actually write exhaustive tests for everything that could possibly be null? Of those who are concerned about type theory? 99%. With a delusional 1% thinking that a gimped type system (read: insufficient for formal proofs) is some kind of magic that negates the need to write tests, somehow not noticing that many of the lessons on how to write good tests come from those language ecosystems (e.g. Haske…

> to see how they ended up in that situation

The "how" is almost always lack of discipline (or as I sometimes couch it, "imagination") but usually shit like https://github.com/microsoft/SynapseML/issues/405#:~:text=cl...

I've had to learn in my career not to open other people's projects in a real IDE because of all the screaming it does about "value can be null"

Re: The Grug Brained Developer (2022)

#533

Earlier quoted context omitted.

Eh, it's there for those who want it, but nobody uses it

See this just sounds like you do not have an engineering culture or learning, enabling, and using debuggers.

Not sure what an engineering culture is, but I don't want it. I just want to attach a debugger to our stuff (not the unit tests).

Re: The Grug Brained Developer (2022)

#534
post #516
post #491

Earlier quoted context omitted.

Oh the errant nulls only ever came up when I was writing dynamically typed languages. Is that what you're asking about?

Not specifically, but if that is where your example comes from, that’s fine. It’s all the same. What have you got?

On a PHP project I ran into cases where I changed the shape of an object (associative array) I was passing around and forgot about one of the places I was using it. Didn’t turn into a production bug but still was the kind of thing I would rather be a squiggly line rather than remembering to rerun all the paths through the code. Didn’t help that we were testing by hand.

Same thing on the front end in JS: change the shape of some record that has more places using it than I could remember. Better tests would have caught these. A compiler would be even better.

FWIW I’ve written a lot of tests of code written in all of the languages I like. You absolutely need tests, you just don’t need them to be as paranoid when writing them.

Re: The Grug Brained Developer (2022)

#535
post #211

Earlier quoted context omitted.

It's absolutely not an anti-pattern if you have appropriate tools to handle different levels of logging, and especially not if you can filter debug output by area. You touch on this, but it's a bit strange to me that the default case is assumed to be "all logs all the time". I usually roll my own wrapper around an existing logging package, but https://www.npmjs.com/package/debug is a good example of what life can be…

I know a lot of people do that in all kinds of software (especially enterprise), still, I can't help but notice this is getting close to Greenspunning[0] territory. What you describe is leaving around hand-rolled instrumentation code that conditionally executes expensive reporting actions, which you can toggle on demand between executions. Thing is, this is already all done automatically for you[1] - all you need is…

I agree that logging all functions is reinventing the wheel.

I think there's still value in adding toggleable debug output to major interfaces. It tells you exactly what and where the important events are happening, so that you don't need to work out where to stick your breakpoints.

Re: The Grug Brained Developer (2022)

#536
post #534
post #516

Earlier quoted context omitted.

Not specifically, but if that is where your example comes from, that’s fine. It’s all the same. What have you got?

On a PHP project I ran into cases where I changed the shape of an object (associative array) I was passing around and forgot about one of the places I was using it. Didn’t turn into a production bug but still was the kind of thing I would rather be a squiggly line rather than remembering to rerun all the paths through the code. Didn’t help that we were testing by hand. Same thing on the front end in JS: change the sh…

> A compiler would be even better.

Right, but the condition here is that the languages that are expressive enough to negate the need for testing are, shall we say, unusable. In the real world people are going to be using, at best, languages with gimped type systems that still require testing to fill in the gaps.

Given that, we're trying to understand your rejection of the premise that the tests you will write to fill in those gaps will also catch things like null exceptions in the due course of execution. It remains unclear where you think these errant nulls are magically coming from.

I'm not convinced "Didn’t help that we were testing by hand.", "Better tests would have caught these." is that rejection. Those assertions, while no doubt applicable to your circumstances, is kind of like saying that static type systems don't help either because you can write something like this:

    data MaybeString = Null | Str String
    len :: MaybeString -> Int
    len (Str s) = length s

    main :: IO ()
    main = do
        print (len Null) -- exception thrown
But just because you can doesn't mean you should. There is a necessary assumption here that you know what you are doing and aren't tossing complete garbage at the screen. With that assumption in force, it remains uncertain how these null cases are manifesting even if we assume a compiler that cannot determine null exception cases. What is a concrete example that we can run with to better understand your rejection?

Re: The Grug Brained Developer (2022)

#537

“Good debugger worth weight in shiny rocks, in fact also more” I’ve spent time at small startups and on “elite” big tech teams, and I’m usually the only one on my team using a debugger. Almost everyone in the real world (at least in web tech) seems to do print statement debugging. I have tried and failed to get others interested in using my workflow. I generally agree that it’s the best way to start understanding a s…

Debuggers are great. I too have tried and failed to spread their use.

But the reason is simple: they are always 100x harder to set up and keep working than just type a print statement and be done with it.

Especially when you're in a typical situation where an app has a big convoluted docker based setup, and with umpteen packers & compilers & transpilers etc.

This is why all software companies should have at least one person tasked with making sure there are working debuggers everywhere, and that everyone's been trained how to use them.

There should also be some kind of automated testing that catches any failures in debugging tooling.

But that effort's hard to link directly to shipped features, so if you started doing that, management would home in on that dev like a laser guided missile and task him to something with "business value", thereby wasting far more dev time and losing far more business value.

Re: The Grug Brained Developer (2022)

#538
post #519

Earlier quoted context omitted.

> How many people actually write exhaustive tests for everything that could possibly be null? Of those who are concerned about type theory? 99%. With a delusional 1% thinking that a gimped type system (read: insufficient for formal proofs) is some kind of magic that negates the need to write tests, somehow not noticing that many of the lessons on how to write good tests come from those language ecosystems (e.g. Haske…

> to see how they ended up in that situation The "how" is almost always lack of discipline (or as I sometimes couch it, "imagination") but usually shit like https://github.com/microsoft/SynapseML/issues/405#:~:text=cl... I've had to learn in my career not to open other people's projects in a real IDE because of all the screaming it does about "value can be null"

That's a tough bouncing ball to follow as it appears that the resolution was to upgrade to a newer version of a dependency, but if we look at that dependency, the fix seems to be found somewhere in this https://github.com/microsoft/LightGBM/compare/v2.2.1...v2.2....

There is admittedly a lot in the update and I may have simply missed it, but I don't see any modifications, even additions, to tests to denote recognition of the problem in the earlier version. Which, while not knowing much about the project, makes me think that there really isn't any meaningful testing going on. That maybe be interesting for what it is, I suppose, but not really in the vein of the discussion here about where one is using type systems and testing to overcome their personal limitations.

Re: The Grug Brained Developer (2022)

#539

Earlier quoted context omitted.

debugging is useful when your codebase is bad: imperative style, mutable state, weak type system, spaghetti code, state and control variables intermixed. i'd rather never use debugger, so that my coding style is enforced to be clean code, strong type system, immutable variables, explicit error control, explicit control flow etc

You've gotten downvoted but I think you're correct - if there were no debuggers, the developers would be forced to write (better) code that didn't need them.

Thank you for defending the common sense opinion. Some people here are too reactionary

Re: The Grug Brained Developer (2022)

#540
post #470

Earlier quoted context omitted.

Assume that there was room for null. What is your concrete example of where null becomes a problem in production, but goes unnoticed by your tests?

Relevant: Google Cloud Incident Report – 2025-06-13 - https://news.ycombinator.com/item?id=44274563 - June, 2025 (220 comments)

Not exactly as, in that case, they chose not to test the error condition for correct behaviour at all. The problem wasn't just the null pointer condition, but also that the coded behaviour under that state was just plain wrong from top to bottom.

More careful use of the type system might have caught the null pointer case specifically, but the compiler still wouldn't have caught that they were doing the wrong thing beyond the null pointer error. In other words, the failure would have still occurred due to the next problem down the line from a problem that is impossible to catch with a partial type system.

While a developer full of hubris who thinks they can do no wrong may let that slide, our discussion is specifically about a developer who fully understands his personal limitations. He recognizes that he needs the machine to hold his hand. While that includes leveraging types, he understands that the type system in any language he will use in the real world isn't expressive enough to cover all of the conditions necessary. Thus he will also write tests to fill in the gaps.

Now, the premise proposed was that once you write the tests to cover that behaviour in order to fill in the gaps where the type system isn't expressive enough, you naturally also ensure that you don't end up with things like null pointer cases by way of the constraints of test execution. The parent rejected that notion, but it remains unclear why, and we don't yet have a concrete example showing how errant nulls "magically" appear under those conditions.

"I don't need testing" isn't the same thing, and has nothing to do with the discussion taking place here.

Post reply on HN