VB6 Logic Bomb



  • I'm updating a VB6 application to work with MySQL and SQLite. Now VB6 does have a concept of NULL but throws a hissy fit if you attempt to assign a NULL value to any of the basic data types (int, float, string). To avoid this issue, as part of writing a DLL in C that handles all of the database communication, I'm trapping the NULL values and converting them to a more benign value that VB likes. Int and Float columns get set to zero, string columns to a blank string.

    VB uses the BSTR construct for strings, so I allocate a zero length BSTR and return that instead of NULL. Works fine in Vista & Win7 but crashes in WinXP. After much swearing and hair pulling, I find a note tucked into one of the knowledge base articles saying that by convention, a NULL BSTR pointer must be treated as a blank string. Problem fixed.

    So, because VB6 has issues with NULL values, I must return a NULL.



  • @Darthon said:

    writing a DLL in C that handles all of the database communication, I'm trapping the NULL values and converting them to a more benign value that VB likes. Int and Float columns get set to zero, string columns to a blank string.

    Is any of this a good idea?



  • Not even VB.Net?  Is it an option to update to that when updating the other stuff?



  • @Sutherlands said:

    Not even VB.Net?  Is it an option to update to that when updating the other stuff?

    I second this...  You SHOULD be able to quickly and easily upgrade the VB6 app to VB.Net, no?  There are lots of tools out there.

    I think you'll find working with nullable types in .Net 2.0+ much easier than what you got now.


  • Discourse touched me in a no-no place

    @beermouse said:

    @Darthon said:
    writing a DLL in C that handles all of the database communication, I'm trapping the NULL values and converting them to a more benign value that VB likes. Int and Float columns get set to zero, string columns to a blank string.

    Is any of this a good idea?

    It may provide some entertainment value if it shows up on the front page.



  • @C-Octothorpe said:

    You SHOULD be able to quickly and easily upgrade the VB6 app to VB.Net, no? 

     No, not really. They are basically unrelated languates. VB.NET (any version) has more in common with Visual C++ than any VB language, conversion tools or not.

    The issue the OP mentioned is well known. The quick-and-dirty solution is to tack & "" on the end of any reference to a database field that might possibly be null.



  • Hah, VB6 IS an upgrade, it was in VB4 when I started this project. As for updating to .Net, there are lots of gotchas in the code that would cause problems in moving to .Net (Extensive use of GoSub for one). If there was some way of jumping completely over .Net to VB2008 or later, that I would be interested in. I wouldn't be able to convince management to go for it though and I agree with their reasoning.

    However nice the technical reasons are for using a newer version of VB are, the business reasons aren't there. Switching from flat-files to a database back-end is introducing enough changes to the product without all of the bugs introduced by a radical upgrade in language revision. Playing games like returning zero instead of NULL from left joins results in fewer changes to the existing, working code logic. Since this program moves money around, any bugs cause REALLY irate customers. So as nice as it would be to play with the shiny new revisions of the compiler, the business risk isn't worth finding out the hard way what Microsoft has changed in this version.


  • Discourse touched me in a no-no place

    @Darthon said:

    Switching from flat-files to a database back-end is introducing enough changes to the product without all of the bugs introduced by a radical upgrade in language revision. Playing games like returning zero instead of NULL from left joins results in fewer changes to the existing, working code logic. Since this program moves money around, any bugs cause REALLY irate customers. So as nice as it would be to play with the shiny new revisions of the compiler, the business risk isn't worth finding out the hard way what Microsoft has changed in this version.

    Wait...are you saying that you're creating a new database as part of this project? If so, why on earth would you make columns nullable?


  • Discourse touched me in a no-no place

    @Darthon said:

    Since this program [written in VB] moves money around...
    Out of interest, how are the money values stored?



  • So then why are you upgrading to VB6?



  • None of the table columns allow NULL, however left/right joins will generate plenty of 'em.



  • @Darthon said:

    None of the table columns allow NULL, however left/right joins will generate plenty of 'em.
    Check out ISNULL or COALESCE...



  • @Darthon said:

    VB uses the BSTR construct for strings, so I allocate a zero length BSTR and return that instead of NULL. Works fine in Vista & Win7 but crashes in WinXP. After much swearing and hair pulling, I find a note tucked into one of the knowledge base articles saying that by convention, a NULL BSTR pointer must be treated as a blank string. Problem fixed.

    So, because VB6 has issues with NULL values, I must return a NULL.

    I'm not sure what you're complaining about here?

    Yes, the contract states that a NULL BSTR is semantically equal to an empty one, but you should have known that already if you mess around with them manually. What's the problem with that? And your program crashing on trying to use an empty one might have just been a memory management error on your side, for all we know.

     



  •  @Darthon said:

    If there was some way of jumping completely over .Net to VB2008 or later, that I would be interested in.

    Wait, what?

     


  • Discourse touched me in a no-no place

    @Kneth said:

     @Darthon said:

    If there was some way of jumping completely over .Net to VB2008 or later, that I would be interested in.

    Wait, what?

     

    Mixing VB versions with Visual Studio versions. VB 6 was part of Visual Studio 6. The next release, Visual Studio 2002, was called Visual Studio .Net because it was the first version with .Net. Then they started using the year, so successive releases were called VS2003, VS2005, '08, '10. VS2002/VS.Net and all later revisions do VB.Net, not classic VB>



  • @PedanticCurmudgeon said:

    @beermouse said:
    @Darthon said:
    writing a DLL in C that handles all of the database communication, I'm trapping the NULL values and converting them to a more benign value that VB likes. Int and Float columns get set to zero, string columns to a blank string.

    Is any of this a good idea?

    It may provide some entertainment value if when it shows up on the front page.

    FTFY



  • @Darthon said:

    Now VB6 does have a concept of NULL but throws a hissy fit if you attempt to assign a NULL value to any of the basic data types (int, float, string).
     

    do you mean literally an actual "Null" keyword? if yes, that's news for me, I always thought that VB6 had only "Nothing" (which, afaik, can be assigned to int/float/string/whatever), but i'm not really sure, it's been a long time i've worked with it.


  • Discourse touched me in a no-no place

    @C-Octothorpe said:

    @Sutherlands said:

    Not even VB.Net?  Is it an option to update to that when updating the other stuff?

    I second this...  You SHOULD be able to quickly and easily upgrade the VB6 app to VB.Net, no?  There are lots of tools out there.

    I think you'll find working with nullable types in .Net 2.0+ much easier than what you got now.

    Except that none of the built-in framework libraries and even fewer of the third party ones bother supporting nullable input types, so you have to litter your code with casts and null handling at every fucking method call.


  • @Weng said:

    Except that none of the built-in framework libraries and even fewer of the third party ones bother supporting nullable input types, so you have to litter your code with casts and null handling at every fucking method call.
     

    Some third-party developer: "I have to litter my code with casts and null handling in every fucking method? No way!"

    it has to be done somewhere, what does it matter where exactly? i personally am more content when seeing how these cases are handled than relying that the library/method somehow gets it sorted out.



  • @The_Assimilator said:

    [quote user="PedanticCurmudgeon"][quote user="beermouse"][quote user="Darthon"]writing a DLL in C that handles all of the database communication, I'm trapping the NULL values and converting them to a more benign value that VB likes. Int and Float columns get set to zero, string columns to a blank string.

    Is any of this a good idea?[/quote]It may provide some entertainment value if when it shows up on the front page.[/quote]

    FTFY[/quote]

    How about a "Future WTFs" forum where stories like this can be continued or even better: predicting the post the next dev working on the project would post?



  • @SEMI-HYBRID code said:

    Some third-party developer: "I have to litter my code with casts and null handling in every fucking method? No way!"

    it has to be done somewhere, what does it matter where exactly? i personally am more content when seeing how these cases are handled than relying that the library/method somehow gets it sorted out.

     

    I prefer to handle it in the spot that causes me the least amount of effort. One check in the DLL code vs. hundreds of checks in the VB code.

    Your visibility argument does carry some weight as none of the other developers on this project will ever open up the C files to see how things are handled.  However I've documented that this is how the DLL code works and it'll be the expected behavior.
     



  •  @SEMI-HYBRID code said:

    @Darthon said:

    Now VB6 does have a concept of NULL but throws a hissy fit if you attempt to assign a NULL value to any of the basic data types (int, float, string).
     

    do you mean literally an actual "Null" keyword? if yes, that's news for me, I always thought that VB6 had only "Nothing" (which, afaik, can be assigned to int/float/string/whatever), but i'm not really sure, it's been a long time i've worked with it.

    With VB6, you can set strings to null with the vbNullString constant and they're treaded as equivilent to a blank string.  At least in VB they are, don't try passing vbNullString to API calls unless you know they can take a NULL pointer.

    However you can also assign the value of NULL to a variant and this is what was giving me trouble.   Database code typically returns variants.  I could have also solved the problem by implementing a different GetData() method for each variable type (i.e. GetDataInt(), GetDataFloat(), etc.) but I chose not to go that route.

     

     



  • Actually, the equivalent of NULL is "Nothing"



    if var is nothing then debug.print "It's nothing!"



    is valid syntax.



  • @Daid said:

    Actually, the equivalent of NULL is "Nothing"



    if var is nothing then debug.print "It's nothing!"



    is valid syntax.
     

    Ah, but var isn't "nothing" - it's the name of a location to store some information. 

     

    (I abhor the concept of "null"... if you need a bitflag somewhere telling you if a variable has meaningful data, use a bitflag!)

     



  • @too_many_usernames said:

    I abhor the concept of "null"
     

    I abhor if statements.



  • @too_many_usernames said:

    (I abhor the concept of "null"... if you need a bitflag somewhere telling you if a variable has meaningful data, use a bitflag!)

    ?

    So instead of:

    var something == null

    if(something == null)

       something = somethingNew;

     

    you now have:

    var something == null

    var flags = SOMETHING_NULL

    if(flags.HasValue(SOMETHING_NULL))

       something = somethingNew

     

    ?



  • @Sutherlands said:

    @too_many_usernames said:
    (I abhor the concept of "null"... if you need a bitflag somewhere telling you if a variable has meaningful data, use a bitflag!)

    ?

    Something more like this:

    MyObject mo = foobar.getMyObject(); // never null
    
    mo.computeStuff();  // no-op if this MyObject represents a null MyObject
    
    gimmeMyObject(mo);  // no null worries
    
    // Okay, now we may to interact with a third-party lib
    // it needs a value that MyObject stores...
    
    if (mo.hasValidData()) { // checks internal status field or somesuch
    	EnterpriseFactoryFactoryFactory.newThirdPartyLibraryFactoryFactory.getThirdPartyLibraryFactoryInstance().newThirdPartyLibrary.newQuux().quux(mo.getData());
    } else {
    	// mo's data isn't valid (is null), so don't pass it in
    	MrLogger.log("Bypassed ThirdPartyLibrary because MyObject was invalid.");
    }
    

    I regularly use special NullMyObject subclasses to hold a non-null reference to uninitialized/invalid MyObjects.



  • @too_many_usernames said:

    (I abhor the concept of "null"... if you need a bitflag somewhere telling you if a variable has meaningful data, use a bitflag!)
     

    not that pretend i know anything about it, but isn't this how Null is implemented in the depths of machine/interpreted code?



  • @Xyro said:


    I regularly use special NullMyObject subclasses to hold a non-null reference to uninitialized/invalid MyObjects.

    Ah right, the old "null doesn't exist" null objects idea.  Gag me with a spoon.



  • @Sutherlands said:

    @Xyro said:


    I regularly use special NullMyObject subclasses to hold a non-null reference to uninitialized/invalid MyObjects.

    Ah right, the old "null doesn't exist" null objects idea.  Gag me with a spoon.

     

    Eh, null pointers (in my mind at least) are distinctly different classes of objects than "nullable variables."  I actually don't have a conceptual problem with the concept of null pointers. (They aren't so much "null pointers" as they are "pointers that don't point to anything".) 

     

    Or did I misunderstand your lament?

     

    @SEMI-HYBRID code said:

    not that pretend i know anything about it, but isn't this how Null is implemented in the depths of machine/interpreted code?

    The difficulty doesn't seem to be in the implementation (in fact, that is how you'd do it - or perhaps like pointers-to-null you use a special bit pattern in the native data type).  The problem is that there is inconsistency in how languages treat the metadata. Some languages seem to make the metadata available in a way that often confuses it with non-meta data.



  • @Sutherlands said:

    @Xyro said:
    I regularly use special NullMyObject subclasses to hold a non-null reference to uninitialized/invalid MyObjects.

    Ah right, the old "null doesn't exist" null objects idea.  Gag me with a spoon.

    What's wrong with that?

    Here's a scenario for the sake of discussion. It doesn't involve nulls; instead, I argue that if you find this object-oriented solution acceptable, then it's a short leap to accept not-null null objects.

    I wrote module that snaps into a third-party program. Like all third-party stuff, it is of questionable quality. I need to log the modules actions, and I have to use the third-party logger to do so. This logger is in no way dynamic, instead it's controlled by external settings that get passed into the module. So in order to know if you should be logging things, and you basically have to the settings it if its enabled before doing anything with it.

    Instead of peppering the code with if (settings.isLoggerEnabled()) { logger.log("slurping soup"); } type branches, I wrapped the built-in logger with my own object. We can call it MyLogger. MyLogger implements MyLoggable, which has another implementation: NullLogger. NullLogger no-ops everything. When the settings are first read in, the "mylog" variable either gets set to an instance of MyLogger, which logs everything, or NullLogger, which logs nothing.

    This is pretty basic OO technique, to which I believe dhromed would find agreeable.

    Now, what if instead of the settings giving me a boolean as to whether I should log or not, it just gave me a logger instance? And what if the logger it returned was null when it mean that no logging should be performed? I think it's easy to say one would use the same solution of a NullLogger. But now extend that logic further, what if you are the callee and need to return something to which the question was, say, invalid or inapplicable or nonexistent? Your options are basically 1) throw an exception; 2) make the caller deal with a null; or 3) pass back an object representing the nullness of the return.

    Option 1 is sometimes the way to go, but sometimes isn't, due to the annoyance factor. It depends on if the caller broke the contract, or if the data to return just doesn't exist. A nullable integer field in a database would be a good example of this. Option 2 is quite nearly a sin, because you're really just passing your problems onto someone else. I guess this would be the part where we'd disagree. Oh crap, I'm late for a meeting. Someone else continue this post for me.



  • @too_many_usernames said:

    Eh, null pointers (in my mind at least) are distinctly different classes of objects than "nullable variables." 

    In what language?  What nullable variables are you referring to that are bad?

    @Xyro said:

    @Sutherlands said:
    @Xyro said:
    I regularly use special NullMyObject subclasses to hold a non-null reference to uninitialized/invalid MyObjects.
    Ah right, the old "null doesn't exist" null objects idea.  Gag me with a spoon.
    What's wrong with that?

    Here's a scenario for the sake of discussion. It doesn't involve nulls; instead, I argue that if you find this object-oriented solution acceptable, then it's a short leap to accept not-null null objects.

    [. . .]

    Why would the logger itself not take care of whether you should log or not?



  • @Sutherlands said:

    In what language?  What nullable variables are you referring to that are bad?
     

    I don't think any of them are "bad"; just some are more awkward than others.

    Some of it is just personal preference; I would find it more clear in the databse sense, for instance, to think of things like "if there is data in this record for field y then..." rather than "if field y in this record is not null..."  And yes, I'm fully aware that "is null" is a shorthand for "if there is data in this record for field..." but I think it it's not worth the pain it appears to inflict.

    Also, another favorite whipping boy is Java, because the concept of an integer or string being "null" just doesn't make sense...but that's just a side effect of Java's decision to "hide" pointers and then overload the equality and pointer dereference operators.

    At the end of the day I don't think it's right or wrong; it just seems that, empirically, people have trouble with "empty container" situations.



  • Okay, meeting over.

    @Sutherlands said:

    Why would the logger itself not take care of whether you should log or not?

    Because it's stupid :(

    The code that grabs, parses, and lexes the settings is completely independent of all the rest of the bits. You even have to handle the parsing and lexing yourself, although they provide utility methods for it. ... This is for a 6-figure software package (plus cumulative-upkeep maintenance fees) from a major computer industry company. Ugh.

    But back to the point. The question is this: If you've got invalid or inapplicable or missing data, how do you represent it? Is there an OO way to do it elegantly? How about in a manner that doesn't force the caller (and/or you) to spray if (obj != null) statements all over the place? Clearly, objects representing nullness is the way to go.

    Who needs if statements when you've got polymorphism?

    @too_many_usernames said:

    Also, another favorite whipping boy is Java, because the concept of an integer or string being "null" just doesn't make sense...but that's just a side effect of Java's decision to "hide" pointers and then overload the equality and pointer dereference operators.

    Hmm? Strings are normal objects in Java, and they can be null just fine. The only thing special about them is that they have a literal form. Primitives like ints can't be null any more than any other data-structure-that-isn't-a-pointer can be in any other language. However, their Integer wrapper can be, since that's a normal object, too. As in any language, only pointers can be null. If you have an integer that is assigned to null, then it's actually a null pointer to an integer value. No whipping necessary.

    Now, strings in Oracle, on the other hand...

    @too_many_usernames said:
    it just seems that, empirically, people have trouble with "empty container" situations.
    Agreed.


  •  



  • @Xyro said:

    Hmm? Strings are normal objects in Java, and they can be null just fine.
     

    Exactly: that's pointer semantics.  Java Objects are really pointers to Objects but the only time they have pointer semantics is when you create one with new or use the = operator to copy an object reference (I don't use Java at all, and I was surprised at the hoops you have to go through to actually copy/"deep copy"/clone() an object).  Otherwise the semantics assume the object is "non-null."  It's really pedantic, but a "null object" isn't really an object at all; it's the lack of an object. A null object in Java is really "a sign pointing you at an object, but it's not pointing to an object right now."

    It just seems like a lot of complicated semantics just to hide pointers.



  • @Xyro said:

    Okay, meeting over. @Sutherlands said:
    Why would the logger itself not take care of whether you should log or not?
    Because it's stupid :(

    Wha??? So let's imagine a class, we'll call it LogWriter.  This class has IsLoggingEnabled and IsTracingEnabled if you want to query its status.  If you call Write, passing in a hypothetical LogEntry class.  The LogEntry class has a Priority, which, based on the settings in LogWriter, will determine if it will actually log.

    @Xyro said:

    But back to the point. The question is this: If you've got invalid or inapplicable or missing data, how do you represent it? Is there an OO way to do it elegantly? How about in a manner that doesn't force the caller (and/or you) to spray if (obj != null) statements all over the place? Clearly, objects representing nullness is the way to go.
    It depends.  Are we talking well-written or poorly-written?  What is the context?  How is an object representing nullness the way to go?  The caller expected you to give it a valid object, and you didn't.  Either the semantics are such that they don't actually need the value (in which case I can pass back a default value), or the semantics are such that you've just screwed them royally.  If I've got invalid data, chances are I'm going to throw an exception.  Clearly, objects representing nullness are not the way to go.

    @Xyro said:

    Who needs if statements when you've got polymorphism?
    Indeed... remind me again... how'd you get that different class to begin with? :P



  • @Sutherlands said:

    @Xyro said:
    Because it's stupid :(

    Wha???

    I know, Java has that sort of stuff built-in, too, as well as nearly universally used Apache library that precedes and supercedes the built-in logger. But... the Enterprise third-party library doesn't use the stuff everyone else does...

    @Sutherlands said:

    It depends. [...]

    Yes, no doubt it's not a solution you'd use all of the time, but I see no reason why it should be viewed with antipathy. Sometimes you want to hold an object of some sort, but which that object doesn't represent anything "real" yet, where the meaning of "real" is domain-specific. May be it's an uninitialized object. You want to eschew filling up your code with if (obj != null), since it's only "null" at first, but you also don't want to pre-initialize the object before other events take place. A "null object" which no-ops its actions would be perfect.

    @Sutherlands said:

    @Xyro said:
    Who needs if statements when you've got polymorphism?
    Indeed... remind me again... how'd you get that different class to begin with? :P
    Hm? I don't understand what you mean.



  • @Xyro said:

    @Sutherlands said:
    @Xyro said:
    Who needs if statements when you've got polymorphism?
    Indeed... remind me again... how'd you get that different class to begin with? :P
    Hm? I don't understand what you mean.

    if(needNullObject)

       return new NullObjectImplementation()

    else

       return new Implementation()

     

    Also, I don't think I've ever run into a scenario where I would use a null object.



  • Ah, I see.

    It would be more like

    // Initial value
    MyObject mo = NullMyObject.getInstance();
    

    // This can be set asynchronously or lazily or set to null without concern
    public void setMyObject(MyObject newMo) {
    // It's possible that we ought to accept nulls rather than
    // denonate them as part of a precondition check.
    // This "if" is lame, but at least you only have to do it once.
    if (newMo != null) {
    this.mo = newMo;
    } else {
    this.mo = NullMyObject.getInstance();
    }
    }

    // No need to check for nulls; very clean
    public void doABarrelRoll() {
    mo.press('R'); // (Does nothing if a NullMyObject.)
    mo.press('R');
    }

    as opposed to the doABarrelRoll() method implemented as
    public void doABarrelRoll() {
    	if (mo =! null) { // laaaame
    		mo.press('Z');
    		mo.press('Z');
    	}
    }
    

    If my logger example, pretend that I wasn't using a super stupid logger and was just checking for other settings instead. Like, did the config specify to perform some extra step or no? For example, should I validate the XML before transmitting it? In the config code, either pass back a NullValidator or a RealValidator; in the calling code, just execute getValidator().validate(xml) as part of a normal flow, nice and pretty like.



  • @Xyro said:

    if (newMo != null)
    I FOUND IT!

     

    But seriously.. is this representing an N64 controller?  Your example just goes to show me you probably should never have gotten to that situation in the first place.

    @Xyro said:

    If my logger example, pretend that I wasn't using a super stupid logger and was just checking for other settings instead. Like, did the config specify to perform some extra step or no? For example, should I validate the XML before transmitting it? In the config code, either pass back a NullValidator or a RealValidator; in the calling code, just execute getValidator().validate(xml) as part of a normal flow, nice and pretty like.
    Why doesn't the "RealValidator" have a setting called "ShouldValidate" that it checks itself?  Better question, why are you calling validate IF YOU DON'T WANT TO VALIDATE?!



  • @Sutherlands said:

    @Xyro said:

    if (newMo != null)
    I FOUND IT!

     

    But seriously.. is this representing an N64 controller?  Your example just goes to show me you probably should never have gotten to that situation in the first place.

     

     and the OP is pretty clear that it's not himself who got him into that situation.

     

    @Sutherlands said:

    @Xyro said:
    If my logger example, pretend that I wasn't using a super stupid logger and was just checking for other settings instead. Like, did the config specify to perform some extra step or no? For example, should I validate the XML before transmitting it? In the config code, either pass back a NullValidator or a RealValidator; in the calling code, just execute getValidator().validate(xml) as part of a normal flow, nice and pretty like.
    Why doesn't the "RealValidator" have a setting called "ShouldValidate" that it checks itself?  Better question, why are you calling validate IF YOU DON'T WANT TO VALIDATE?!

     seriously, what are you trying to troll out of him? and more importantly, why are you arguing about the OP IF YOU HAVEN'T EVEN BOTHERED TO READ IT?

     



  • @SEMI-HYBRID code said:

    and the OP is pretty clear that it's not himself who got him into that situation.
    The example was not the OP.  The... well, the post by Xyro where he explained what was going on (which is still not this example) does not need "null objects".  The "OP" said that he wrapped the built-in logger with his own logger.  So he has control over the code inside "the logger" to determine whether he should log a given message.

    @SEMI-HYBRID code said:

    seriously, what are you trying to troll out of him? and more importantly, why are you arguing about the OP IF YOU HAVEN'T EVEN BOTHERED TO READ IT?
    quit trollin, bro

     

    If you have 2 objects that you created for validation or logging, and one is to "do nothing", you can have the "real object" do that based on whatever it is you need it to.  If the object in question is not written by you, then you can use the Facade pattern.



  • @Sutherlands said:

    If you have 2 objects that you created for validation or logging, and one is to "do nothing", you can have the "real object" do that based on whatever it is you need it to.  If the object in question is not written by you, then you can use the Facade pattern.

    But then your code has to check for validity (even if it's just a boolean) every single time the desired action is asked to be performed, even when it's completely known before the code enters the action. Of course, the benefits are much more apparent when you have more than just a "real" object and a "null" object. An empty collections object would be like a "null object". You can pass back a Collections.emptyList() to the calling code and they won't have to check for nullness every time they use it. They just iterate over it and go.

    Let's say you had some object in an inner loop. Whether or not you call if (obj != null) obj.doStuff(); or doStuff() was implemented to do some internal checking, you still have to branch at every iteration. That's what I'm calling lame. Just call doStuff() and skip over all the repeating if statements with conditions that will not change. Polymorph!



  • @Xyro said:

    But then your code has to check for validity (even if it's just a boolean) every single time the desired action is asked to be performed,
    OH NO!  The processing cost of that is... is... perfectly miniscule and much smaller than a function call.  Oh, I guess my excitement was for nothing.

    @Xyro said:

    You can pass back a Collections.emptyList() to the calling code and they won't have to check for nullness every time they use it. They just iterate over it and go.
    I'm perfectly happy passing back an empty list when there was nothing to put in the list.  If I couldn't contact the database, I'm not going to, though.

    @Xyro said:

    Let's say you had some object in an inner loop. Whether or not you call if (obj != null) obj.doStuff(); or doStuff() was implemented to do some internal checking, you still have to branch at every iteration. That's what I'm calling lame. Just call doStuff() and skip over all the repeating if statements with conditions that will not change. Polymorph!

    You really think checking for null is slower than finding the appropriate overridden function in a vtable? 


  • @Sutherlands said:

    You really think checking for null is slower than finding the appropriate overridden function in a vtable?

    The CPU takes a smoke break after being asked to do lame null checking over and over. Then it starts talking bad about you behind your back to the computer's peripherals. That's why the printer has such a bad attitude.

    Okay, so I was doing a little coding yesterday and I thought of you. I have a bunch of functor objects, and I needed to look up which one to use. For simplicity sake, let's say the functors accept objects and returns strings, so they're kind of like glorified toString()s. Actually, that's very much what they're like. Which functor I use is looked up in a rule matching object, and the set of functors it chooses from is dynamic. So, it would kind of be like, if these options are set, return a type-A toString(); if these other options are set, choose a type-B toString(); then maybe a type-C toString() enters the battlefield and is a better match for some of the rules under a type-A scenario. Something like that.

    Well, the rule-matching object will return null if nothing properly matches. I wasn't too keen on making that a special case and null check its return, so I created a default rule that will match under any condition if nothing else does, and with it I created a "null toString functor" that just returns the empty string. (Actually a bit more complicated than that, but that's kind of what it boils down to, at least for the sake of this simplified example.)

    This way, when I go to display the given information on the object, I can just process the objects without a single null check and without any ifs. It's beautiful and nice and flowy; it takes care of the otherwise special null case by making it a not-special case.

    Hmm, maybe I'm more opposed to special cases than to null-checking, specifically. I try to make all my code beautiful and flowy.



  • Control should travel through code like an electrical pulse through a chip. Code behaves in a way because it simply is, not because it branches as it checks for conditions.

    Not always feasible in all situations, whether in or outside code, but it's a good priciple, I think.



  • @Xyro said:


    This way, when I go to display the given information on the object, I can just process the objects without a single null check and without any ifs. It's beautiful and nice and flowy; it takes care of the otherwise special null case by making it a not-special case.

    Hmm, maybe I'm more opposed to special cases than to null-checking, specifically. I try to make all my code beautiful and flowy.

    Yes, and your example is also DRY in action. The biggest problem with having to have null checks everywhere is that you have to have null checks everywhere. In addition to making it more difficult to read the code and understand what it's really doing, it's just many more places where you will create bugs. I wouldn't worry about the cost of looking anything up in a vtable until I had a reason to. And except for some very rare circumstances, I suspect nothing ever will.



  • @Xyro said:

    The CPU takes a smoke break after being asked to do lame null checking over and over.
    If it's taking its smoke break inside your case then I hope it's in a well-ventilated area.

    @Xyro said:

    Hmm, maybe I'm more opposed to special cases than to null-checking, specifically. I try to make all my code beautiful and flowy.

    I would say your example is not a "null-object" but a "do-nothing-object". Which is perfectly valid.


  • @Sutherlands said:

    @Xyro said:
    The CPU takes a smoke break after being asked to do lame null checking over and over.
    If it's taking its smoke break inside your case then I hope it's in a well-ventilated area.
     

    Like his windy ass.


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.