• FEo (unregistered)

    If you're just tapping the shift key it's probably more akin to playing the drums than the piano

    (how's that drool drummer? coming out of both sides of the mouth? Awesome! Means the stage must be level)

  • Hannes (unregistered)

    Jesus... and I always use "object.ToString()". Now I know what I'm doing wrong!

  • (disco)

    now I feel like I don't deserve it because you guys basically gifted it to me.

    Anal Fristing

  • (cs) in reply to Hannes

    First sign of a WTF: code (of whatever quality) which at best replicates existing library functionality.

  • (disco)

    It occurs to me that the "representative line" could simply be a bogus attempt at enabling all the "else if" lines to have the same layout. The if() condition is - going by the writer's description - always false, so it will never actually happen, but it allows all the meat-lines to format tidily.

    None of that excuses anything about any of this article. It's amazing the amount of fucknuttery you'll find in any codebase of significant size, but this wins prizes for effort as well as achievement.

  • (disco)

    The real WTF is this: the original developer was allergic to letting native data-types cross module boundaries. Every function accepted all of its parameters as strings. Every function returned strings. Every function depended on this class to interact with values that could easily have been passed in natively.

    Heh, that makes me hope that this stuff was intended to be used with Powershell, where we're always told how awesome it is that you don't have to pass text around.

  • (disco)

    There are entire languages that work this way. Us Tclers got smart however and eventually developed an object that had the string representation that all objects have and a second representation to cache the last used non string type of the value.

  • (disco)

    It seems like there was a missed opportunity to Stringize the values into an XML document which would then be passed as the parameters for every function. That would be really enterprise-y.

  • (disco)

    string.Empty isn't actually a const - it's static readonly. It is entirely possible to use reflection to blow over it with another value or null. A null which we can be damned sure the garbage collector won't take from us.

  • (disco)

    private static string StringizeDate(DateTime? value) { if (!value.HasValue) return null;

    var s = String.Format(_formatProvider, "{0:yyyy}-{0:MM}-{0:dd}T{0:HH}:{0:mm}:{0:ss}", value.Value);
    if (value.Value.Kind == DateTimeKind.Utc) s += "Z";
    return s;
    

    } That is actually sane and makes good use of the String format library

    I do not really agree:

    private static string StringizeDate(DateTime? value)
    {
        string rtn=null;
        if (value.HasValue)
            rtn=value.Value.Kind == DateTimeKind.Utc?
    				value.Value.ToString("u"):
    				value.Value.ToString("s")
        return rtn;
    }
    
  • (disco)

    Sure, it converts all built-in types to strings (conveniently ignoring the built-in ToString() method for these objects, except maybe Date if you want to be picky. But what about objects you need to pass across module boundaries -- certainly these contain built-in data types too? And trees of objects; and arrays....

    And wouldn't it be easy to create a wrapper class for each built-in type (shudder; I think my heart just stopped) which then would negate the reason for ToString? I mean, if you're not stringifying objects, then passing IntWrapper(some_int) would work for you, right?

    Wonder what the original coder really had in mind?

  • (disco) in reply to Spencer

    You joke, but I've had to maintain such an abomination. My last job involved supporting a web application in a shop full of "developers" who believed that object models were "too complex" and "hard to follow". Instead, one monstrous XmlDocument object was passed around between the many pages. Right before I quit there were more than 62000 calls to SelectSingleNode(), every last one containing a hard-coded XPath which had been copy/pasted a thousand times over.

  • (disco)

    He named it UUUU because MUUMUU would have been lame.

  • (disco) in reply to CoyneTheDup
    CoyneTheDup:
    He named it UUUU because MUUMUU would have been lame.
    Nah, it's an alternative spelling of "Ewww"...
  • (disco) in reply to Steve_The_Cynic

    It's better than "W", it's "Double-double-U".

  • (disco)

    This would go great with the legacy code I am working on which passes everything (well, almost everything) in a heterogeneous HashMap with String keys.

    First you get a domain object, put most or all of its properties in local vars, then stick those vars into a non-typed HashMap with hard coded strings as keys, then pass that to another method which pulls out each of the properties from the HashMap, casting them to their expected type, assigning them to local vars.

    Rinse and repeat.

    What could be better?

    Stringify the properties.

    We are already halfway there; anything that can be stored in the DB as a boolean is instead stored as the string "Y"/"N", "True"/"False", numbers are stored as strings, and some Integer identifiers are stored as BigDecimals where there is never any decimal portion to the identifier.

    Mix this in with some weird multi-layer abstractions such as having a bunch of integer constants for retrieving the domain object properties embedded in a bunch of if/else statements to get those properties, then store a bunch of global vars in system properties changed by anything on any thread in any class, and you have the start of a combination that drives developers screaming into the night.

  • (disco) in reply to algorythmics
    algorythmics:
    now I feel like I don't deserve it because you guys basically gifted it to me.
    Why do you think I didn't post? ;-)
  • (disco)

    Post like this, readed on my lunch break, make me lost my apetite..

    this is a nice way of figthting obesity...

  • (disco)

    Everything in .NET inherits from System.Object

    System.Object has a ToString() method

    So they are reinventing (in a custom way) something that's already built in.

    This almost looks like a poor man's Serializable()

  • (disco) in reply to Chris_W

    Yes, technically a static, uninitialized String reference. Closest you can get to a NULL with a value type.

  • (disco) in reply to Developer_Dude

    If portability is a goal then using Y/N for database booleans can make good sense. In fact, in many of the real-world situations I have found myself in a boolean in a database requires one of 4 values: Uninitialised (not yet set) i.e. null True False Unable to determine. Database booleans can't handle this and so two booleans are needed to cover the same range. But a character field can handle every option.

    Some databases use BigDecimals as the nearest type for autoincrement row numbering, which means there are scenarios where for portability BigDecimals may have to be used even though in a given implementation the values will be integers.

  • (disco) in reply to kupfernigk
    kupfernigk:
    I have found myself in a boolean in a database requires one of 4 values: Uninitialised (not yet set) i.e. null True False Unable to determine.
    You forgot FILE_NOT_FOUND.
  • (disco) in reply to kupfernigk
    kupfernigk:
    If portability is a goal then using Y/N for database booleans can make good sense. In fact, in many of the real-world situations I have found myself in a boolean in a database requires one of 4 values: Uninitialised (not yet set) i.e. null True False Unable to determine. Database booleans can't handle this and so two booleans are needed to cover the same range. But a character field can handle every option.

    Some databases use BigDecimals as the nearest type for autoincrement row numbering, which means there are scenarios where for portability BigDecimals may have to be used even though in a given implementation the values will be integers.

    DECLARE @ActualValue BIT, @CanDetermine BIT
    
    SELECT CASE WHEN @CanDetermine = 0 THEN 'Unable to determine'
    	WHEN @ActualValue = 1 THEN 'True'
    	WHEN @ActualValue = 0 THEN 'False'
    	ELSE 'Uninitialized'
    END
    
  • (disco) in reply to RFoxmich
    RFoxmich:
    There are entire languages that work this way. Us Tclers got smart however and eventually developed an object that had the string representation that all objects have and a second representation to cache the last used non string type of the value.

    But that's done competently. Funnelling everything through strings just for the hell of it is damn slow.

  • (disco) in reply to kupfernigk
    kupfernigk:
    If portability is a goal then using Y/N for database booleans can make good sense. In fact, in many of the real-world situations I have found myself in a boolean in a database requires one of 4 values:Uninitialised (not yet set) i.e. nullTrueFalseUnable to determine.Database booleans can't handle this and so two booleans are needed to cover the same range. But a character field can handle every option.

    Some databases don't even have a boolean type available for use in columns...(Oracle, for instance)

  • (disco) in reply to tarunik
    tarunik:
    Some databases don't even have a boolean type available for use in columns...(Oracle, for instance)

    That's a problem for the export process, not my database's model.

  • (disco) in reply to chubertdev
    chubertdev:
    That's a problem for the export process, not my database's model.

    Be glad you don't deal with Orrible then, or else it would be a problem for your database's model.

  • (disco) in reply to tarunik

    I make it a point not to.

  • (disco) in reply to tarunik

    My recollection was that it didn't but that was years ago and I thought it might have changed since. Ah well...

  • (disco) in reply to kupfernigk
    kupfernigk:
    My recollection was that it didn't but that was years ago and I thought it might have changed since.Ah well...

    It hasn't changed since.

  • (disco) in reply to chubertdev

    Yes, you can handle it with two booleans or two bits, which are logically equivalent since a boolean can be represented by one bit. But how much space in an actual tuple in a real world database is required for two bits? A moment's thought shows that unless you have a number of bit fields that fits into a byte boundary, there must always be wasted space. A character representation of a variable which has only a few enumerable values is often (a) efficient and (b) human readable. Back in the days when we had only kilobytes to play with for the entire system things were somewhat different, but bit storage is still hard to do well. In one experimental architecture we built we had an add on 1Mbit static RAM (1M by 1 bit) module whose sole purpose was to store a large number of temporary bit variables from a fast data logging application, because the data was 16 bits wide and otherwise the number of words of RAM would have had to double. But you can't modify hardware to suit the application easily, not nowadays anyway.

  • (disco) in reply to tarunik

    Perhaps now Larry's stepped aside a bit...nah.

  • (disco) in reply to aliceif

    You'll have to explain that to me. I may be missing a point or a joke, but - what file?

  • (disco) in reply to kupfernigk

    It's a long-running joke here; see http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx

  • (disco) in reply to Spencer
    Spencer:
    It seems like there was a missed opportunity to Stringize the values into an XML document which would then be passed as the parameters for every function. That would be really enterprise-y.
    What's more, is it gives you dynamic type checking: what could be better than `<value type="int">1234</value>`? It will keep you from accidentally passing the string `"1234"` for that parameter, whereas if you just used `ParseInt` the latter would look like a valid value. See? Brilliant!
  • (disco) in reply to FrostCat
    FrostCat:
    It's a long-running joke here

    It's a long-running joke that, to paraphrase @mott555 (writing about something else), in true TDWTF fashion we took, used, abused, beat into the ground, turned into a horse, killed for glue, then continued to beat on the corpse afterwards.

  • (disco) in reply to FrostCat

    I see I have failed to cross a pons asinorum and I trudge off heavily into the storm and night.

  • (disco) in reply to kupfernigk
    kupfernigk:
    I see I have failed to cross a _pons asinorum_ and I trudge off heavily into the storm and night.

    Meh. You can't be expected to know an inside joke when you're new. Just be aware there are a lot of them here, and they're generally obscure, and based mostly on old front-page stories.

  • (disco) in reply to FrostCat
    FrostCat:
    Meh. You can't be expected to know an inside joke when you're new.

    Yes you can.

  • (disco) in reply to FrostCat

    Also remember they're all unfunny.

  • (disco)

    Strongly typed - let the compiler do most of the heavy lifting Weakly typed - let the unit tests do most of the heavy lifting Stringly typed - let your coworkers do most of the heavy lifting (of your codebase to tdwtf)

  • (disco) in reply to Developer_Dude

    Then settle on one - not "T" or "Y" or "True" or "N" or any of the other variations (upper/lower/mixed case) not to mention mispellings (yes, almost every usage of these "booleans" used a hard coded local string, not a constant).

    Plus, it is aggravating and error prone to have to convert strings to booleans and back again. Not to mention the code was converting to Boolean instead of boolean so it was having to check for nulls.

    If you have a multi-value boolean (true/false/unknown) then use some kind of integer enum - zero, one and two? Or minus one for unknown and zero for false and one for true - that converts better and stands out well when looking at the data (minus one being an obvious and often used flag).

    We have converted them all to bit (SQL Server) and it is just a lot simpler as the JDBC driver handles it fine.

    Long would be better than Big Decimal if you never have to use a decimal.

    Now we are using GUIDs with NewSequentialID instead of any kind of integer ID.

    As for portability, in this app it isn't an issue, but in my experience our new schema will be more portable than the old schema with at least two different error prone ways of representing booleans as strings.

  • X (unregistered)

    String him up!

Leave a comment on “Stringify All the Things!”

Log In or post as a guest

Replying to comment #:

« Return to Article