rspec/rules/S5419/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

115 lines
4.3 KiB
Plaintext

== Why is this an issue?
When a function has several consecutive parameters of the same type, there is a risk that the arguments are not provided in the right order. Moreover, it is generally the sign of code which is too low-level. Maybe
* the arguments should have a stronger type
* some arguments could be grouped together to form a higher level abstraction.
The use of two parameters of the same type is useful in situations like comparing arguments, combining arguments through a binary operation and swapping arguments but three or more arguments of the same type is considered bad practice.
This rule raises an issue when a function is defined with more than two consecutive parameters of the same type. For this rule, only the "raw" type of the parameter will be considered (a ``++string const &++`` will be considered the same type as a ``++std::string++``).
=== Noncompliant code example
[source,cpp]
----
double acceleration(double initialSpeed, double finalSpeed, double deltaT) { // Noncompliant
return (finalSpeed - initialSpeed) / deltaT;
}
double dot_product(double x1, double y1, double x2, double y2); // Noncompliant
void f() {
double x1,x2,y1,y2;
auto result = dot_product(x1,x2,y1,y2);// The order is wrong, even if it might look logical
auto acc = acceleration(10, 50, 110); // Very unclear, probably a bug...
}
----
=== Compliant solution
[source,cpp]
----
// This code assumes the use of a strong type / units library
Acceleration acceleration(Speed initialSpeed, Speed finalSpeed, Duration deltaT){
return (finalSpeed - initialSpeed) / deltaT;
}
struct point {
double x;
double y;
};
double dot_product(point p1, point p2);
double f() {
point p1,p2;
auto result = dot_product(p1,p2);
auto acc = acceleration(50 * km / hour, 110 * km / hour, 10s);
}
----
== Resources
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#i4-make-interfaces-precisely-and-strongly-typed[I.4: Make interfaces precisely and strongly typed]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Rewrite the function arguments to make its use less error-prone.
'''
== Comments And Links
(visible only on this page)
=== on 30 Aug 2019, 11:51:25 Loïc Joly wrote:
\[~geoffray.adde]: Could you please review my changes?
=== on 30 Aug 2019, 18:09:36 Nicolas Harraudeau wrote:
\[~loic.joly] The Noncompliant part seems to be on the wrong lines. Shouldn't it raise on the function signature rather than the call?
It seems to me that such a rule would raise many false positives. Ex: a function comparing two objects of the same type, merging them or doing something similar.
It would also encourage developers to reorder their arguments just to not raise an issue.
=== on 30 Aug 2019, 22:19:37 Loïc Joly wrote:
\[~nicolas.harraudeau]:
* Changed the position of noncompliant
* Two objects of the same type are ok, it is only triggered with 3 objects.
* Reordering would be a way to silence the issue, but for me, it would probably be an inferior solution most of the time. And I'm afraid that if we explicitly mention it, it might lead some developers to laziness (sweeping things under the rug), this is why I removed it from the first specification. I'm even wondering about removing the "consecutive" part of this rule... If you have a good example where reordering would lead to good code, let me know.
=== on 9 Sep 2019, 20:03:59 Ann Campbell wrote:
\[~geoffray.adde] & [~loic.joly] it's not clear to me why 3 params of the same type is bad but 2 is okay.
=== on 10 Sep 2019, 09:27:40 Loïc Joly wrote:
There are many functions for which 2 arguments of the same type are useful. For instance copying data from a source to a destination, or combining two elements into a third one (for instance, finding the GCD of 2 numbers). We felt that signaling those would raise far too many issues.
=== on 10 Sep 2019, 13:18:35 Ann Campbell wrote:
IMO you should add that to the description [~loic.joly]. Currently it seems totally arbitrary.
=== on 10 Oct 2019, 16:19:39 Geoffray Adde wrote:
\[~ann.campbell.2], I justified the part about 3 arguments.
=== on 11 Oct 2019, 14:15:35 Ann Campbell wrote:
\[~geoffray.adde], [~loic.joly] I've done a little additional wordsmithing. See what you think
=== on 14 Oct 2019, 10:00:16 Geoffray Adde wrote:
Fine by me
endif::env-github,rspecator-view[]