'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