When I have the following code with 2 levels of Ternary operations
double amount = isValid ? (isTypeA ? vo.getTypeA() : vo.getTypeB()) : 0;
Which Sonar warns about
Ternary operators should not be nested (squid:S3358)
Just because you can do something, doesn't mean you should, and that's the case with nested ternary operations. Nesting ternary operators results in the kind of code that may seem clear as day when you write it, but six months later will leave maintainers (or worse - future you) scratching their heads and cursing.
Instead, err on the side of clarity, and use another line to express the nested operation as a separate statement.
My colleague suggested that such level can be accepted and it's more clear than the alternative.
I wonder if this rule (or others) can be configured to allowed levels limit?
If not, why sonar is so strict when it deals with code conventions?
I don't want to ignore rule, just to customize to allow up to 2 levels instead of 1.
I wonder if this rule can be configured to allowed levels limit?
The Ternary operators should not be nested rule cannot be configured. You are only able to enable or disable it.
I wonder if other rules can be configured to allowed levels limit?
I don't know any existing rule which can do it. Luckily, you are able to create a custom analyzer. The original rule class is here NestedTernaryOperatorsCheck. You can simply copy it and adjust to your needs.
why sonar is so strict when it deals with code conventions?
SonarSource provides a lot of rules for different languages. Every customization makes code more difficult to maintain. They have a limited capacity, so they have to make decisions which are unaccepted by all users (but are accepted by most of them).
Related
Currently working on modifying big mapping classes and some new rules have appeared making me wonder what is the best option here.
Imagine a classic mapping function like so:
yyy.setType(xxx.getType);
yyy.setSomething(xxx.getSomethigElse);
yyy.setThisAsWell(xxx.getThatAsWell);
And I now have a condition to check, what would be better? (knowing that I won't have future similar condition checking to do):
final Boolean isRuleApplying = xxx.getRule == RULE;
yyy.setType(
isRuleApplying ? RULE_STUFF : xxx.getType
);
yyy.setSomething(
isRuleApplying ? RULE_STUFF_OTHER : xxx.getSomethigElse
);
yyy.setThisAsWell(
isRuleApplying ? RULE_STUFF_AGAIN : xxx.getThatAsWell
);
Or is it better to use the old if else?
if (xxx.getRule == RULE) {
yyy.setType(RULE_STUFF);
yyy.setSomething(RULE_STUFF_OTHER);
yyy.setThisAsWell(RULE_STUFF_AGAIN);
} else {
yyy.setType(xxx.getType);
yyy.setSomething(xxx.getSomethigElse);
yyy.setThisAsWell(xxx.getThatAsWell);
}
I feel that using ternary operation make it less maintainable and adds more complexity (checks everytime). But I wanted to get some other opinions.
Note: I have a bunch of try..catch so using if means duplicating those try blocks or adding an if in every block which kind of kills readability.
There's no absolute answer to this question. It depends.
With the ternary operator, you immediately see:
Three properties are always set to some value, and it's always the same properties, independent of the condition.
You see the two alternative values close to one another, so for a reader it's easy to compare them.
But there are some (many?) developers who arent't used to that operator (is that their fault or ours?), so using it might force them to look up its meaning instead of immediately understanding the code (to me, having a LISP background, the ternary operator always was as least natural as the if statement).
And it's true, with the ternary operator, you end up with three conditionals instead of one (but you should ignore these minor performance effects unless you find out that it really hurts in your application).
On the other hand, with the if statement, you immediately see:
It's just one condition that influences all properties.
You see the properties combinations for the two situations close together.
And even Java beginners will understand your code.
So, it depends on:
the Java fluency of your co-workers
whether you want to stress the different values for the single properties or the value-sets for the three properties.
And of course, all this isn't very object-oriented. If code structure and budget allow, maybe you could come up with a solution using polymorphism instead of the conditionals.
I found some questions on SO about checking operations before executions for over/underflow behavior. It seems that there are ways to do this quite easy. So why isn't there an option to automatically check each mathematical operation before execution or why is there not Exception for buffer over/underflow of arithmetic operations? Or phrased differently: In what scenario would it be useful to allow operations to overflow unnoticed?
Is it maybe a matter of run-time? Or is the main source of overflow occurring during non-mathematical operations?
Actually, for C there are checking options, see here: http://danluu.com/integer-overflow/
As for java, adding integer overflow checks would open a can of worms. As java does not offer unsigned types, unsigned math is often done in plain int or long types - obviously the VM will not be magically aware of the unsigned nature of the operation intended, meaning you either need to add unsigned types or the programmer would need to pay a lot of attention to turn the checks on/off. An example for unsigned math with signed types can be found in Arrays.binarySearch. On a side note, Java does exactly define what the result in case of overflow is, so relying on overflow behavior is legal use of defined behavior.
As briefly analyzed in the C link above, these checks can have a severe impact on performance in practice, due to a combination of crude implementation and/or by interfering with other code optimizations.
Also, while most CPU's can detect overflow (usually by the C and V flag), they do it simultaneously for signed/unsigned (common CPU ISA's do not make a distiction between signed/unsigned operations in case of add/sub). Its up to the program to respond to these flags, which means inserting additional instructions into the code. Again this means the programmer/compiler has to be aware if the operation is intended to be signed or unsigned to make the correct choice.
So overflow detection does come with a cost, albeit it could be made reasonably small with good compiler support.
But in many cases overflows are either not possible by design (e.g. the valid input parameters of a function cannot produce overflow), desired (e.g. wrap around behavior counters), or when they do happen are caught by other means when the result is used (e.g. by array bounds checking).
I have to think hard for instances where I actually ever felt the need for overflow checking. Usually you're far more concerned to validate the value range at specific points (e.g. function arguments). But these are arbitrary checks for a function specfic value range, which the compiler cannot even know (well, in some languages it would, because its explicitly expressed, but neither Java nor C fall in this category).
So overflow checking is not universally useful. It doesn't mean there aren't any potential bugs it could prevent, but compared to other bugs types overflow isn't really a common issue. I can't remember when I last saw a bug caused by integer overflow. Off by one bugs are far more common, for example. On the other hand, there are some microoptimizations that explicitly rely on overflow wraparound (e.g. an old question of mine, see accepted answer: Performance: float to int cast and clipping result to range).
With the situation as described, forcing C/Java to check and respond to integer overflow would make them worse languages. They would be slower, and/or the programmer would simply deactivate the feature because it gets in the way more than it is useful. That doesn't mean overflow checking as a language feature would generally be bad; but to really get something out of it, the environment also needs to fit (e.g. as mentioned above, Java would need unsigned types).
TL;DR It could be useful, but it requires much deeper language support than just a switch to be useful.
I can offer two potential factors as to why unchecked arithmetic is the default:
Sense of familiarity: Arithmetic in C and C++ is unchecked by default and people who got used to those languages would not expect the program to throw, but to silently continue. This is a misconception, as both C and C++ have undefined behavior on signed integer overflow/underflow. But nonetheless, it has created a certain expectation in many people's minds and new languages in the same family tend to shy away from visibly breaking established conventions.
Benchmark performance: Detecting overflow/underflow usually requires the execution of more instructions than you would need if you decided to ignore it. Imagine how a new language would look like if a person not familiar with it wrote a math-heavy benchmark (as it often happens) and "proved" that the language is dramatically slower than C and C++ even for the simplest mathematical operations. This would damage people's perception of the language's performance and it could hinder its adoption.
The Java language just does not have this feature built-in as a keyword or mechanism to apply directly for the +, - and * operators. For example, C# has the checked and unchecked keywords for this. However, these checks can be costly and hard to implement, when there is no native support in the language. As for Java 1.8, the methods addExact, subtractExact and multiplyExact have been added to the API to provide this feature, as pointed out by #Tom in the comments.
Why is this not done automatically even if the language supports it? The simple answer is that in general over- and underflow can be accepted or wanted behaviours or they simply do not occur because of a sophisticated and well executed design as it should be. I would say that exploiting over- and underflows is rather a low-level or harware programming concern to avoid additional operations for performance reasons.
Overall, your application design should either explicitly state the sensible use of arithmetic over- and underflows or better not need to use them at all, because it can lead to confusion, unintuitive behaviour or critical bugs. In the first case you don't check, in the second case the check would be useless. An automatic check would be superfluos and only cost performance.
A contrived example of a wanted overflow, could be a counter. Say you have an unsigned short and count it up. After 65536 it goes back to zero because of the overflow, which can be convenient.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Following pseudo-C++-code:
vector v;
... filling vector here and doing stuff ...
assert(is_sorted(v));
auto x = std::find(v, elementToSearchFor);
find has linear runtime, because it's called on a vector, which can be unsorted. But at that line in that specific program we know that either: The program is incorrect (as in: it doesn't run to the end if the assertion fails) or the vector to search for is sorted, therefore allowing a binary search find with O(log n). Optimizing it into a binary search should be done by a good compiler.
This is only the easiest worst case behavrior I found so far (more complex assertions may allow even more optimization).
Do some compilers do this? If yes, which ones? If not, why don't they?
Appendix: Some higher level languages may easily do this (especially in case of FP ones), so this is more about C/C++/Java/similar languages
Rice's Theorem basically states that non-trivial properties of code cannot be computed in general.
The relationship between is_sorted being true, and running a faster search is possible instead of a linear one, is a non-trivial property of the program after is_sorted is asserted.
You can arrange for explicit connections between is_sorted and the ability to use various faster algorithms. The way you communicate this information in C++ to the compiler is via the type system. Maybe something like this:
template<typename C>
struct container_is_sorted {
C c;
// forward a bunch of methods to `c`.
};
then, you'd invoke a container-based algorithm that would either use a linear search on most containers, or a sorted search on containers wrapped in container_is_sorted.
This is a bit awkward in C++. In a system where variables could carry different compiler-known type-like information at different points in the same stream of code (types that mutate under operations) this would be easier.
Ie, suppose types in C++ had a sequence of tags like int{positive, even} you could attach to them, and you could change the tags:
int x;
make_positive(x);
Operations on a type that did not actively preserve a tag would automatically discard it.
Then assert( {is sorted}, foo ) could attach the tag {is sorted} to foo. Later code could then consume foo and have that knowledge. If you inserted something into foo, it would lose the tag.
Such tags might be run time (that has cost, however, so unlikely in C++), or compile time (in which case, the tag-state of a given variable must be statically determined at a given location in the code).
In C++, due to the awkwardness of such stuff, we instead by habit simply note it in comments and/or use the full type system to tag things (rvalue vs lvalue references are an example that was folded into the language proper).
So the programmer is expected to know it is sorted, and invoke the proper algorithm given that they know it is sorted.
Well, there are two parts to the answer.
First, let's look at assert:
7.2 Diagnostics <assert.h>
1 The header defines the assert and static_assert macros and
refers to another macro,
NDEBUG
which is not defined by <assert.h>. If NDEBUG is defined as a macro name at the point in the source file where <assert.h> is included, the assert macro is defined simply as
#define assert(ignore) ((void)0)
The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included.
2 The assert macro shall be implemented as a macro, not as an actual function. If the macro definition is suppressed in order to access an actual function, the behavior is undefined.
Thus, there is nothing left in release-mode to give the compiler any hint that some condition can be assumed to hold.
Still, there is nothing stopping you from redefining assert with an implementation-defined __assume in release-mode yourself (take a look at __builtin_unreachable() in clang / gcc).
Let's assume you have done so. Now, the condition tested could be really complicated and expensive. Thus, you really want to annotate it so it does not ever result in any run-time work. Not sure how to do that.
Let's grant that your compiler even allows that, for arbitrary expressions.
The next hurdle is recognizing what the expression actually tests, and how that relates to the code as written and any potentially faster, but under the given assumption equivalent, code.
This last step results in an immense explosion of compiler-complexity, by either having to create an explicit list of all those patterns to test or building a hugely-complicated automatic analyzer.
That's no fun, and just about as complicated as building SkyNET.
Also, you really do not want to use an asymptotically faster algorithm on a data-set which is too small for asymptotic time to matter. That would be a pessimization, and you just about need precognition to avoid such.
Assertions are (usually) compiled out in the final code. Meaning, among other things, that the code could (silently) fail (by retrieving the wrong value) due to such an optimization, if the assertion was not satisfied.
If the programmer (who put the assertion there) knew that the vector was sorted, why didn't he use a different search algorithm? What's the point in having the compiler second-guess the programmer in this way?
How does the compiler know which search algorithm to substitute for which, given that they all are library routines, not a part of the language's semantics?
You said "the compiler". But compilers are not there for the purpose of writing better algorithms for you. They are there to compile what you have written.
What you might have asked is whether the library function std::find should be implemented to potentially seek whether or not it can perform the algorithm other than using linear search. In reality it might be possible if the user has passed in std::set iterators or even std::unordered_set and the STL implementer knows detail of those iterators and can make use of it, but not in general and not for vector.
assert itself only applies in debug mode and optimisations are normally needed for release mode. Also, a failed assert causes an interrupt not a library switch.
Essentially, there are collections provided for faster lookup and it is up to the programmer to choose it and not the library writer to try to second guess what the programmer really wanted to do. (And in my opinion even less so for the compiler to do it).
In the narrow sense of your question, the answer is they do if then can but mostly they can't, because the language isn't designed for it and assert expressions are too complicated.
If assert() is implemented as a macro (as it is in C++), and it has not been disabled (by setting NDEBUG in C++) and the expression can be evaluated at compile time (or can be data traced) then the compiler will apply its usual optimisations. That doesn't happen often.
In most cases (and certainly in the example you gave) the relationship between the assert() and the desired optimisation is far beyond what a compiler can do without assistance from the language. Given the very low level of meta-programming capability in C++ (and Java) the ability to do this is quite limited.
In the wider sense I think what you're really asking for is a language in which the programmer can make asserts about the intention of the code, from which the compiler can choose between different translations (and algorithms). There have been experimental languages attempting to do that, and Eiffel had some features in that direction, but I'm now aware of any mainstream compiled languages that could do it.
Optimizing it into a binary search should be done by a good compiler.
No! A linear search results in a much more predictable branch. If the array is short enough, linear search is the right thing to do.
Apart from that, even if the compiler wanted to, the list of ideas and notions it would have to know about would be immense and it would have to do nontrivial logic on them. This would get very slow. Compilers are engineered to run fast and spit out decent code.
You might spend some time playing with formal verification tools whose job is to figure out everything they can about the code they're fed in, which asserts can trip, and so forth. They're often built without the same speed requirements compilers have and consequently they're much better at figuring things out about programs. You'll probably find that reasoning rigorously about code is rather harder than it looks at first sight.
When Java 8 was released, I was expecting to find its implementation of Optional to be basically the same as Guava's. And from a user's perspective, they're almost identical. But Java 8's Optional uses null internally to mark an empty Optional, rather than making Optional abstract and having two implementations. Aside from Java 8's version feeling wrong (you're avoiding nulls by just hiding the fact that you're really still using them), isn't it less efficient to check if your reference is null every time you want to access it, rather than just invoke an abstract method? Maybe it's not, but I'm wondering why they chose this approach.
Perhaps the developers of Google Guava wanted to develop an idiom closer to those of the functional world:
datatype ‘a option = NONE | SOME of ‘a
In whose case you use pattern matching to check the true nature of an instance of type option.
case x of
NONE => //address null here
| SOME y => //do something with y here
By declaring Option as an abstract class, the Google Guava is following this approach, where Option represent the type ('a option), and the subclasses for of and absent would represent the particular instances of this type (SOME 'a and NONE).
The design of Option was thoroughly discussed in the lambda mailing list. In the words of Brian Goetz:
The problem is with the expectations. This is a classic "blind men
and elephant" problem; the thing called Optional has different
"essential natures" to different viewpoints, and the problem is not
that each is not valid, the problem is that we're all using the same
word to describe different concepts (more precisely, assuming that the
goals of the JDK team are the same as the goals of the people you
condescendingly refer to as "those familiar with the concept."
There is a narrow design scope of what Optional is being used for in
the JDK. The current design mostly meets that; it might be extended
in small ways, but the goal is NOT to create an option monad or solve
the problems that the option monad is intended to solve. (Even if we
did, the result would still likely not be satisfactory; without the
rest of the class library following the same monadic API conventions,
without higher-kinded generics to abstract over different kinds of
monads, without linguistic support for flatmap in the form of the <-
operator, without pattern matching, etc, etc, the value of turning
Optional into a monad is greatly decreased.) Given that this is not
our goal here, we're stopping where it stops adding value according to
our goals. Sorry if people are upset that we're not turning Java into
Scala or Haskell, but we're not.
On a purely practical note, the discussions surrounding Optional have
exceeded its design budget by several orders of magnitude. We've
carefully considered the considerable input we've received, spent no
small amount of time thinking about it, and have concluded that the
current design center is the right one for the current time. What is
surely meant as well-intentioned input is in fact rapidly turning into
a denial-of-service attack. We could spend endless time arguing this
back and forth, and there'd be no JDK 8 as a result. I'm sure no one
wants that.
So, let's keep our input on the subject to that which is within the
design center of the current implementation, rather than trying to
convince us to change the design center.
i would expect virtual method invocation lookup to be more expensive. you have to load the virtual function table, look up an offset, and then invoke the method. a null check is a single bytecode that reads from a register and not memory.
In drools the drools dialect, conjunctions are implicit. For example:
rule "new drool"
when
Fact(id=="fact1")
Fact(id=="fact2")
then
end
The above requires there be two Fact objects. One must have an id of "fact1", the other must have an id of "fact2".
However, the AND operator does exist. You could write the same drools as follows:
rule "new drool"
when
Fact(id=="fact1") AND
Fact(id=="fact2")
then
end
I was under the impression that there is absolutely no logical or practical difference between these two expressions. However, I have a user telling me he is experiencing different behavior when he uses the explicit conjunction vs the implicit one. I am skeptical, but I haven't been able to find any documentation to support my position. Does anyone know whether an implicit vs explicit conjunction in drools could see different behavior?
The AND is implicit between the two Conditional Elements, so if the user is experiencing different behaviours there should be a bug there. If you can manage to reproduce in a test case the different behaviours please open a jira for it.