'with' bug?
Faux Amis
faux at amis.com
Sun Nov 4 15:51:15 PST 2012
On 04/11/2012 17:05, Chris Cain wrote:
> On Sunday, 4 November 2012 at 14:59:24 UTC, Faux Amis wrote:
>> I failed to mention that I am mostly talking about private module
>> scope variables. I don't see how private module scoped vars make for
>> less testable, readable or more bug prone code.
>
> It's not like I feel that you should never use them, but what he says is
> right. The more open access that is given to a variable, the more
> difficult it is for the programmer to know what will access or change
> it. That becomes a huge problem in many languages that don't use
> thread-local variables by default, but it's still a problem in D.
>
> Without using some sort of automated search, you can't know where in the
> module a variable is accessed or changed. Sometimes even a search will
> be insufficient:
> ---
> module a;
> int b; // the variable we're interested in
> int c;
>
> void blah() {
> foo();
> bar();
> }
>
> void foo() {
> c = b + 1;
> }
>
> void bar() {
> b *= 3;
> }
> ---
>
> So, via search, we can see that b is being accessed in foo, and being
> changed in bar. However, a simple search will not tell us that blah is
> accessing and changing b. Furthermore, any function that uses blah will
> also be accessing and changing b. The reason this is a problem is that
> it's "hidden" from the people reading the code. You might not know that
> using "blah" will write and read from b, which might effect the behavior
> of the call to "bax" later on in your code.
>
> Consider this code, however:
>
> ---
> void main() {
> int b = 5; // the variable we're interested in
> int c = blah(b);
> // What's the value of b here? How about c?
> bax(b);
> flax();
> bongo();
> for(d; sheep(c))
> blast(d);
> // Do you still know what b is? Of course you do!
> }
>
> int blah(ref int b) {
> int c = foo(b);
> bar(b);
> return c;
> }
>
> void foo(int b) {
> return b + 1;
> }
>
> void bar(ref int b) {
> b *= 3;
> }
>
> void bax(int b) {
> // large switch statement on b for behaviors
> }
> ---
>
> Now we're explicit in what uses b. All of a sudden, we can reason much
> more about the code without doing nearly as much searching. We know who
> depends on the value of b and who might change b. If we allowed it to be
> a global variable, or a module variable, or even a static struct
> variable, we might not always have such a good grasp on what is
> happening to it.
>
> And if you don't have a good grasp on what's happening to the state of
> your program, you might introduce bugs. Hence, it's bug prone to use
> module scoped variables.
>
> As for testability: if the behavior of your code depends on globals
> (and/or module-scoped variables), then it should be obvious why it's
> more difficult to test. Tests shouldn't be effected by tests run before
> nor should they have an effect on tests run after. When you use globals,
> your code will violate that by definition. Unless, of course, you spend
> time being very careful to reset globals before and/or after each test.
> That certainly makes testing more difficult and error prone, though.
>
>
> Now, that all said, it's not like a velociraptor will jump through your
> window and eat your face off if you use a global or a module scoped
> variable. I'm sure you can come up with examples of where it might be
> beneficial or preferable. But it's something that should be avoided
> where you can.
>
> Here's a good resource on why global variables are bad:
> http://c2.com/cgi/wiki?GlobalVariablesAreBad
>
> Most of those reasons are applicable to module-scoped variables as well.
> Even struct static variables can still be problematic for some of the
> same reasons.
In your last paragraph you are getting to my point in my other post:
I think there is nothing wrong with a module scope private var as in D a
module is the first encapsulation and adding a wrapper only adds noise.
These are equivalent(from a good-coding pov):
---
module a;
private int i;
---
module b;
// annoying wrapper
//which makes it difficult to have a single b in the program
struct S{
int i;
}
---
These are also equivalent:
---
module a;
int i;
---
module b;
struct S{
static int i;
}
---
More information about the Digitalmars-d
mailing list