How can i replace assertions with if's? Example:
public Wezel<Wartosc,Indeks> getWujek()
{
assert rodzic != null; // Root node has no uncle
assert rodzic.rodzic != null; // Children of root has no uncle
return rodzic.getBrat();
}
An assertion is roughly equivalent to:
if (!condition) {
throw new AssertionError();
}
public Wezel<Wartosc,Indeks> getWujek()
{
if(rodzic == null) { // Root node has no uncle
throw new Exception("Root node has no uncle");
}
if(rodzic.rodzic == null) {
throw new Exception("Children of root have no uncle");
}
return rodzic.getBrat();
}
Replacing these assertions would take the form of the following validation:
if (rodzic == null)
throw new MyValidationException("rodzic cannot be null");
if (rodzic.rodzic == null)
throw new MyValidationException("rodzic.rodzic cannot be null");
return rodzic.getBrat();
Note that there's a distinction between throwing an Exception and an Error - Exceptions are meant to be caught and handled farther up, while Errors indicate a situation that you can't recover from. For example, you might consider a defining and using a MyValidationError if the failed check is irrecoverable.
Related
I'm currently investing a lot of time in cleaning up my code.
I have a lot of If statements that handles my signup form in frontend.
I have a feeling that after reading the book "Clean code". That this is just ugly, however I didn't seem to find any "amazing/incredible" cleanup format for my code below.
lets say I have 15 more if-statements then this will cause a lot of duplicates, so are there any major improvements possible?
User userByUsername = userRepo.findByUsername(user.getUsername());
User userByEmail = userRepo.findUserByEmail(user.getEmail());
if (userByUsername != null && userByEmail != null) {
throw new AccountException("Email and username already exist");
}
if (userByUsername != null) {
throw new AccountException("Username already exist");
}
if (userByEmail != null) {
throw new AccountException("Email already exist");
}
Another example with another method:
public void addConditions(ReservationDto reservationDto) {
long roomId = roomService.findRoomByRoomName(reservationDto.getRoomName()).getRoomId();
// Check for adding room: Roomcapacity for timeslote reached
// If maxCapacityAfternoon reached, then only add to afternoon possible
int roomCapacity = roomService.findRoomByRoomId(roomId).getCapacity();
boolean maxCapacityMorning = roomCapacity <= getNumberOfReservationsForRoomByDateVoormiddag(roomId, reservationDto.getDate());
boolean maxCapacityAfternoon = roomCapacity <= getNumberOfReservationsForRoomByDateNamiddag(roomId, reservationDto.getDate());
boolean isMorning = reservationDto.isMorning();
boolean isAfternoon = reservationDto.isAfternoon();
capacityConditions(reservationDto, maxCapacityMorning, maxCapacityAfternoon);
// Check: Reservation can only be made when it meets the following conditions
// - Same user
// - is active
// - Morning and date overlap
// - Afternoon and date overlap
Reservation mappedReservation = mapReservationDto(reservationDto);
int amountOfReservationsForDay = reservationRepo.existsReservationForDay(mappedReservation.getUsername(), mappedReservation.getDate());
if (isMorning && isAfternoon) {
if (amountOfReservationsForDay > 0) {
throw new ServiceException(RESERVATION_MSG + FOR_FULL_DAY + reservationDto.getDate());
}
if (reservationRepo.existsReservationForMorning(mappedReservation.getUsername(), mappedReservation.getDate()) > 0
|| reservationRepo.existsReservationForAfterNoon(mappedReservation.getUsername(), mappedReservation.getDate()) > 0
) {
throw new ServiceException(RESERVATION_MSG + "in de voor- of namiddag.");
}
}
if (isMorning && !isAfternoon) {
if (amountOfReservationsForDay > 0) {
throw new ServiceException(RESERVATION_MSG + FOR_FULL_DAY + reservationDto.getDate());
}
if (reservationRepo.existsReservationForMorning(mappedReservation.getUsername(), mappedReservation.getDate()) > 0) {
throw new ServiceException(RESERVATION_MSG + "in de voormiddag.");
}
}
if (!isMorning && isAfternoon) {
if (amountOfReservationsForDay > 0) {
throw new ServiceException(RESERVATION_MSG + FOR_FULL_DAY + reservationDto.getDate());
}
if (reservationRepo.existsReservationForAfterNoon(mappedReservation.getUsername(), mappedReservation.getDate()) > 0) {
throw new ServiceException(RESERVATION_MSG + "in de namiddag");
}
}
if (!isMorning && !isAfternoon) {
throw new ServiceException("Selecteer een tijdstip voor uw reservatie");
}
}
As you can see my project has a lot of conditions when I want to add a reservation. These are only the add conditions and don't take into account the room capacity check. Which is a long list of If's as well
You could create an enum for all the data validation exceptions that can be thrown
public enum DataValidationError {
USERNAME_EXISTS,
EMAIL_EXISTS,
...
}
public static class AccountException extends Exception {
private final List<DataValidationError> errors;
public AccountException(List<DataValidationError> errors) {
this.errors = errors;
}
public List<DataValidationError> getErrors() {
return errors;
}
}
Usage:
List<DataValidationError> errors = new ArrayList<>();
User userByUsername = userRepo.findByUsername(user.getUsername());
User userByEmail = userRepo.findUserByEmail(user.getEmail());
if (userByUsername != null) {
errors.add(DataValidationError.USERNAME_EXISTS);
}
if (userByEmail != null) {
errors.add(DataValidationError.EMAIL_EXISTS);
}
if (!errors.isEmpty()) {
throw new AccountException(errors);
}
This way you could add as many errors in the enum and keep adding them to a list and throw it only once at the end.
I am not sure if any really major improvement can be applied here. But for example since you are throwing the same type of exception you might play around your error message and throw exception only once. Like:
if(userByEmail != null || userByUsername != null){
String message = (userByEmail != null ? "Email" : "Username") + " already exist";
if(userByEmail != null && userByUsername != null){
message = "Email and username already exist";
}
throw new AccountException(message);
}
For make the code more extensible and close I would use a chain of validation for this kind of things. If you know about the SOLID principle, you have a problem of SRP and OCP. By implementing a chain of validation, you would have each node have one purpose and you could easily and more validation in the futur. After you just have to create a chain !
The thing is that validation is ONE thing, so I would too create lost of tiny function with good names, so the reader can "escape early" the reading if needed.
Here is the design patern that could help you: https://refactoring.guru/design-patterns/chain-of-responsibility
I think you repository should thow those exceptions too ! If you can't find a user throw an exception in your repository. You'll have less validation all over you code and it's easyer to read.
For the below piece of code Sonar throws me a critical violation - Correctness - Nullcheck of status value previously dereferenced
Can someone suggest on this on what am I doing wrong here?
code
public boolean isExactMacthBill(AddressResponse response) {
boolean exactMatch = false;
if (null != response && null != response.getHostResponse()) {
HostResponseDetail hostResponse = response.getHostResponse();
String addressStatus = hostResponse.getMatchStatus();
ResponseDetail status = hostResponse.getStatus();
String addressMatchCode = status.getCode();
if (null != response.getMatchedAddresses() && response.getMatchedAddresses().size() > 0 && status != null) {
if (addressStatus.equalsIgnoreCase(Constants.USPS_MATCH)
|| (addressStatus.equalsIgnoreCase(Constants.PARTIAL_MATCH)
&& addressMatchCode.equalsIgnoreCase("3SXU"))) {
exactMatch = true;
} else
exactMatch = false;
}
}
return exactMatch;
}
The actual problem is in the line after the highlighted one - you've got:
if (... && status != null)
Just remove that check and I think SonarLint will be happy. It unnecessary, because if status is null then status.getCode() will already have thrown an exception before you reach that condition.
Fundamentally, you need to know whether getStatus() should ever return null - whether you have to handle that situation explicitly. If you do, you should check it before your call to status.getCode(), and react accordingly. If you don't, it's fine to call the getCode() method - if your assumption is incorrect, you'll get a NullPointerException as normal, which is probably the most appropriate result for the scenario of "the world isn't as I expect it to be". But you shouldn't try to "handle" it being null after you've already depended on it being non-null.
status can be null when it is received from hostResponse.getStatus();; so when the line String addressMatchCode = status.getCode(); is called it can result in a Null Reference Exception.
You should verify all the variables if there are null before calling methods on them.
Move your addressMatchCode inside your if condition which null check the status.
public boolean isExactMacthBill(AddressResponse response) {
boolean exactMatch = false;
if (null != response && null != response.getHostResponse()) {
HostResponseDetail hostResponse = response.getHostResponse();
String addressStatus = hostResponse.getMatchStatus();
ResponseDetail status = hostResponse.getStatus();
if (null != response.getMatchedAddresses() && response.getMatchedAddresses().size() > 0 && status != null) {
String addressMatchCode = status.getCode();
if (addressStatus.equalsIgnoreCase(Constants.USPS_MATCH)
|| (addressStatus.equalsIgnoreCase(Constants.PARTIAL_MATCH)
&& addressMatchCode.equalsIgnoreCase("3SXU"))) {
exactMatch = true;
} else
exactMatch = false;
}
}
return exactMatch;
}
I tried to find a similar question, but I didn't succeed.
In a bean, I'm looping through a ViewEntryCollection several times, adding or deleting entries. Could someone tell me exactly when these objects should be recycled? I want to be able to reuse the whole collection so I don't want to destroy any objects I might still need.
My code:
public static int FTSearchAll(ViewEntryCollection vec, View vw, String cat, String query) throws NotesException {
...
for (ViewEntry ve = nav.getFirst(); ve != null; ) {
ViewEntry next = nav.getNext(ve);
Document doc = ve.getDocument();
if (doc == null)
continue;
try {
Vector v = session.evaluate(query, doc);
if (v != null && v.size() > 0 && (Double) v.elementAt(0) != 0) {
vec.addEntry(ve, false);
} else {
for (ViewEntry dce = vec.getFirstEntry(); dce != null;) {
ViewEntry dcnext = vec.getNextEntry(dce);
if (dce.getNoteID().equals(ve.getNoteID())) {
vec.deleteEntry(dce);
incinerate(dce);
break;
}
dce = dcnext;
}
}
} catch (NotesException ne) {
} finally {
incinerate(ve, doc);
}
ve= next;
}
As always: thanks!
The rule is quite simple: when a Java object pointing to a Notes C object is about to go onto the garbage heap, .recycle() must have been called.
So you need to do that for all entries inside the loop.
My little rule of thumb: the block (think { ... } ) that created a Notes Java object must call its .recycle() function at the end.
Saves you lot of headaches
I see this, but not completely sure whether I miss something or the code keeps its functionality... :S
for (ViewEntry ve = nav.getFirst(); ve != null; ) {
ViewEntry next = nav.getNext(ve);
Document doc = ve.getDocument();
if (doc == null) {
incinerate(ve); // << new
ve = next; // << new
continue;
}
try {
Vector v = session.evaluate(query, doc);
if (v != null && v.size() > 0 && (Double) v.elementAt(0) != 0) {
vec.addEntry(ve, false);
} else {
for (ViewEntry dce = vec.getFirstEntry(); dce != null;) {
ViewEntry dcnext = vec.getNextEntry(dce);
if (dce.getNoteID().equals(ve.getNoteID())) {
vec.deleteEntry(dce);
incinerate(dce, dcnext); // << new
break;
}
incinerate(dce); // << new
dce = dcnext;
}
}
} catch (NotesException ne) {
} finally {
incinerate(ve, doc);
}
ve = next;
}
Maybe it would be better to check another implementation.
Anyway, I recommend you to use the OpenNTF Domino API and get rid of recycle, and you will get also a proper iteration over entries:
http://www.openntf.org/main.nsf/project.xsp?r=project/OpenNTF%20Domino%20API
The code below is for javax.activation.DataHandler.getDataContentHandler, 1.41, 07/05/14.
If the dataContentHandler member variable is null when the method is called, then it gets set by the 'if' clause at [1] (which is what happens in my program).
It then immediately gets overwritten in the if clause at [2].
Am I missing something, or is that unlikely to be the intended behaviour?
private synchronized DataContentHandler getDataContentHandler() {
// make sure the factory didn't change
if (factory != oldFactory) {
oldFactory = factory;
factoryDCH = null;
dataContentHandler = null;
transferFlavors = emptyFlavors;
}
if (dataContentHandler != null)
return dataContentHandler;
String simpleMT = getBaseType();
if (factoryDCH == null && factory != null)
factoryDCH = factory.createDataContentHandler(simpleMT);
if (factoryDCH != null)
dataContentHandler = factoryDCH;
if (dataContentHandler == null) { // [1]
if (dataSource != null)
dataContentHandler = getCommandMap().
createDataContentHandler(simpleMT, dataSource);
else
dataContentHandler = getCommandMap().
createDataContentHandler(simpleMT);
}
// getDataContentHandler always uses these 'wrapper' handlers
// to make sure it returns SOMETHING meaningful...
if (dataSource != null) // [2]
dataContentHandler = new DataSourceDataContentHandler(
dataContentHandler,
dataSource);
else
dataContentHandler = new ObjectDataContentHandler(
dataContentHandler,
object,
objectMimeType);
return dataContentHandler;
}
I
Am I missing something, or is that unlikely to be the intended behaviour?
Looks like that is the intended behavior per the comment:
// getDataContentHandler always uses these 'wrapper' handlers
// to make sure it returns SOMETHING meaningful...
If you look closely at the code, the 'dataContentHandler' is passed as an argument to 'new DataSourceDataContentHandler' and 'new ObjectDataContentHandler'. That is the 'wrapping' referred to in the comment.
I am using auto generated JPAController of Netbeans 8 using Java 1.8.
public void create(Physical physical) {
if (physical.getTalentCollection() == null) {
physical.setTalentCollection(new ArrayList<Talent>());
}
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
Specialmark specialmarkId = physical.getSpecialmarkId();
System.out.println(specialmarkId+ "...nullValue");
if (specialmarkId != null) {
System.out.println(specialmarkId+ "...ain't right");
specialmarkId = em.getReference(specialmarkId.getClass(), specialmarkId.getId());
physical.setSpecialmarkId(specialmarkId);
}
.....
}
During physical object creation, Specialmark (part of physical object) is an optional.
It can have a value or be null.
Specialmark in the table physical allows you to have null values.
When Specialmark is null, the if (specialmarkId != null) {...} should skipped. Instead, it got ignored and proceed.
the error message is
"... An instance of a null PK has been incorrectly provided for this find operation.
at db.jpa.PhysicalJpaController.create(PhysicalJpaController.java:57)"
System.out.println(specialmarkId+ "...nullValue");
output "null...nullValue" it shows specialmarkId value is null
System.out.println(specialmarkId+ "...ain't right");
Output "null...ain't right" shows if (specialmarkId != null) {...} has been ignored even specialmarkId is null.
Why does (specialmarkId != null) {...} not work?
I guess specialmarkId is not really null, but specialmarkId.toString() is overwriten for it to return the string "null".
Instead of
System.out.println(specialmarkId+ "...nullValue");
try something like
System.out.println((specialmarkId != null?
specialmarkId.toString() + "(not null)": "(this IS REALLY NULL)")
+ "...nullValue");