Skip to content
This repository has been archived by the owner on Mar 5, 2023. It is now read-only.

Reduce unnecessary asserts #239 #414

Merged
merged 2 commits into from
Jun 1, 2017

Conversation

Zhiyuan-Amos
Copy link
Contributor

@Zhiyuan-Amos Zhiyuan-Amos commented May 15, 2017

Fixes #239

Proposed merge commit message:

Parameter validation is done by using asserts, and throws AssertionError
when validation fails.

Asserts may not always be enabled. Furthermore, specific exceptions
such as NullPointerException should be thrown to make the error more
explicit.

Let's
    - Replace the asserts for public APIs with checkNotNull() and
      checkArgument(), which throws an appropriate exception when 
      validation fails.
    - Enhance CollectionUtil#isAnyNull(…) to do the same operation as
      Objects#requireNonNull(T), and also able to take in multiple 
      parameters.

@CanIHasReview-bot
Copy link

v1

@Zhiyuan-Amos submitted v1 for review.

(📚 Archive)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/1/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you want to fetch this PR to.

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[v1]

EditCommand#createEditedPerson() and EditCommandParser#parseTagsForEdit() still uses assert keyword.

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[v1 1/2]
Just a clarification question.

@@ -25,7 +25,6 @@
* Returns true if the list contains an equivalent person as the given argument.
*/
public boolean contains(ReadOnlyPerson toCheck) {
assert toCheck != null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does ObservableList allow null elements? If it does, then internalLIst.contains() will not trigger an NPE.

Copy link
Contributor Author

@Zhiyuan-Amos Zhiyuan-Amos May 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, it allows null elements. If the list allows for null elements, does it mean that we should allow the method to be called contains(null)? Or should we require it to be non-null?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For our side, it should prohibit accepting null, so we should use checkNotNull()

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[v1 2/2]

Replace asserts with proper exceptions for parameter validation

Parameter validation is done by using asserts, and throws AssertionError
when validation fails.

Asserts may not always be enabled. Furthermore, specific exceptions
such as NullPointerException should be thrown to make the error more
explicit.

Let's replace the asserts with checkNotNull() and checkArgument(),
which throws an appropriate exception when validation fails.

@Zhiyuan-Amos Zhiyuan-Amos force-pushed the 239-reduce-asserts branch 3 times, most recently from 4f67e03 to 9617027 Compare May 16, 2017 07:46
@CanIHasReview-bot
Copy link

v2

@Zhiyuan-Amos submitted v2 for review.

(📚 Archive) (📈 Interdiff between v1 and v2)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/2/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you want to fetch this PR to.

@yamgent
Copy link
Member

yamgent commented May 17, 2017

@pyokagan @MightyCupcakes For your review please, as both of you have previously suggested a guideline on how we can replace the asserts. :)

@yamgent yamgent requested a review from damithc May 18, 2017 03:01
@pyokagan
Copy link
Contributor

Check if any of the comments from #300 apply here.

@pyokagan pyokagan removed their request for review May 18, 2017 05:17
@pyokagan
Copy link
Contributor

It may be a good idea to start off from the commits in #300, rather than starting from scratch (so reviewers don't have to make the same comments).

@Zhiyuan-Amos
Copy link
Contributor Author

Yup I've referred to the commits from #300. We discussed with prof, prof's opinion is that we should replace assert with checkNotNull for every public method, even though there may be methods inside the method that will throw NPE.

Rationale is: Some of the method calls that throw NPE are found in the middle of the execution of the method. The code executed earlier in the method may have persistent effects, which may result in unintended changes to the program when the app crashes due to NPE.

@pyokagan
Copy link
Contributor

@Zhiyuan-Amos

we should replace assert with checkNotNull for every public method, even though there may be methods inside the method that will throw NPE.

OK. That should have been in the commit message.

How about other differences between this PR and #300? E.g., the use of Guava's checkNotNull() instead of JDK's requireNotNull()? As well as the other stylistic differences like the use of the:

this.someField = requireNonNull(someField);

pattern?

