I have a query that does not have a result, when the DB is empty. Therefore NULL is the correct return value.
However, the compiler in Android Studio gives me the warning: Condition 'maxDateTime != null' is always 'true'.
If I debug the code, the null check performs correctly as the value is actually null.
When I rewrite the interface to 'fun queryMaxServerDate(): String?' (notice the question mark), the compiler warning goes away.
But should not 'fun queryMaxServerDate(): String' result in a compilation error since it can be null?
#Dao
interface CourseDao {
// Get latest downloaded entry
#Query("SELECT MAX(${Constants.COL_SERVER_LAST_MODIFIED}) from course")
fun queryMaxServerDate(): String
}
// calling function
/**
* #return Highest server date in table in milliseconds or 1 on empty/error.
*/
fun queryMaxServerDateMS(): Long {
val maxDateTime = courseDao.queryMaxServerDate()
var timeMS: Long = 0
if (maxDateTime != null) { // Warning: Condition 'maxDateTime != null' is always 'true'
timeMS = TimeTools.parseDateToMillisOrZero_UTC(maxDateTime)
}
return if (timeMS <= 0) 1 else timeMS
}
The underlying code generated by the annotation is java and thus the exception to null safety as per :-
Kotlin's type system is aimed to eliminate NullPointerException's from
our code. The only possible causes of NPE's may be:
An explicit call to throw NullPointerException(); Usage of the !!
operator that is described below;
Some data inconsistency with regard
to initialization, such as when:
An uninitialized this available in a
constructor is passed and used somewhere ("leaking this");
A
superclass constructor calls an open member whose implementation in
the derived class uses uninitialized state;
Java interoperation:
Attempts to access a member on a null reference of a platform type;
Generic types used for Java interoperation with incorrect nullability,
e.g. a piece of Java code might add null into a Kotlin
MutableList, meaning that MutableList should be used
for working with it;
Other issues caused by external Java code.
Null Safety
e.g. the generated code for queryMaxServerDate() in CourseDao would be along the lines of :-
#Override
public String queryMaxServerDate() {
final String _sql = "SELECT max(last_mopdified) from course";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final String _result;
if(_cursor.moveToFirst()) {
final String _tmp;
_tmp = _cursor.getString(0);
_result = _tmp;
} else {
_result = null;
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
As you can see, no data extracted (no first row) and null is returned.
I've read somewhere that a variable should be entered into the code if it is reused. But when I write my code for logic transparency, I sometimes create intermediate variables (with names reflecting what they contain) which are used only once.
How incorrect is this concept?
PS:
I want to do it right.
It is important to note that most of the time clarity takes precedence over re-usability or brevity. This is one of the basic principles of clean code. Most modern compilers optimize code anyway so creating new variables need not be a concern at all.
It is perfectly fine to create a new variable if it would add clarity to your code. Make sure to give it a meaningful name. Consider the following function:
public static boolean isLeapYear(final int yyyy) {
if ((yyyy % 4) != 0) {
return false;
}
else if ((yyyy % 400) == 0) {
return true;
}
else if ((yyyy % 100) == 0) {
return false;
}
else {
return true;
}
}
Even though the boolean expressions are used only once, they may confuse the reader of the code. We can rewrite it as follows
public static boolean isLeapYear(int year) {
boolean fourth = year % 4 == 0;
boolean hundredth = year % 100 == 0;
boolean fourHundredth = year % 400 == 0;
return fourth && (!hundredth || fourHundredth);
}
These boolean variables add much more clarity to the code.
This example is from the Clean Code book by Robert C. Martin.
Should I destroy an instance even if its creation fails in Vulkan?
Which one is correct:
1:
VkResult Result = vkCreateInstance( info, NULL, instance );
if(Result != VK_SUCCESS)
{
vkDestroyInstance(Instance, NULL);
glfwTerminate();
exit(EXIT_FAILURE);
}
2:
VkResult Result = vkCreateInstance( info, NULL, instance );
if(Result != VK_SUCCESS)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
From the specification:
If a command returns a run time error, it will leave any result pointers unmodified, unless other behavior is explicitly defined in the specification.
And since VkCreateInstance takes a VkInstance*, it will be left unmodified.
I have an application that loads in a bundle and in doing so I call CFURLCreateFromFileSystemRepresentation before CFBundleCreate: -
bundlePackageURL = CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault,
(const UInt8*)bundlePackageFileSystemRepresentation,
strlen(bundlePackageFileSystemRepresentation),
true );
Most of the time, running the same application and loading the same bundle that resides in the application bundle's Resource directory, the function works and returns a valid CFURL. However, with exactly the same parameters passed in to the function, the call sometimes fails.
I now have code to handle the failure: -
CFURLRef bundlePackageURL = NULL;
int attempt = 0;
while((bundlePackageURL == NULL) && (attempt++ < 12000))
{
bundlePackageURL = CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault,
(const UInt8*)bundlePackageFileSystemRepresentation,
strlen(bundlePackageFileSystemRepresentation),
true );
// failed to load, so try again
if(bundlePackageURL == NULL)
fprintf(stdout, "Retrying to obtain CFURL: %d...\n", attempt);
}
As you can see, this makes up to 12000 attempts to call the function and when it fails, I've seen it take anything between a few hundred to over 10000 repeated calls before it succeeds.
Can anyone please explain why the function may be failing at times and if this is normal?
I've responded to threads here (or at least commented) with answers containing code like this, but I'm wondering if it's good or bad form to write a series of if branches with one (or more) of the branches doing nothing in them, generally to eliminate checking for null in every branch.
An example (C# code):
if (str == null) { /* Do nothing */ }
else if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
instead of:
if (str != null && str == "SomeSpecialValue")
{
// ...
}
else if (str != null && str.Length > 1)
{
// ...
}
And, of course, this is just an example, as I tend to use these with larger and more complex classes. And in most of these cases, a null value would indicate to do nothing.
For me, this reduces the complication of my code and makes sense when I see it. So, is this good or bad form (a code smell, even)?
I prefer doing it like this-
if (str != null)
{
if (str == "[NULL]")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
I think you can always "reword" an if with an empty body into it's negation with a body, and that it looks better and makes more sense.
I would normally put a return or something like that in the first if:
void Foo()
{
if (str == null) { return; }
if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
If you can't do this, because the function does something else after the if/else, I'd say it's time to refactor, and split the if/else part out into a separate function, from which you can return early.
It is indeed good to avoid the following, because it needlessly re-checks one of the conditions (the fact that the compiler will optimize this away is beside the point--it potentially makes more work for folks trying to read your code):
if (str != null && str == "SomeSpecialValue")
{
// ...
}
else if (str != null && str.Length > 1)
{
// ...
}
But it's also rather bizarre to do what you suggested, below:
if (str == null) { /* Do nothing */ }
else if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
I say this is bizarre because it obfuscates your intent and defies the reader's expectations. If you check for a condition, people expect you to do something if it is satisfied--but you're not. This is because your intent is not to actually process the null condition, but rather to avoid a null pointer when you check the two conditions you're actually interested in. In effect, rather than having two conceptual states to handle, with a sanity provision (non-null input), it reads instead like you have three conceptual states to handle. The fact that, computationally, you could say there are three such states is beside the point--it's less clear.
The usual case approach in this sort of situation is as Oren A suggested--check for the null, and then check the other conditions within the result block:
if (str != null)
{
if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
This is little more than a matter of readability-enhancing style, as opposed to an issue of code smell.
EDIT: However, if you're set on the do-nothing condition, I do very much like that you included a "do nothing" comment. Otherwise, folks might think you simply forgot to complete the code.
In this particular case I will return early and it makes code easier to read
if (string.IsNullOrEmpty(str)) { return; }
I like to put an explicit return statement.
Yes it is a code smell.
One indication is that you thought to ask this question.
Another indication is that the code looks incomplete- as if something should belong there. It may be readable sure, but it feels off.
When reading that code, an outsider has to stop for a second and use brainpower to determine if the code is valid/complete/correct/as intended/adjective.
user359996 hit the nail on the head:
I say this is bizarre because it obfuscates your intent and defies the reader's expectations.
Your first example is perfectly readable to me -- doesn't smell at all.
It all depends on context. If putting an empty if statement makes the code more readable, then go for that.
It's readable, whether it is good or bad depends upon what you are trying to achieve - generally long nested "goes-on-forever" type if statements are bad. Don't forget about static string methods baked into the framework: string.IsNullOrEmpty() and string.IsNullOrWhiteSpace().
Your if (str == null) { /* Do nothing */ } line is unusual, but does have one positive point: it is letting other developers know up front that you are deliberately doing nothing for that case, with your long if/else if structure your intentions could become unclear if you changed it to
if (str != null)
{
/* carry on with the rest of the tests */
}