Jump to content

  • Log In with Google      Sign In   
  • Create Account

mike3

Member Since 06 Feb 2012
Offline Last Active Dec 26 2013 02:44 AM

Posts I've Made

In Topic: Why are static variables bad?

05 September 2013 - 08:30 PM

 

The constructor for Foo now gets gibberish in the whatever field and crashes or behaves in some unpredictable ("undefined") way. It's not that the old code (here, meaning the code that makes the FooContext and the Foo) attempts to use "whatever", it's that the old code doesn't use "whatever", and because it was not updated to take "whatever" into account (meaning, it doesn't even set it to null, it doesn't do anything with it, period), causes Foo's constructor to gag.
 
So do you add the check for "whatever" not being set in to the old code, in which case it would probably be easier simply to just properly initialize whatever, or do you add the check in Foo, and regardless of the check placement, do you need to add a constructor to FooContext that ensures a stable "uninitialized" or "null" value that can be checked for? Because if you have to add the check and/or set-to-null in the old Foo-using code, then if you forget to add it there, you have a crash or other failure. To me, it seems the only way to make it robust against such omission is to put a constructor in FooContext that pre-initializes whatever to null.

Why would it crash on "whatever" if none of the old code uses it? You literally could have an object with two members, one being a pointer set to gibberish and one being a pointer set to a valid object and as long as you never tried to -use- the gibberish pointer it wouldn't actually do anything undefined.

 

 

The way I interpreted the example, the crash occurs when Foo's constructor is invoked with the FooContext having an uninitialized whatever member, and the crash occurs when Foo's constructor is invoked and chokes.


In Topic: Why are static variables bad?

05 September 2013 - 07:10 PM

 

Do you mean a check on "whatever"? Since "whatever" was supposed to be the problem variable, as it was supposed to represent a "new feature" that had been added, and all preexisting code (i.e. before the feature addition) only knew of bla. The code already initializes bla.

I suppose I wasn't understanding the example very well. If "whatever" is a member added to the struct later then what would it being set to null matter for old code? Unless the "old code" tried to utilize it then it would essentially be the same as the transparent addition of adding a new variable to a class your code was using, but not utilizing that particular variable.

I'm assuming the point you're getting at is, someone adds the new "whatever" variable to an object, and your code attempts to use the "whatever" object, but your coworker managing the usage of the struct that passes it to you hasn't implemented setting that whatever to something yet. In that case of course you would have to check validity of the object before you use it. If I'm getting this wrong please do re-explain it to me. 

 

