rspec/rules/S5414/cfamily/rule.adoc
Fred Tingaud 22b4470f2a
Modify CFamily rules: CPP-4080 Refresh and standardize CppCoreGuidelines references (#3514)
Update all links to C++ Core Guidelines to `e49158a`.

Refresh done using the following script and some manual edits:
db76e34e74/personal/fred-tingaud/rspec/refresh-cppcoreguidelines.py

When re-using this script, be mindful that:
 - it does not cover `shared_content`
 - it does not properly escape inline code in links (e.g., "[=]" or "`mutex`es")
 - it does not change `C++` to `{cpp}` in link titles.

Co-authored-by: Marco Borgeaud <marco.borgeaud@sonarsource.com>
2023-12-20 10:08:18 +01:00

120 lines
4.5 KiB
Plaintext

== Why is this an issue?
Mixing (non-const) ``++public++`` and ``++private++`` data members is a bad practice because it confuses the intention of the class:
* If the class is a collection of loosely related values, all the data members should be ``++public++``.
* On the other hand, if the class is trying to maintain an invariant, all the data members should be ``++private++``.
If we mix data members with different levels of accessibility, we lose clarity as to the purpose of the class.
=== Noncompliant code example
[source,cpp]
----
class MyClass { // Noncompliant
public:
int firstNumber1() const { return firstNumber; }
void setFirstNumber(int firstNumber) { this->firstNumber = firstNumber; }
int secondNumber = 2;
private:
int firstNumber = 1;
};
----
=== Compliant solution
[source,cpp]
----
class MyClass { // Depending on the case, the solution might be different. Here, since this class does not enforce any invariant, we make all the data members public
public:
int firstNumber;
int secondNumber;
};
----
=== Exceptions
Since ``++const++`` data members cannot be modified, it's not breaking encapsulation to make a const value public, even in a class that enforces an invariant.
[source,cpp]
----
class MyClass { // Compliant by exception
public:
const int constNumber = 0; // const data members are fine
private:
int number = 1;
};
----
== Resources
=== Documentation
* Wikipedia - https://en.wikipedia.org/wiki/Class_invariant[Class invariant]
=== External coding guidelines
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c134-ensure-all-non-const-data-members-have-the-same-access-level[C.134: Ensure all non-`const` data members have the same access level]
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c9-minimize-exposure-of-members[C.9: Minimize exposure of members]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
"Don't mix public and private data members."
=== Highlighting
Primary: the name of the class.
Secondaries: one public and one private data member.
'''
== Comments And Links
(visible only on this page)
=== on 9 Sep 2019, 20:24:12 Ann Campbell wrote:
\[~loic.joly] and [~abbas.sabra] first, this rule title does not conform to our "X should [not] Y" standard.
Second, is this rule about having in the same class members that are both non-``++const++`` and ``++public++`` along with members that are ``++private++`` with whatever ``++const++``-ness? Because it is not clear to me from the title and description.
In fact, after multiple readings and some cogitation I think this is about having modifiable, ``++public++`` members in a class with ... _anything_ else in it? Because if I can modify the public members directly then what's the point of having methods? They certainly won't be able to notice/act on changes to the public members.
And finally, I suggest the 2ndary locations highlight every public non-``++const++`` member, not just one of them.
=== on 10 Sep 2019, 09:52:18 Loïc Joly wrote:
\[~ann.campbell.2] I would say non-const public data members are fine is we mix them with const public data members and public member functions, but nothing else. Protected/private functions would not harm, but would probably not be very useful. So I'm not sure about detecting them. It's hard to find a title that is not too long... I even considered using the simpler (and less accurate) title "a class should not contain both public and private data members", and talk about the public const case as an exception. What do you think?
Some people argue for no functions in "bag-of-data" classes. But it's not commonly accepted, since there is some value in providing some functions anyways, understanding that they will not provide encapsulation, but may still be useful:
* Constructors to enforce initialization of all members
* Utility functions, for instance to output the class on a stream, to send it to a database...
Some of those features might be provided by free functions, but sometimes a member function makes it easier to use...
=== on 10 Sep 2019, 13:51:16 Ann Campbell wrote:
____
"a class should not contain both public and private data members", and talk about the public const case as an exception. What do you think?
____
I think this is a reasonable option altho it should be pluralized: Classes should not... Another title option is: Non-const data members should either all be public or all be private
endif::env-github,rspecator-view[]