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.

Reply via email to