The example appears to be: We have a class "Foo" which takes a "FooContext" to specify how to set it up. Initially, this "FooContext" contains only one parameter, "bla". Bits of code are created that have to make Foos from a FooContext, and naturally, they only set bla. But then down the road as our project progresses, someone decides now to add a new feature to Foo, which now requires a new parameter, "whatever", in the FooContext. And in how I imagine this scenario, which may or may not be how kunos imagined it, I imagine "whatever" to be a strictly "extensional" feature, i.e. it does not alter the original behavior of Foo, but extends it to add capability, that is, that the old way of using Foo should still work and not break. (The reason for this requirement is because without it, we might be forced to change the code anyway, but I'm trying to isolate the addition of the data field itself as the problem) But the programmer adding the new "whatever" parameter forgets a place where FooContexts are used and so doesn't add the proper initialization to the extensional feature whatever. The constructor for Foo now gets gibberish in the whatever field and crashes or behaves in some unpredictable ("undefined") way. It's not that the old code (here, meaning the code that makes the FooContext and the Foo) attempts to use "whatever", it's that the old code doesn't use "whatever", and because it was not updated to take "whatever" into account (meaning, it doesn't even set it to null, it doesn't do anything with it, period), causes Foo's constructor to gag.

 

So do you add the check for "whatever" not being set in to the old code, in which case it would probably be easier simply to just properly initialize whatever, or do you add the check in Foo, and regardless of the check placement, do you need to add a constructor to FooContext that ensures a stable "uninitialized" or "null" value that can be checked for? Because if you have to add the check and/or set-to-null in the old Foo-using code, then if you forget to add it there, you have a crash or other failure. To me, it seems the only way to make it robust against such omission is to put a constructor in FooContext that pre-initializes whatever to null.


In Topic: Why are static variables bad?

05 September 2013 - 03:22 PM

 

So what would be the correct approach in the example case, with the struct where a new member may be added? Where would the error be "reported" to, and in what way? More importantly, how would we know "whatever" was uninitialized, when its value as uninitialized may be undefined?

E.g.

FooContext fooContext;
fooContext.bla = <smth>; // old code that didn't know about the new "whatever" feature

// member whatever could have an undefined value, so how does this check that and "report" it, fail gracefully, etc.?
Foo *foo(new Foo(fooContext));

As like he says, it seems you need a constructor of some kind in fooContext to prevent this. Even if not one to force the programmer to pass a parameter, then at least a default one to initialize the variables so their values are all defined (perhaps so as to indicate special uninitialized states that Foo can then check for).

The ideal thing to do would be to treat the context as a volatile object and check for null on .bla before attempting to use it.
 

 

Do you mean a check on "whatever"? Since "whatever" was supposed to be the problem variable, as it was supposed to represent a "new feature" that had been added, and all preexisting code (i.e. before the feature addition) only knew of bla. The code already initializes bla. (Though I suppose maybe a check on bla would be good too, as someone could fail to init that, too) But where would this check go? If "in the code initializing the FooContext", then that means the programmer has to add it to each such piece of code, which creates a lot of duplicated checks, and more importantly, if you're doing that why aren't you just adding a proper initialization of whatever? And furthermore, the programmer adding such checks is then aware of the existence of the rest of the code, whereas kunos' scenario was that someone adds a new feature ("whatever" in this case) but isn't aware of/forgets to add the corresponding initialization to every place the FooContext is initialized. So if they are to add the checks to wherever the FooContext is initialized, then they know about those places, and so they should be adding proper initialization too, I'd think. But his scenario is that they are not so aware. It seems he wants it "robust against feature addition" or something like that. If the check goes in the constructor, then what about the concern about constructors being bloated with checks?


In Topic: Why are static variables bad?

05 September 2013 - 01:22 AM

I fail to see how it is "fail safe." If something were going to fail being set or passed as a paramater later it would certainly cause problems in the constructor, in terms of errors the constructor is the most volatile part of the object for error checking. Bloating the constructor with checking code is a bad idea anyway.

 

So how do you suggest to avoid crashing when someone "fails to pass something" as you suggest should be avoided? And in the example given, that something was to be passed to a constructor.


In Topic: Why are static variables bad?

04 September 2013 - 05:28 PM

Personally I think this is a HUGE problem in that you code should not be designed in such a way that if you fail to pass something to it, that it crashes. It should if anything report it, or if it causes a fatal error it should crash with a thrown exception in a way that the programmer knows they messed up and it needs to be fixed immediately, rather than a user error.

The whole methodology behind the default constructor object is to treat the object as the most important thing in the world, that it should be concerned only with its own state and not trust any information received from other parts of the program, by verifying that data is both correct and exists it prevents the program from crashing without having to worry about things outside of its own code like "did the coder set this object right before creating me."

 

 

So what would be the correct approach in the example case, with the struct where a new member may be added? Where would the error be "reported" to, and in what way? More importantly, how would we know "whatever" was uninitialized, when its value as uninitialized may be undefined?

 

E.g.

 

FooContext fooContext;

fooContext.bla = <smth>; // old code that didn't know about the new "whatever" feature

 

// member whatever could have an undefined value, so how does this check that and "report" it, fail gracefully, etc.?

Foo *foo(new Foo(fooContext));

 

As like he says, it seems you need a constructor of some kind in fooContext to prevent this. Even if not one to force the programmer to pass a parameter, then at least a default one to initialize the variables so their values are all defined (perhaps so as to indicate special uninitialized states that Foo can then check for).


PARTNERS