Date: Tue, 03 Jan 2023 01:45:08 +0000
Hi All,
Please accept my apology for the late response, very busy. Didn’t want to leave this discussion open ended.
I really appreciate your responses.
>>>> "Private, protected, and public provide control over inheritance of members, which would not be possible by diligence alone (and the lack of "private" would kill interoperability between various code sets by forcing all developers to choose personally unique member variable names to allow subclasses to exist without conflicting with base class should-be-private member names), and the use case for design rule enforcement is enormous as well. Otoh, the access-per-member use case seems rather esoteric (also there are a lot of potential complications especially where inheritance and templating become involved)."
I clearly see a per-member access feature for classes being unnecessary in some cases. Still hiding a class data member from specific methods that don't need to know about is useful. Also it gives the compiler additional knowledge of how your class' data is being used so may reveal possible optimizations. Unless you're dealing with a single function body, data hiding may be applicable.
>>>> "But more importantly, and to be blunt, things like private, protected, public, const, override, those all enforce good, effective design patterns. On the other hand, per-member access controls seem to enforce only bad design patterns, where better organization of classes, improved documentation, and testing are the typical good approach. To get to the point where per-member access is necessary, mistakes would have had to have been made, and C++ *tries* (sometimes failing, but it tries) to encourage things that are not mistakes."
Any feature in C++ can be misused, but in general data hiding is good practice regardless​ of where it's applied. Otherwise we could say Lambdas are bad because we're declaring a function inside a function for the purpose of hiding logic and data. Why not instead add another method to the class of the function using the lambda? This is similar to your argument against the ability to declare a namespace inside a class' body.
For limiting access to class member types to specific methods inside the same class, I could create a member class type, but there's issues with that approach. For example, in the code below SomeType xyz need to be static and defined or a Namespace class instance must be created:
class Foo {
public:
void foo_method0();
void foo_method1();
struct Namespace {
friend void foo_method0();
private:
SomeType xyz;
};
};
Having a feature that allows namespaces in the body of the class will solve this problem.
James S.
------- Original Message -------
On Wednesday, November 9th, 2022 at 4:24 PM, Jason C <jason.cipriani_at_[hidden]> wrote:
> Private, protected, and public provide control over inheritance of members, which would not be possible by diligence alone (and the lack of "private" would kill interoperability between various code sets by forcing all developers to choose personally unique member variable names to allow subclasses to exist without conflicting with base class should-be-private member names), and the use case for design rule enforcement is enormous as well. Otoh, the access-per-member use case seems rather esoteric (also there are a lot of potential complications especially where inheritance and templating become involved).
>
> Const (and constexpr) allows the compiler to make various assumptions, and allows code to exist that could not exist without it; allowing the existence of a number of more complex language features especially where temporary variables and references are concerned.
>
> But more importantly, and to be blunt, things like private, protected, public, const, override, those all enforce good, effective design patterns. On the other hand, per-member access controls seem to enforce only bad design patterns, where better organization of classes, improved documentation, and testing are the typical good approach. To get to the point where per-member access is necessary, mistakes would have had to have been made, and C++ *tries* (sometimes failing, but it tries) to encourage things that are not mistakes.
>
> Jason
>
> On Wed, Nov 9, 2022 at 9:58 AM Smith, Jim via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>> Thanks for the feedback!
>>
>> I understand what you're saying here because the ability to enforce these restriction isn't available in C++. We could use the same arguments if private, protected, public, and const were never implemented. These access specifiers were implemented to make controlling access to data an types easier than adding additional tests and comments.
>>
>> James S.
>>
>> ------- Original Message -------
>> On Monday, November 7th, 2022 at 9:26 PM, Jason C via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>>> I agree with the other Jason on this.
>>>
>>> Other appropriate design patterns and strategies can mitigate this issue, most notably *good documentation* and *unit testing*, among other things (such as other Jason's suggestion of splitting up the class). For example:
>>> /**
>>> * @postcondition data1 and data2 will not be modified.
>>> */
>>> void Foo::Method_2 () {
>>> }
>>>
>>> Having this documentation in a visible location will allow other developers to understand what should and shouldn't be done. Furthermore:
>>> void test_Foo_Method_2 () {
>>> Foo foo;
>>> auto data1 = foo.data1;
>>> auto data2 = foo.data2;
>>> foo.Method_2();
>>> FAIL_TEST_IF(foo.data1 != data1);
>>> FAIL_TEST_IF(foo.data2 != data2);
>>> }
>>>
>>> There, some fictitious unit testing framework is used to ensure that Method_2() behaves properly, where errors will be caught during testing presuming test case coverage is appropriate.
>>>
>>> A Different Jason
>>>
>>> On Mon, Nov 7, 2022 at 7:25 PM Jason McKesson via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>>
>>>> On Mon, Nov 7, 2022 at 3:17 PM Smith, Jim via Std-Proposals
>>>> <std-proposals_at_[hidden]> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> Sometimes I'd like to hide data from a subset of class methods while still allowing other methods to access them.
>>>>
>>>> I find this notion to be dubious. If a class is so big that, to ensure
>>>> the sanity of the class's state, it becomes necessary to give
>>>> individual member functions access to individual data members, then
>>>> that class has grown too big and needs to be split out into multiple
>>>> classes. The only downside is that it is slightly less convenient, as
>>>> the outer class has to explicitly expose the functions of the inner
>>>> class.
>>>> --
>>>> Std-Proposals mailing list
>>>> Std-Proposals_at_[hidden]
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_lists.isocpp.org
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Please accept my apology for the late response, very busy. Didn’t want to leave this discussion open ended.
I really appreciate your responses.
>>>> "Private, protected, and public provide control over inheritance of members, which would not be possible by diligence alone (and the lack of "private" would kill interoperability between various code sets by forcing all developers to choose personally unique member variable names to allow subclasses to exist without conflicting with base class should-be-private member names), and the use case for design rule enforcement is enormous as well. Otoh, the access-per-member use case seems rather esoteric (also there are a lot of potential complications especially where inheritance and templating become involved)."
I clearly see a per-member access feature for classes being unnecessary in some cases. Still hiding a class data member from specific methods that don't need to know about is useful. Also it gives the compiler additional knowledge of how your class' data is being used so may reveal possible optimizations. Unless you're dealing with a single function body, data hiding may be applicable.
>>>> "But more importantly, and to be blunt, things like private, protected, public, const, override, those all enforce good, effective design patterns. On the other hand, per-member access controls seem to enforce only bad design patterns, where better organization of classes, improved documentation, and testing are the typical good approach. To get to the point where per-member access is necessary, mistakes would have had to have been made, and C++ *tries* (sometimes failing, but it tries) to encourage things that are not mistakes."
Any feature in C++ can be misused, but in general data hiding is good practice regardless​ of where it's applied. Otherwise we could say Lambdas are bad because we're declaring a function inside a function for the purpose of hiding logic and data. Why not instead add another method to the class of the function using the lambda? This is similar to your argument against the ability to declare a namespace inside a class' body.
For limiting access to class member types to specific methods inside the same class, I could create a member class type, but there's issues with that approach. For example, in the code below SomeType xyz need to be static and defined or a Namespace class instance must be created:
class Foo {
public:
void foo_method0();
void foo_method1();
struct Namespace {
friend void foo_method0();
private:
SomeType xyz;
};
};
Having a feature that allows namespaces in the body of the class will solve this problem.
James S.
------- Original Message -------
On Wednesday, November 9th, 2022 at 4:24 PM, Jason C <jason.cipriani_at_[hidden]> wrote:
> Private, protected, and public provide control over inheritance of members, which would not be possible by diligence alone (and the lack of "private" would kill interoperability between various code sets by forcing all developers to choose personally unique member variable names to allow subclasses to exist without conflicting with base class should-be-private member names), and the use case for design rule enforcement is enormous as well. Otoh, the access-per-member use case seems rather esoteric (also there are a lot of potential complications especially where inheritance and templating become involved).
>
> Const (and constexpr) allows the compiler to make various assumptions, and allows code to exist that could not exist without it; allowing the existence of a number of more complex language features especially where temporary variables and references are concerned.
>
> But more importantly, and to be blunt, things like private, protected, public, const, override, those all enforce good, effective design patterns. On the other hand, per-member access controls seem to enforce only bad design patterns, where better organization of classes, improved documentation, and testing are the typical good approach. To get to the point where per-member access is necessary, mistakes would have had to have been made, and C++ *tries* (sometimes failing, but it tries) to encourage things that are not mistakes.
>
> Jason
>
> On Wed, Nov 9, 2022 at 9:58 AM Smith, Jim via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>> Thanks for the feedback!
>>
>> I understand what you're saying here because the ability to enforce these restriction isn't available in C++. We could use the same arguments if private, protected, public, and const were never implemented. These access specifiers were implemented to make controlling access to data an types easier than adding additional tests and comments.
>>
>> James S.
>>
>> ------- Original Message -------
>> On Monday, November 7th, 2022 at 9:26 PM, Jason C via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>>> I agree with the other Jason on this.
>>>
>>> Other appropriate design patterns and strategies can mitigate this issue, most notably *good documentation* and *unit testing*, among other things (such as other Jason's suggestion of splitting up the class). For example:
>>> /**
>>> * @postcondition data1 and data2 will not be modified.
>>> */
>>> void Foo::Method_2 () {
>>> }
>>>
>>> Having this documentation in a visible location will allow other developers to understand what should and shouldn't be done. Furthermore:
>>> void test_Foo_Method_2 () {
>>> Foo foo;
>>> auto data1 = foo.data1;
>>> auto data2 = foo.data2;
>>> foo.Method_2();
>>> FAIL_TEST_IF(foo.data1 != data1);
>>> FAIL_TEST_IF(foo.data2 != data2);
>>> }
>>>
>>> There, some fictitious unit testing framework is used to ensure that Method_2() behaves properly, where errors will be caught during testing presuming test case coverage is appropriate.
>>>
>>> A Different Jason
>>>
>>> On Mon, Nov 7, 2022 at 7:25 PM Jason McKesson via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>>
>>>> On Mon, Nov 7, 2022 at 3:17 PM Smith, Jim via Std-Proposals
>>>> <std-proposals_at_[hidden]> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> Sometimes I'd like to hide data from a subset of class methods while still allowing other methods to access them.
>>>>
>>>> I find this notion to be dubious. If a class is so big that, to ensure
>>>> the sanity of the class's state, it becomes necessary to give
>>>> individual member functions access to individual data members, then
>>>> that class has grown too big and needs to be split out into multiple
>>>> classes. The only downside is that it is slightly less convenient, as
>>>> the outer class has to explicitly expose the functions of the inner
>>>> class.
>>>> --
>>>> Std-Proposals mailing list
>>>> Std-Proposals_at_[hidden]
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_lists.isocpp.org
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2023-01-03 01:45:21