Java 8 resolved the Tri-lean case, and I didn't know !
-
That is my first post on the DWTF. While i'm a fervent reader since 2010 I never posted before because lots of code I see here is so much better (erm... you see what I mean) than the code I see daily I don't think my contribution would be worth it... Until today...
I'm working since more than a week on a web application we just got back from one of our contractors. I should have been production ready two weeks ago but we quickly found the application was crippled of bugs and mis behavior so my bosses called me (and another pal) to patch/glue/sew/anythingelseyoucanimagine the application in order to make it work a much as we can.
It quickly turned the code (either Java or Javascript) was of very high WTF standards.
I'm just gonna share the last bit I found this morning which made me understand that I totally missed what Java8 really offered us since it has been publicly available. Shame on me.
This part of code is a OTP validation system. OTP is 6 digits long and is only valid for a couple of minutes.
public Boolean verifyOtpUserBOCode(OtpUserBODTO otpUserBODTO, String otp) { // First some null tests... if(Objects.isNull(otpUserBODTO)) { log.info("otpUserBODTO NULL "); return null; } OtpUserBO otpUserBO = otpUserBORepository.findOneByLogin(otpUserBODTO.getLogin()); if(Objects.isNull(otpUserBO)){ log.info("otpUserBO NULL "); return null; } // Get duration from database and do nothing of it RefParam refParam = refParamRepository.findOneByLibelleParam(Constantes.DURATION_OTP_CODE_IN_SECOND); Long durationOtpCode = 0L; if(!Objects.isNull(refParam)){ durationOtpCode = Long.parseLong(refParam.getValeurParam()); } // another null check ZonedDateTime dateCreationOtpCode = otpUserBO.getDateCreationOtpCode(); if(Objects.isNull(dateCreationOtpCode)){ log.info("dateCreationOtpCode NULL"); return null; } // Check if the OTP in DB is the same as the one passed in parameter if(otp.equals(otpUserBO.getOtpCode())) return true; return false; }
As you can see we are returning true/false/null, quite a standard tri-lean. You can also notice the good use of dateCreationOtpCode and durationOtpCode... Yes they are absolutely not checking the expiration time...
What is really ingenious here is how they handle the result !
Boolean resultFound = verifyOtpUserBOCode(otpUserBODTO, otpCode); return Optional.ofNullable(resultFound) .map(result -> new ResponseEntity<>( result, HttpStatus.OK)) .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
Optional.ofNullable ! Damn that's really elegant ! Thanks Java 8 !
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
OtpUserBODTO
fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf
-
Objects.isNull()
? Really?!= null
wasn't good enough?An extra WTF is using
!Objects.isNull(...)
instead ofObjects.nonNull(...)
, if going that route.
-
@zecc LOL, yes didn't took time to talk about it, but the code is crippled of those and I made the very same remark :D
-
@ben_lubar pfff, this is reaalllllly not the worst name you could see through this code ;)
-
@zecc said in Java 8 resolved the Tri-lean case, and I didn't know !:
Objects.isNull()
? Really?!= null
wasn't good enough?An extra WTF is using
!Objects.isNull(...)
instead ofObjects.nonNull(...)
, if going that route.Objects.isEqualToFive(4) // false
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
Thanks Java
Guys, I found TRWTF!
-
@doctorjones #troll (too bad I can't massively upvote ;))
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
That is my first post on the DWTF
Lies! You have two posts from seven years ago.
-
@coldandtired Ho ? Seriously ? Don't remember those !!!!
-
@coldandtired Damn, one post and one reply in fact, didn't remember those. The snippet came from a "normal" project actually, much more normal than what i'm working on at the moment
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
Optional.ofNullable ! Damn that's really elegant ! Thanks Java 8 !
Options are quite nice… in languages where they are actually efficient. In Java, building an object, with (at least) 3 pointers overhead (one pointer to point to it, one pointer for VMT and one for the metadata), just to handle
if something == null
is brutal overkill. And while the method calls and type checks (Java still type-erases generics) can be inlined and optimized, optimizing away allocations is, in many cases, not possible (especially if they actually returned Optional as it was (presumably) intended).Also,
java.lang.Optional
is broken, because it is itself nullable, so it actually has two, distinct, ways in which it can be None:null
andOptional.EMPTY
. This thing just makes no sense without value types (did I hear they are finally considering them for Java 9?).Instead, they should have provided the combinators for all references. That would actually make sense.
-
@bulb said in Java 8 resolved the Tri-lean case, and I didn't know !:
did I hear they are finally considering them for Java 9?
Havn't they been considering them since like java 5 ? Or is it just sane people begging for them ?
-
@swayde I don't really know. I don't generally care for Java (and this is part of the reason why—if a language has strong typing, it should allow zero-cost analog of Boost.Units, otherwise the type system misses the point).
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
As you can see we are returning true/false/null, quite a standard tri-lean.
I'd suggest trying to refactor verifyUserBodyOdor() into returning an Optional<boolean>, if performance isn't super important; and if Optional supported primitive types, which it doesn't.
As @Bulb mentioned, the use of this kind of "option type" can be nice. Your taste might vary, of course.
Entertains the idea of code returningOptional.of(Boolean.TRUE)
,Optional.of(Boolean.FALSE)
andOptional.empty()
.
Yeah, the correct refactoring is: just return an Enum already!
-
@zecc said in Java 8 resolved the Tri-lean case, and I didn't know !:
Yeah, the correct refactoring is: just return an Enum already!
Or an
int
eger, assuming you actually want to reduce overhead for real.
-
@bulb said in Java 8 resolved the Tri-lean case, and I didn't know !:
This thing just makes no sense without value types (did I hear they are finally considering them for Java 9?).
AFAIK, they'll be postponed to Java 10.
-
FLAGGED FOR Libelle
-
-
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
@coldandtired Damn, one post and one reply in fact, didn't remember those. The snippet came from a "normal" project actually, much more normal than what i'm working on at the moment
In any case, welcome in! It's nice when lurkers come out of the light.
-
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
@doctorjones #troll (too bad I can't massively upvote ;))
That's
:trollface:
(or:trolleybus:
)
-
@dcon said in Java 8 resolved the Tri-lean case, and I didn't know !:
@twister said in Java 8 resolved the Tri-lean case, and I didn't know !:
@doctorjones #troll (too bad I can't massively upvote ;))
That's
:trollface:
(or:trolleybus:
)ITYM
-
@dcon what about
:passport_control:
?
-
-
-
-
@accalia That's off
:anger:
not off:troll:
-
@pleegwat said in Java 8 resolved the Tri-lean case, and I didn't know !:
@accalia That's off
:anger:
not off:troll:
i have no idea what you could mean....
-
presents an as a peace offering
-
Anyway. The reason why Boolean etc. suck so much as nullable types is because they were designed for different problem - how to store primitives in generic containers.
-
Wait, isn't Optional<Boolean> a FIVE-state boolean?
-
- null Optional<Boolean>
- Empty Optional<Boolean> (Optional<Boolean> containing null)
- Optional<Boolean> containing False Boolean
- Optional<Boolean> containing True Boolean
- ???
What am I missing?
-
@ben_lubar No, MsoTriState is the five-state boolean
https://msdn.microsoft.com/en-us/library/aa432714(office.12).aspx
-
@hungrier OMG, didn't know this !
-
@hungrier said in Java 8 resolved the Tri-lean case, and I didn't know !:
MsoTriState is the five-state boolean
Is it for checkboxes?
-
@zecc said in Java 8 resolved the Tri-lean case, and I didn't know !:
- null Optional<Boolean>
- Empty Optional<Boolean> (Optional<Boolean> containing null)
- Optional<Boolean> containing False Boolean
- Optional<Boolean> containing True Boolean
- ???
What am I missing?
- Optional<Boolean> containing FILE_NOT_FOUND ???
-
@zecc Optional<Optional<Optional<....>>> ;)
-
@zecc said in Java 8 resolved the Tri-lean case, and I didn't know !:
- null Optional<Boolean>
- Empty Optional<Boolean> (Optional<Boolean> containing null)
- Optional<Boolean> containing False Boolean
- Optional<Boolean> containing True Boolean
- ???
What am I missing?
Wait,
null
andempty
are the same? What's the point of having anOptional<T>
class as opposed to some static methods?
-
@ben_lubar An
Optional
can either be empty or contain a non-null value. Having theOptional
itself be null is .One use of it is with collection implementations that don't permit null values. Another is as a more obvious signal than
@Nullable
that empty values need to be handled.
-
@greybeard I wish C# strings weren't nullable, so I could do
string? foo;
(That'sNullable<String>
for you Java people).
-
@ben_lubar said in Java 8 resolved the Tri-lean case, and I didn't know !:
@greybeard I wish C# strings weren't nullable, so I could do
string? foo;
(That'sNullable<String>
for you Java people).Also,
Nullable<Nullable<T>>
should totally be a thing people can do, but it isn't. (Imagine pulling data out of a database and not knowing whether the field exists, whether it's null, or whether it's the default value for the type.) C# has some dumb thing called DBNull, which is not null.
-
@ben_lubar
Nullable
is an annotation, not a generic. There's no such thing asNullable<String>
.One can do:
Optional<Optional<String>> foo = Optional.of(Optional.of("bar"));
if one is sufficiently crazy.
-
@greybeard said in Java 8 resolved the Tri-lean case, and I didn't know !:
@ben_lubar
Nullable
is an annotation, not a generic. There's no such thing asNullable<String>
.Having said that, its declaration is
public struct Nullable<T> where T : struct
so T can only be a struct, of whichstring
isn't one.
-
@powerlord said in Java 8 resolved the Tri-lean case, and I didn't know !:
@greybeard said in Java 8 resolved the Tri-lean case, and I didn't know !:
@ben_lubar
Nullable
is an annotation, not a generic. There's no such thing asNullable<String>
.Having said that, its declaration is
public struct Nullable<T> where T : struct
so T can only be a struct, of whichstring
isn't one.Is
int??
orNullable<int?>
a thing? I seem to remember it not being one.
-
@ben_lubar said in Java 8 resolved the Tri-lean case, and I didn't know !:
@greybeard I wish C# strings weren't nullable, so I could do
string? foo;
(That'sNullable<String>
for you Java people).That's a proposed feature for C# 8.
-
@ben_lubar said in Java 8 resolved the Tri-lean case, and I didn't know !:
C#ADO has some dumb thing called DBNull, which is not null.It's a library thing, not a language thing.
-
@raceprouk said in Java 8 resolved the Tri-lean case, and I didn't know !:
@ben_lubar said in Java 8 resolved the Tri-lean case, and I didn't know !:
@greybeard I wish C# strings weren't nullable, so I could do
string? foo;
(That'sNullable<String>
for you Java people).That's a proposed feature for C# 8.
Wouldn't making strings non nullable be a massive backwards compatibility break?
-
@jaloopa said in Java 8 resolved the Tri-lean case, and I didn't know !:
@raceprouk said in Java 8 resolved the Tri-lean case, and I didn't know !:
@ben_lubar said in Java 8 resolved the Tri-lean case, and I didn't know !:
@greybeard I wish C# strings weren't nullable, so I could do
string? foo;
(That'sNullable<String>
for you Java people).That's a proposed feature for C# 8.
Wouldn't making strings non nullable be a massive backwards compatibility break?
Yes, which is why it'll be opt-in IIRC.
-
@raceprouk so you'd be able to choose to make strings non nullable in order to make some of them nullable?
Don't get me wrong, I quite like the idea of a language where nothing is nullable without explicitly stating it can be, but adding it as an option into something where there's 15 years of legacy code is, at best, going to be used about as much as
checked