@@ -30,7 +33,7 @@
*/
public ModelManager(ReadOnlyAddressBook addressBook, UserPrefs userPrefs) {
super();
assert !CollectionUtil.isAnyNull(addressBook, userPrefs);
checkArgument(!CollectionUtil.isAnyNull(addressBook, userPrefs));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be throwing an NullPointerException or an IllegalArgumentException?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably NullPointerException, I think, since this is implicitly just checking the arguments to this constructor.

Copy link
Contributor Author

@Zhiyuan-Amos Zhiyuan-Amos May 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup this is a good catch. Perhaps CollectionUtil.isAnyNull should throw NullPointerException if any of the variables are null?

Currently CollectionUtil.isAnyNull is only used in assert statements so when assert is enabled, they throw AssertionError. As such, if we let CollectionUtil.isAnyNull throw NPE instead, I don't think there's much that need to be changed in the codebase :>

Edit: We can rename it as well to be requireNonNull to sound similar to Objects.requireNonNull

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zhiyuan-Amos I think this still doesn't throw NullPointerException?

@pyokagan
Copy link
Contributor

the use of Guava's checkNotNull() instead of JDK's requireNotNull()?

I think that it's not good to use Guava's functions actually, as checking arguments and not-null has to be done throughout the code-base and it would mean that the code in addressbook-level4 can't be trivially shared with the other levels (since they are not supposed to have access to a java build system like gradle). Instead, I think it's better to just use the standard library's requireNotNull() and write our own checkArgument().

@Zhiyuan-Amos Zhiyuan-Amos force-pushed the 239-reduce-asserts branch 4 times, most recently from 2295b00 to fc13a60 Compare May 19, 2017 05:32
@CanIHasReview-bot
Copy link

v3

@Zhiyuan-Amos submitted v3 for review.

(📚 Archive) (📈 Interdiff between v2 and v3)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/3/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you want to fetch this PR to.

*/
public static void checkArgument(Boolean condition, String errorMessage) {
if (!condition) {
throw new IllegalArgumentException();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorMessage isn't used.

@CanIHasReview-bot
Copy link

v7

@Zhiyuan-Amos submitted v7 for review.

(📚 Archive) (📈 Interdiff between v6 and v7)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/7/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

Copy link
Contributor

@MightyCupcakes MightyCupcakes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message:

Let's replace the asserts with checkNotNull() and checkArgument(),
which throws an appropriate exception when validation fails.

I thought we are using requireNonNull?

Copy link
Contributor

@MightyCupcakes MightyCupcakes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message:

Java native Objects#requireNonNull(T) can only take in ...

Java -> Java's

@CanIHasReview-bot
Copy link

v8

@Zhiyuan-Amos submitted v8 for review.

(📚 Archive) (📈 Interdiff between v7 and v8)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/8/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

Parameter validation is done by using asserts, and throws AssertionError
when validation fails.

Asserts may not always be enabled. Furthermore, specific exceptions
such as NullPointerException should be thrown to make the error more
explicit.

Let's replace the asserts with requireNonNull() and checkArgument(),
which throws an appropriate exception when validation fails.
@CanIHasReview-bot
Copy link

v9

@Zhiyuan-Amos submitted v9 for review.

(📚 Archive) (📈 Interdiff between v8 and v9)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/9/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

@Zhiyuan-Amos
Copy link
Contributor Author

added tests for AppUtil#checkArgument

*/
public static boolean isAnyNull(Collection<?> items) {
return items.stream().anyMatch(Objects::isNull);
public static void requireNonNull(Collection<?> items) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Giving this the same name as Objects#requireNonNull may be dangerous though. If import static seedu.address.commons.util.CollectionUtil.requireNonNull is not present in the file, then Objects#requireNonNull would be used instead, which would be hard to detect by just reading the diff in a code review.

Maybe give this another name? Maybe requireNonNullElements or requireAllNonNull.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright!

@Zhiyuan-Amos
Copy link
Contributor Author

@MightyCupcakes any comments? :>

@MightyCupcakes
Copy link
Contributor

No other comments.

@Zhiyuan-Amos Zhiyuan-Amos force-pushed the 239-reduce-asserts branch 2 times, most recently from 1ac1e31 to 931511e Compare May 30, 2017 12:20
Java’s native Objects#requireNonNull(T) can only take in an Object.
Calling the native method requires multiple calls in cases where certain
methods require multiple parameters to be non-null.

Let’s update CollectionUtil#isAnyNull(…) to do the same operation as
Objects#requireNonNull(T), and also able to take in multiple parameters.
@CanIHasReview-bot
Copy link

v10

@Zhiyuan-Amos submitted v10 for review.

(📚 Archive) (📈 Interdiff between v9 and v10)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/414/10/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

@Zhiyuan-Amos
Copy link
Contributor Author

@MightyCupcakes ping :>

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants