November 06, 2018
On Thursday, 1 November 2018 at 03:10:22 UTC, H. S. Teoh wrote:
> On Thu, Nov 01, 2018 at 02:45:19AM +0000, unprotected-entity via Digitalmars-d-announce wrote: [...]
>> Another thing to look for, is signs of code smell. I would include in this, unit tests calling private methods (which seems to be a popular thing for D programmers to do). Some will disagree that this is a code smell, but I have yet to see a good argument for why it is not.
>
> White-box testing.
>
> In principle, I agree with you that if your unittests are doing black-box testing, then they should definitely not be calling private methods.
>
> However, limiting yourself to black-box testing means your private functions can be arbitrarily complex

If any of your functions are arbitrarily complex, you're doing it wrong (if alone) or your colleagues are (because it passed code review).

> and yet it's not thoroughly tested.

If it's not thoroughly tested via the public API, then either some of the private code is useless and should be deleted, or the public API tests aren't good enough.

> Sometimes you really do want a unittest to ensure the private method is doing what you think it's doing, and this requires white-box testing.

Only when writing the private method TDD-style. After it's written, I'd delete any and all tests for the private code and rely on the public API instead. Possibly useful when debugging though.

> This is especially important to prevent regressions, even if it seems redundant at first.  Only doing black-box testing means a later code change in the private method can subtly introduce a bug that's not caught by the unittest (because it cannot call a private method directly to verify this).

This makes no sense to me. If the public API tests didn't catch a regression, then the tests are bad. End of.

November 06, 2018
On Friday, 2 November 2018 at 10:18:11 UTC, ShadoLight wrote:
> On Friday, 2 November 2018 at 00:53:52 UTC, H. S. Teoh wrote:
>>
>> And along that line, recent wisdom is that it's better to move things *out* of classes (and structs) if they don't need access to private members. (Sorry, I wanted to include a link for this, but I couldn't find the article -- the title eludes me and google isn't turning up anything useful.)  Class and struct APIs should be as minimal as possible -- just enough to do what needs to be done and no more, and the rest of the syntactic sugar (that makes it more palatable to your users) belongs outside as optional convenience functions.
>>
>
> Maybe you are thinking of the "Prefer non-member non-friend functions to member functions" rule from Herb Sutter's "Effective C++" books?

C++ however doesn't have reflection. The problem with non-member functions is I can't reflect on a type and loop over its member functions if some of the functionality is somewhere else.
November 06, 2018
On Saturday, 3 November 2018 at 04:50:52 UTC, unprotected-entity wrote:
> On Saturday, 3 November 2018 at 00:44:15 UTC, Laeeth Isharc wrote:
>> [...]
>
> I believe that responses like this, are really just designed to further obfuscate the point I'm trying to make, so that it cannot progress any further.
>
> Now, speaking of keeping an open mind....let's get back to my point.. can we?
>
> (q1) Why is it, that people who use D, object *so much* to the idea of allowing (at the choice of the programmer) for a type to have it's own private state *within* a module (so that its private state is respected by other code also within that module)?

Because it adds no value. Creating a new file is not expensive.

> (q2)Why must a type within a module *always* have its private state exposed to other code within the module? (the key word here, being 'always').

Because then `friend` isn't needed.

> (q3) Should a language intentionally set out to prevent a programmer from making that choice?

Yes, given that it decreases the overall complexity of the language.


November 06, 2018
On Monday, 5 November 2018 at 01:39:46 UTC, unprotected-entity wrote:
> On Saturday, 3 November 2018 at 21:35:04 UTC, Walter Bright wrote:
>> On 11/2/2018 5:44 PM, Laeeth Isharc wrote:
>>> When one encounters a new idea that's unfamiliar sometimes it's easy to think that because it's unfamiliar it must be unsound. That can be a mistake.  It might be better to suspend judgement for a while and keep an open mind.
>>
>> So true. My ideas on how to write code have changed dramatically over the years, and continue to change.
>
> I hear the advantages of the way D does it.
>
> But nobody wants to hear about the disadvantages.

We heard you, we just disagree it's a disadvantage.

> What harm can come, from an optional tool, that enables enforceable encapsulation of a type, within a module (from code also in the module, but outside that type)?
>
> Can someone please answer that?

The harm is complexity.

But hey, if you want to write such a tool go right ahead.

> And yet again, I remind people that this is not a request for change. This is a discussion about what benefit such a tool can bring.

In my opinion, no benefit at all.


November 07, 2018
On Monday, 5 November 2018 at 11:07:11 UTC, Mike Parker wrote:
>
> So where are these teams of imperfect D programmers who are plagued by accidental modifications of private class members? Sociomantic? Funkwerk? Weka?

First, nobody needs to explain the problems that type errors create.

Any decent programmer should already be well aware of such problems.

Second, it's a matter of scale. How many D programmers are there?

The probability that someone will do something silly, like below, will increase with scale. That's just how it is.

Now. How many C++/Java/C# programmers are there?

And, since the chance of error will increase with the number of users (and also the number of lines) how many of them would find that their compiler will happily compile the code below?

and the is answer: zero

no matter how many of them - it'll *always* be zero.

unless they do it in D.

------
module test;

class Firefighter
{
    private void DoSomethingATraineeShouldNotDo() {}

}

class TraineeFirefighter : Firefighter {}

unittest
{
    TraineeFirefighter joe = new TraineeFirefighter();
    joe.DoSomethingATraineeShouldNotDo();

}
----------
November 07, 2018
On Wednesday, 7 November 2018 at 11:00:49 UTC, TheFirefighter wrote:
> Now. How many C++/Java/C# programmers are there?

Even if a `super private` attribute or something is introduced, the semantics of private in D will not change. Your hypothetical C# programmer who switches to D assuming identical visiblity semantics to C# will still write that program that makes the plane crash. Luckily Java programmers write one class per file anyway.

On Wednesday, 7 November 2018 at 11:00:49 UTC, TheFirefighter wrote:
> First, nobody needs to explain the problems that type errors create.
>
> Any decent programmer should already be well aware of such problems.

Look, you can keep making new accounts and restating that it's so obvious you don't need to convince anyone, and that D programmers are just stubborn. But it won't help advancing the discussion like you want.

If you can't show that there are actual programmers writing appropriately sized modules containg bugs simply because of the lack of a class-private visibility level, then people don't want to engineer a solution to a seemingly non-existant problem, write and maintain the compiler code + specification for it, update existing tutorials, editors and tools, inform existing users about the change, and making the language more complex overall.

Imagine if I made a proposal like this:

"Hello, MrHaltingProblem here!

We obviously need a @noloops attribute. My co-workers are constantly writing buggy loops with wrong loop conditions so I NEED the extra protection. You're asking for a justification? Trust me, any decent programmer knows the importance of this. You are just too stubborn to see all the bugs that the lack of this attribute causes. Asking for real world examples?
```
class Plane {
  void doLandingProcedure() {
    // lots of code
    while (1) {} // OOPS!
    // lots of code
  }
}
```

There! Now let's discuss the benefit of such a feature in D."

This doesn't look like a compelling argument, so D programmers would probably suggest making more use of ranges instead.
November 07, 2018
On Wednesday, 7 November 2018 at 13:15:03 UTC, Dennis wrote:
> [snip]
>
> "Hello, MrHaltingProblem here!
>
> We obviously need a @noloops attribute. My co-workers are constantly writing buggy loops with wrong loop conditions so I NEED the extra protection. You're asking for a justification? Trust me, any decent programmer knows the importance of this. You are just too stubborn to see all the bugs that the lack of this attribute causes. Asking for real world examples?
> ```
> class Plane {
>   void doLandingProcedure() {
>     // lots of code
>     while (1) {} // OOPS!
>     // lots of code
>   }
> }
> ```
>
> There! Now let's discuss the benefit of such a feature in D."
>
> This doesn't look like a compelling argument, so D programmers would probably suggest making more use of ranges instead.

