• Little Bobby Tables (unregistered)

    Time to have this code an""ed.

  • bvs23bkv33 (unregistered)

    void is our god

  • P (unregistered)

    It hasn't caused any errors so far because, well, they probably haven't actually used it. Or even tested it.

  • (nodebb) in reply to P

    Or their tests don't actually check anything and also eat all exceptions, which is not unknown

    Addendum 2019-12-11 07:54: They execute the code of course, to make sure the coverage metrics are satisfied...

  • Scott (unregistered)

    Case-sensitive, so it will miss the cases of "Null", "nULL", "NULL", though. Nice way to drive someone crazy--"sometimes, data is corrupted but not always".

    Of course, I work with a system where the original knucklehead developers set all data which is a nullable value type in the database (datetime/int/long/etc) to MinValue before passing it up to the application layers, instead of just defining that data as int?/DateTime?/long?/whatever.

    I guess it's a lot easier to check "if thing == Int32.MinValue" than it is "if !thing.HasValue".

    Just kidding. It's not. Needless to say, this application is a trainwreck. Slowly refactoring to normalcy. Or at least, less bad.

  • Herr Otto Flick (unregistered) in reply to Scott
    Case-sensitive, so it will miss the cases of "Null", "nULL", "NULL", though.

    JSON is case sensitive too, so you would not expect a serialiser to produce NULL for a null value.

  • Anonymous') OR 1=1; DROP TABLE wtf; -- (unregistered)

    This is a clbuttic WTF.

  • (nodebb)

    https://www.thefreedictionary.com/words-containing-null

    'Nuff said...

  • my name is missing (unregistered)

    If a null falls in the forest, does it make a sound?

  • (nodebb) in reply to my name is missing

    only if it hits an anti-NULL , resulting in an explosion of #UNDEFINEDs

  • (nodebb)

    Vaguely related: Excel has this annoying behavior where a cell you never touched is super-ultra-empty, but if you type anything in there and then delete everything the cell, it's now only sorta-kinda-empty and is treated differently by functions like ISEMPTY() . WHether or not the menu Clear/All works as you might have expected depends partly on what version of Excel you're running.

  • Jaime (unregistered) in reply to Scott

    I guess it's a lot easier to check "if thing == Int32.MinValue" than it is "if !thing.HasValue".

    I see a lot of people spending time thinking about how to put in a stand-in value that means "this thing has no value". Those people keep forgetting that that's what null already means. I see the same people put defaults on database columns, then use data access layers like Entity Framework, and wonder why their defaults never work.

  • (nodebb)

    Everybody knows that the correct solution is to serialize null integers as unix date epoch, 1970-01-01 00:00:00 UTC.

  • Devil's Advocate (unregistered) in reply to Jaime

    While I won't defend the practice in general, I have been tempted to use a stand-in value for specific cases. Mainly, where null is not an option, such as MSSQL primary keys. In this case, where there was a top level and multiple sub levels which have the same data points, just broken out. It'd be nice to have a single table for this, but since primary keys don't allow nulls (even when uniquely defined), it's either duplication or stand-in values.

    tl;dr: Sometimes you have to work around restrictions around nulls.

  • VI (unregistered) in reply to Jaime

    Those people keep forgetting that that's what null already means.

    I've worked with people who have been "trained" that "null is the root of all evil, never ever consider using null". These people need some replacement for null, so they make up a new one. That's how you end up with code that has 4 different values that mean "null" (but only one of these can be checked by static tools - the one defined by the language). Optional<T>, NULLVALUE = 0, hasValue() ? getValue() : -1 (getValue() will throw an exception if there isn't one)...

  • Jaime (unregistered)

    I saw some Brainiac use DateTime.MaxValue in and EndDate field to mean "has no end date". The problem is that DateTime.MaxValue has a time component of 23:59:59.999999, but after round-tripping through the database, came back as 23:59:59.999000 due to MSSQL's defaults. So, a field set to DateTime.MaxValue won't compare successfully to DateTime.MaxValue if you leave the UI and come back. Good times were had by all.

  • Jaime (unregistered)

    At my current job, one table uses "1/1/1980" for null in a birth date field. Let that sink in for a minute.

  • Silverfox (unregistered)

    Inherited a database in which it seems that the developers did not understand cascading deletes. So when a person's record was deleted (yes, I know) all that happens was the surname was changed to "KILL".

    Every sql statement ever had to include a clause to exclude these records. Performance was abysmal.

    Then a nice Asian family named KILL turned up ....

  • siciac (unregistered) in reply to VI

    I've worked with people who have been "trained" that "null is the root of all evil, never ever consider using null".

    That training is when devs ask, "why am I tediously writing out all these types, when any dereference can potentially fail?"

    And it's continued when devs try to debug these failures and realize the null contains no context to indicate where the failure actually occurred.

    Nulls may not be the root of all evil, but they're pretty evil.

    These people need some replacement for null, so they make up a new one.

    No, nulls are a replacement for throwing exceptions or returning error codes. Nulls never had well defined semantics, and they're found everywhere they shouldn't be because it's easier to return "null" than to write up an error message.

    Optional was not invented to replace null, rather monads (and related ideas like F#'s computation expressions) are a far more general and mathematically sound way of handling errors and state. Those ideas have been backported as promises, streams, optional, etc.

    getValue() will throw an exception if there isn't one

    If throw() was a function, it'd have a void return value, since it's not returning any value. Null is pretending to be a void (or bottom) value, so it is an exception... but, again, with "fail at the worst possible time, possibly months later" semantics instead of "fail fast."

  • siciac (unregistered) in reply to Jaime

    I saw some Brainiac use DateTime.MaxValue in and EndDate field to mean "has no end date".

    Nah, that's on you, because you should use range arithmetic instead of checking directly. After all, it should work if a user makes up a far future date to accomplish the same end.

  • Jaime (unregistered) in reply to siciac

    The problem was that the UI has a checkbox and date/time picker for the End Date. If they unchecked the box, the underlying value was filled with DateTime.MaxValue. The bug was that if you set "no end date", then went back into the form, the UI showed that and end date of 12/31/9999 was set.

    The "is it in range" code did do range arithmetic. The original dev coded the UI to make that range arithmetic slightly simpler, but in doing so, he built a UI that annoyed the users.

    Does your "that's on you" comment mean that since the end result is accurate, the UI horribleness must be tolerated?

  • xtal256 (unregistered) in reply to cellocgw

    "only if it hits an anti-NULL , resulting in an explosion of #UNDEFINEDs"

    Or as they call it in Death Stranding, a "void out" :)

  • Chris (unregistered)

    I'm finding numerous bugs in our code where parameters have a default value of 0 to represent "not specified / use default behaviour". This is often for bit masks, where the default behaviour is as if the bitmask was set to all 1's / true. Unfortunately, 0 is a valid parameter in some edge cases. Obviously, the default value should be -1, which not only provides the expected default behaviour, but also allows you to skip the check for if the parameter is equal to the default value. I.e. previous code would say if (mask == 0 || (mask & (1 << i)) > 0) { ... }.

  • gidds (unregistered) in reply to Jaime

    Actually, null can mean one of several different things: not present, not loaded yet, not applicable, invalid, or unknown.

    Sometimes you need to distinguish two (or more) of those, and so need to pick at least one special non-null value. (Though if you can find one that will genuinely never occur in normal use, and document it thoroughly, it's not necessarily a WTF.)

  • PimPamPuifeltje (unregistered) in reply to Jaime

    I've seen the use of 12/31/1899 as well..

  • Kurbein (unregistered) in reply to Jaime

    For https://dynamicsuser.net/nav/w/navdev/86/native-navision-database reasons, MS Dynamics NAV defines all colums in all tables as NOT NULL, providing default values for all of them. In the case of dates, it uses '1/1/1753', which happens to be DateTime.MinValue for the undelying SQL Server datetime type (also for https://www.itworld.com/article/2823335/128452-Just-dating-The-stories-behind-12-computer-system-reference-dates.html#slide5 reasons).

    The worst offender though is varchar columns, where the default is ' '. Yes, 1 space, not even the empty string.

  • (nodebb) in reply to Silverfox

    Easy solution. Change the given names of all deleted entries to "DESTROY" as well and update the whole application to only filter out DESTROY KILL instead of everyone else with that particular surname.

  • Little Bobby Tables (unregistered) in reply to a person

    Excuse me? Monsieur and Madame DeStroy are asking where their data has gone.

  • WTFguy (unregistered) in reply to Scott

    @Scott Ref ... Of course, I work with a system where the original knucklehead developers set all data which is a nullable value type in the database (datetime/int/long/etc) to MinValue before passing it up to the application layers, instead of just defining that data as int?/DateTime?/long?/whatever.

    I wonder when this system was designed?

    The .Net framework gained nullable types in 2005 so anything designed much before 2006 would probably not have used that new-fangled scary tech. Big dev shops tend to be conservative about embracing the latest features, and tiny shops tend to be clueless about them. The popular ORM mappers of the time lagged even more.

    Agree completely that if your system was a greenfield from after about 2008 using arbitrary sentinel values instead of null as the value-absent signifier was/is WTF.

  • Jaime (unregistered) in reply to PimPamPuifeltje

    I've seen the use of 12/31/1899 as well.. Yes, but there are far fewer people out there in the real world born in the 19th century. We have dozens of clients with an actual birth date of 1/1/1980.

  • Some Ed (unregistered) in reply to Jaime

    The place where I worked in 1997 had a type of account that usually had an expiration date of 2 years. You could, of course, request extensions through an automated system, but each extension was only good for 2 years from when you requested that extension.

    They used a magic 'will not expire' date of 12/31/1999.

    So, of course, I requested an extension for my account on 12/31/1997.

    My contract was ended in 1998. If their processes were good, my account was removed at that time. But if their processes were good, they would have responded more favorably to a contractor working their Y2K review reporting that particular issue was going to be a major Y2K issue. So the question is, did my account get removed in 1998, while they were doing another round of Y2K stuff in 1999, at the end of 1999, or is it still active?

  • nasch (unregistered)

    "No, nulls are a replacement for throwing exceptions or returning error codes."

    Where did you get that idea? Null can simply mean the field has no value. There is no reason to think that must be an error condition. Middle name, for example. Not everyone has one, so it's appropriate to leave the field null for people who don't.

Leave a comment on “Null Serializer”

Log In or post as a guest

Replying to comment #510265:

« Return to Article