Hacker News new | ask | show | jobs
by Mindless2112 1331 days ago
The state machine example is a good one. It's a textbook case of unreachable code.

The null-checking example is not good. If the external API returns a null where you don't expect one, UnreachableException will be thrown. It doesn't matter if the documentation says it will never be null; clearly the code isn't unreachable. All you need to reach it is bad data! (InvalidDataException would be a better choice, though arguably not an ideal one.)

If you can write a unit test that makes your code throw UnreachableException, you almost certainly should be throwing a different exception.

3 comments

This was my initial thought as well, but from the text I gather there is a flow like this:

[Input Data, maybe null] -> Validate field is not null -> Call this method with the assertion.

This is a small bug-bear for me with nullable types and I wish there was a better way to do it, but many languages allow you to smart-cast away nulls, but only within the local scope. If you want to pass a struct-type around which has nullable fields, but you have already checked for non-null (like this one) you need to convert to a different struct-type, which doesn't have the nullability on its fields. I can't think of a good way round this - as you say with the unit test remark, there is nothing to stop another piece of code calling this method with nulls.

> If you want to pass a struct-type around which has nullable fields, but you have already checked for non-null (like this one) you need to convert to a different struct-type, which doesn't have the nullability on its fields.

Which is exactly what IMO the author should have done. It's actually a reasonable use-case for inheritance:

    #nullable enable

    record SlackEvent
        ( int EventId
        , string Content
        , string? TeamId
        );

    record TeamSlackEvent
        ( int EventId
        , string Content
        , string TeamId
        ) 
        : SlackEvent
            ( EventId : EventId
            , Content : Content
            , TeamId : TeamId
            );
> If you can write a unit test that makes your code throw UnreachableException, you almost certainly should be throwing a different exception.

ArgumentNullException, InvalidOperationException... There's plenty that have been around since the beginning.

What's more important, that I didn't see in the first two examples, are useful error messages.

`ArgumentNullException` was my first idea too. I would and did use it for this kind of purpose.
Invalid date means you got a value that’s not a valid date which is different than falling into an impossible state.
Invalid Data, not date
I would guess they were spell-checker-corrected, and meant "data" both times: the sentence makes sense with either, though "data" is obviously what makes it make sense in this context :)