I get what you're saying here, but just to play devil's advocate, this feature could be added broadly to D without breaking any code. In particular, the @disable attribute could be extended to 1) take some input, in this case a keyword (foreach, while, goto, etc) but potentially also symbols (I'm thinking mainly function names here), and 2) @disable's behavior could be extended so that it works with like the protection attributes in terms of being able to use it as in @disable(keyword) { } or @disable(keyword):. For a start, something like @nogc and @nothrow are really just a special cases of @disable(GC) and @disable(Exception), or something.

Also, the idea could be improved if there was some easy way to combine multiple attributes (there might be, but I don't know off the top of my head).

Where I'm coming from is that these attributes aren't really based on any primitives. They are rather ad hoc. For instance, even this proposal would need additional work to enable @safe and pure to be based on primitives. What if someone wanted to make @disable(template) and have that enforced throughout their code? What if the decision not to include textual macros in D were instead set up as a default for @disable(textual_macros)?


November 08, 2018
On Wednesday, 7 November 2018 at 13:15:03 UTC, Dennis wrote:
>
> If you can't show that there are actual programmers writing appropriately sized modules containg bugs simply because of the lack of a class-private visibility level, then people don't want to engineer a solution to a seemingly non-existant problem, write and maintain the compiler code + specification for it, update existing tutorials, editors and tools, inform existing users about the change, and making the language more complex overall.
>

well you could say the same about pointers. but..what happens when a large number of programmers start using pointers?

In the hands of few, it's not such a big issue.

In the hands of the many, well.. we all know the result. Decades of bugs!

Should we wait till the bugs start appearing?

But my argument actually is less about bugs, or the potential for bugs (although that potential obviously exists). My argument is more about the 'untyped' nature of the D module. That is, a type (say a class) is 'naked' in a module, exposed for all (in that module) to see. It can be violated in any number of ways, by other code in the module. I mean that is just fact. It's not something I should need to continually point out.

Some say that' fine. A class should be subjected to that humiliation.

Other say, if you wan't to prevent that humiliation, then you can do it already - that is, you can clothe a class, in D, by 'walling it off' in it's *own* module.

That immediately tells you something about the nature of the module. The module is essentially an untyped universe. It removes the clothes from the class, and allows it to be violated. On that basis, bugs (or the potential for them), becomes an immediate reality - and more so in the hands of the many, as opposed to the hands fo the few.

Now, if you're one of those that object to the use of classes (and there are many in the D forums), then you would already be biased towards dismissing my argument, and don't mind at all if the class is subject to humiliation. I would prefer you refrain from the discussion, if such bias is going to be used to shutdown the argument. Because it just brings the tone of the discussion down to a level that nobody wants to participate in - likely it's goal in the first place.

Lets be clear. My argument (not my DIP - as there is none) is, that it can only strengthen D, if D allowed the programmer the option (just the option) to ensure that a class wasn't subjected to such humiliation, when there is other code in the module besides that class.

The major purpose of a class afterall (understood by most programmers), is to impose contraints on interactions with other objects (or other code), in order to enforce correctness and eliminate inconsistencies. It does this, by clothing itself, so that other types cannot operate directly on its naked representation.

Yes, I know, you *can* clothe your class in D, but *only* if you wall it off in it's module. If you want 2 classes in your module, now you need to manage 2 classes across 2 different modules. That is an increase in complexity for the programmer.

But you have no choice, because the very instance you put other code in that module, you remove that protective clothing.

All I'm asking for, is the ability to have extra code in the module, without the module removing the clothes from my types.

Is that really too much too ask?

I do not understand the motivations of those that reject such an argument.

(hopefully, the moderator will post this..you never know on these forums..peoples post are going missing, or show up in the wrong order, days later....what's going on?)
November 08, 2018
On Thursday, 8 November 2018 at 09:53:59 UTC, TheFireFighter wrote:
> well you could say the same about pointers. but..what happens when a large number of programmers start using pointers?

I don't see the parallel between pointers and class-private.

> But my argument actually is less about bugs, or the potential for bugs (although that potential obviously exists). My argument is more about the 'untyped' nature of the D module.

That's a shame, I think the bug-argument is the stronger one.

> Now, if you're one of those that object to the use of classes (and there are many in the D forums), then you would already be biased towards dismissing my argument, and don't mind at all if the class is subject to humiliation. I would prefer you refrain from the discussion, if such bias is going to be used to shutdown the argument.

My guess, based on my experience, is that bad coders will seek the shortest path to something that works. So if they need to quickly access a class-private member in the module they're working on, they'll remove the private attribute. But I don't know, I'm biased like everyone. I haven't worked in the same setting as you. That's why I'm really interested in hearing your perspective. I don't have a strong opinion on the importance of visibility attributes within a module, so I'm interested in hearing strong arguments from you. But so far, your arguments boil down to:

- Avoiding justification - "Obviously" "I don't have to explain this" "Any decent programmer knows this"
- Appeal to fear - "Just wait for all the problems that come in the future!"
- Appeal to feeling - "Classes are naked, humiliated, their private parts are violated. That's so clearly wrong."

I don't find such arguments strong. If they were, you could also justify adding the @noloops attribute as I jokingly did in my previous post.

> Lets be clear. My argument (not my DIP - as there is none) is, that it can only strengthen D, if D allowed the programmer the option (just the option) to ensure that a class wasn't subjected to such humiliation, when there is other code in the module besides that class.

That sounds like "I just want there to be the option for aggregate value types... without using struct.". The question this raises is why the current solution is so problematic.

> I do not understand the motivations of those that reject such an argument.

Do you agree that language additions add a lot of weight? If yes, then it's simply the fact that people don't think your suggestion bears that weight because it's already possible to do what you want in another way.
November 08, 2018
On Thursday, 8 November 2018 at 13:18:30 UTC, Dennis wrote:
>
> That sounds like "I just want there to be the option for aggregate value types... without using struct.". The question this raises is why the current solution is so problematic.
>

I just want (for example) to be able to write a module, that contains a class, and also has non-member, non-friend functions.

You simply cannot do that in a D module, as the class has no clothes - to extend the metaphor from my recent post.

I refer you to Scott Meyers article about the benefits of having 'non-friend' non-member functions:

How Non-Member Functions Improve Encapsulation (btw. people misread that title - it should be been "How Non-Friend, Non-Member..."

http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197?pgno=1


>
> Do you agree that language additions add a lot of weight? If yes, then it's simply the fact that people don't think your suggestion bears that weight because it's already possible to do what you want in another way.

No it is not. You can keep saying there is, but it doesn't make it so.

We don't seem to be on the same page here...do you misunderstand what I want?

Fact: I cannot have a class in a module, and specify (so that the compiler can enforce it) that I want other code in the module to respect the specification of that class. It just cannot happen. Don't say it can. It can't. It's fact.

As a result, one of my core guidelines are not applicable anymore, if I used D:

" Don’t force together into a module things that will be used or maintained separately, and don’t separate things that will always be used and maintained together."

Regarding the 'burden' to the D langauge, by providing the programmer with a tool to specify better encapsulation of code *within* the module:

"I have become more and more convinced that the key to code reusability and scalability is encapsulation — having subsystems communicate through small, well-defined interfaces and letting them hide their own implementation details."
- Walter Bright

http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394?queryText=Scott%2BMeyers

i.e. better encapsulation really is a good thing (although for many, it a lesson that needs to be learned).