I've been reading Uncle Bob's Clean Code and have read many articles on the use of Optionals whenever you are faced with returning a null in a Java method. I'm currently refactoring my code and I just don't know how to optimize it with Optionals. Can someone give me some pointers?
public UserLog selectById(String userid) throws DataException {
List<UserLog> logs = selectUserLogs(SQL_SELECT_BY_ID, userid);
return logs.isEmpty() ? null : logs.get(0);
}
private List<UserLog> selectUserLogs(String sql, Object... args) throws DataException {
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, args);
return rows.stream().map(this::toUserLogs)
.collect(Collectors.toList());
}
private UserLog toUserLogs(Map<String, Object> row) {
UserLog userLog = new UserLog("Steven Wozniak", 65, "Male");
return userLog;
}
/**
* Below shows how selectById is being used in another class
*/
...
public void callingMethod() {
if(starttime != null && FIVE_HOUR <= durationSinceStartTime() &&
userLogDao.selectById(userid) != null &&
userLogDao.selectById(userid).getStartTime() != null) {
log.warn("Logs came in late");
}
}
I'm having trouble optimizing the selectById
method. Since I'm doing a Collector.toList()
in the selectUserLogs
method, I can be sure that I will ALWAYS get a List
back. It could be an empty list, but never a null
.
My initial attempt was:
public Optional<UserLog> selectById(String userid) throws DataException {
List<UserLog> logs = selectUserLogs(SQL_SELECT_BY_ID, userid);
return Optional.ofNullable(logs.get(0));
}
However, I completely have no idea how I'm going to optimize the calling of this method and performing the null checks in the callingMethod()
. How would I re-write that so that it looks a tad more elegant?
For your code, I only see this improvement.
If you don't get null
from selectUserLogs
(and I also prefer an empty list than null
), yo can update selectById
and callingMethod
to this:
public Optional<UserLog> selectById(String userid) throws DataException {
List<UserLog> logs = selectUserLogs(SQL_SELECT_BY_ID, userid);
return logs.isEmpty() ? Optional.empty() : Optional.of(logs.get(0));
}
public void callingMethod() {
if (starttime != null && FIVE_HOUR <= durationSinceStartTime()) {
userLogDao.selectById(userid)
.map(UserLog::getStartTime)
.ifPresent(startTime -> log.warn("Logs came in late"));
}
}