Discussion on using module-scoped variables (was 'with' bug?)

Faux Amis faux at amis.com
Tue Nov 6 07:34:36 PST 2012


On 06/11/2012 07:46, Chris Cain wrote:
> On Monday, 5 November 2012 at 08:37:49 UTC, Faux Amis wrote:
>> Ok, good to see that you are replying to incorrectly scoped variables,
>> but this is not the point I am trying to make. I know you should
>> always keep the scope as small as possible.
>
> Eh? I'm confused. The second half of my post certainly was a bit of a
> rant on incorrectly scoped variables (which is related to the
> discussion, but it was my response to bearophile), but the first part of
> my post is supporting the viewpoint that you should avoid using
> module-scoped variables (and even static struct member variables) and
> suggesting an alternative.
>
>> Can you think of a setting in which we have legitimate private struct
>> members? If so, then add to this setting that you only want one
>> instantiation of the data in this struct. As a solution, what is wrong
>> with dropping the struct encapsulation? There is no other code except
>> the struct in the module.
>>
>> I sincerely want to know if there is any difference. As I understand
>> it the scope is exactly the same or even smaller as you can't leak
>> instances of modules as you can structs.
>
>  From my understanding, you're trying to get a specific viewpoint on
> this idea?
>
>> From a good-coding standpoint, do you think there is a difference
>> between these two options?
>>
>> --
>> module a;
>>
>> int a;
>> --
>> module b;
>>
>> struct S{//otherwise unused wrapper
>> static int b;
>> }
>> --
>
> I think the first option is "better" than the second. The second seems
> to be a misuse of struct to me. I can't see why you'd use a struct in
> the second option.
>
> That said, they're effectively equivalent pieces of code. That is,
> they're both static data that is a shared resource among all functions
> that have access to them. And, thus, they're both "equally bad" in terms
> of how they will affect the understandability and testability of the
> code. It's possible that it would cause the code to have more bugs in it
> than it would otherwise.
>
> That is, both of them are not as good of choices as this:
> ---
> void good(ref int b) pure {
>      // code using/setting b
> }
> void good2(int b) pure {
>      // code using b, but not setting it
> }
>
> // No b in module scope or statically allocated
>
> // Sometimes a better idea, depending on circumstances:
> int better(int b) pure {
>     // code using b, and putting changes into changedB
>     return changedB;
> }
>
> // example uses:
> void main() {
>      int a = 1, b = 2, c = 3;
>      good(a);
>      good2(b);
>      c = better(c);
> }
> ---
>
> Because this creates code that is honest about its dependencies and
> allows for the overall state of the program to be consistent between
> runs of functions. This is essential for testability, but it's also
> important for a programmer to reason about the behavior of their code.
Yes, this is obvious.

>
> Of course, I'm sure you can give examples of code that couldn't be
> written like that, and that's okay. I'm only arguing that you should
> avoid static data when it's realistic to do so, not that it will open a
> black hole in your living room if you use it under any circumstances
> :-). Though if you're using it as your "primary data encapsulation," I
> have to wonder whether you're using it in instances it could have been
> avoided.

I would have loved an answer to this:

Is there any reason to encapsulate this kind of code in a struct?
---
module a;

private int _a;

int a(){
   return _a;
}

void a(int aIn){
   _a = aIn;
}

void useA(){
}
---
module main;

static import a;

void main(){
   a.useA();
}
---

What I am trying to get answered here is whether there is something 
special about a struct or a class which makes it a 'correct' data 
encapsulator where a module does not.



More information about the Digitalmars-d mailing list