• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

What's all the fuss about java assertions?

 
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I want to take the OCMJD exam and I am reading the book "SCJD Exam with J2SE 5" written by Andrew Monkhouse and Terry Camerlengo.

At page 49 it says:

Caution You should never use assertions to validate the inputs on public methods—these are methods that other programmers may use, and they may not honor your requirements. You should validate these inputs regardless of whether or not assertions are turned on at runtime.



And it even gives an example of correct use of assertions:



In my opinion this code has a big problem: if you withdraw something from your account and the balance becomes less than 0, then no exceptional event is signaled if assertions are turned off (for example in a production environment).
So from my point of view, I should validate these post-conditions and throw a checked exception instead of doing that assertion thing.

Let me know about your opinion regarding assertions...
 
Bartender
Posts: 3648
16
Android Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Looking at Andrew's assertion example, it has a problem. The assert statement is checked after it has deducted the withdrawal amount. Instead a better version may look something like



As for the OCMJD, you should not rely on assertion. In fact you should not even have an assert statement. Throwing (meaningful) exceptions when validation fails is acceptable.

And welcome to the Ranch.
 
Alexandru Dragoi
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the feedback K. Tsang!
I just started to document myself and read books regarding OCMJD and I think that JavaRanch forum is a great resource to learn.
 
K. Tsang
Bartender
Posts: 3648
16
Android Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Alexandru Dragoi wrote:Thanks for the feedback K. Tsang!
I just started to document myself and read books regarding OCMJD and I think that JavaRanch forum is a great resource to learn.



Yes this forum/site is great place to learn.

Good luck with the assignment. You may want to check out the SCJD FAQ and SCJD wall of fame for pointers and hints.
 
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

K. Tsang wrote:Looking at Andrew's assertion example, it has a problem. The assert statement is checked after it has deducted the withdrawal amount. Instead a better version may look something like


I don't want to be harsh, but you are completely wrong here! That's exactly what the caution (mentioned in the OP) is all about: don't use assertions to verify parameters (arguments) of a public method. So his example is spot on!

If you want to check parameters (arguments) from a public method use IllegalArgumentException instead, like:


With regard to the OCMJD assignment: I didn't use any assertions at all, but a gazillion IllegalArgumentException (and IllegalStateException) to guarantee correct use of the API as possible.

Good luck!
 
K. Tsang
Bartender
Posts: 3648
16
Android Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Roel I agree using assertions is bad. My example is just try to illustrate if assertion was used, the assert statement should check the current balance before withdrawal rather than after.
 
Ranch Hand
Posts: 59
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Checking the balance after makes sense if it's not possible for the balance to be negative. For example, reduceBalance checks the balance itself and throws an exception if there are insufficient funds. This way the program doesn't rely on assertions for correct behavior. They are only used for documentation or testing.

Assertions aren't normally used on parameters because the method can not make any guarantees of what values they have.
 
Alexandru Dragoi
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Sresh Rangi wrote:Checking the balance after makes sense if it's not possible for the balance to be negative. For example, reduceBalance checks the balance itself and throws an exception if there are insufficient funds. This way the program doesn't rely on assertions for correct behavior. They are only used for documentation or testing.

Assertions aren't normally used on parameters because the method can not make any guarantees of what values they have.



That's more realistic!
I was confused because the implementation for reduceBalance was not revealed so I thought that the assertion was the only check to be done.
If the reduceBalance method checks and validates the withdrawalAmount against the current balance by throwing an exception, then I think that this is a good implementation.

However, I would prefer a checked exception (instead of a runtime IllegalArgumentException/IllegalStateException) to be thrown if the validation fails. That is because if the user tries to withdraw an invalid amount, this should be a recoverable condition and not a programming error.
 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Alexandru Dragoi wrote:However, I would prefer a checked exception (instead of a runtime IllegalArgumentException/IllegalStateException) to be thrown if the validation fails. That is because if the user tries to withdraw an invalid amount, this should be a recoverable condition and not a programming error.


Throwing a checked exception when this validation fails is of course even better. But you always have to be careful when using checked exceptions: when used thoughtless they can clutter your code in no time, certainly when you are designing/creating a framework/library/API. And as already mentioned in my previous post: I used IllegalArgumentException/IllegalStateException to guarantee correct use of the API as possible. So that's to prevent a developer of abusing the API, when it goes wrong it's not a recoverable condition, the developer just mad a mistake. The exception which is thrown when a room/contractor is already booked, is definitely a checked exception.
 
Alexandru Dragoi
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Roel De Nijs wrote:

Alexandru Dragoi wrote:However, I would prefer a checked exception (instead of a runtime IllegalArgumentException/IllegalStateException) to be thrown if the validation fails. That is because if the user tries to withdraw an invalid amount, this should be a recoverable condition and not a programming error.


Throwing a checked exception when this validation fails is of course even better. But you always have to be careful when using checked exceptions: when used thoughtless they can clutter your code in no time, certainly when you are designing/creating a framework/library/API. And as already mentioned in my previous post: I used IllegalArgumentException/IllegalStateException to guarantee correct use of the API as possible. So that's to prevent a developer of abusing the API, when it goes wrong it's not a recoverable condition, the developer just mad a mistake. The exception which is thrown when a room/contractor is already booked, is definitely a checked exception.



Let me see if I understand well...

So in my case for a reduceBalance(int withdrawalAmount) method, if I choose to do this:

I must specify in the javadoc that it is a violation to withdraw an something that is bigger than the current amount.
So it will be up to the client of the API who calls this method to perform the actual validation.

Because I specify this in the javadoc, if the client that implements the API fails to adhere to the contract, then this is a programming error and the runtime exception is suitable for my case.
 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Alexandru Dragoi wrote:So it will be up to the client of the API who calls this method to perform the actual validation.


Exactly But this client could be some kind of service (it doesn't has to be a client like some user interface).

Imagine a BankAccount class whiich has an instance variable balance and a method withdraw. The amount to withdraw can never be bigger than the balance total. This domain class will only be used in service classes, not directly by any GUI. So to validate this rule (and to protect your API) you implement the method like this:

The BankAccountService has also a method to withdraw an amount of a certain balance. Because this service will be used by (several) GUI(s) you'll throw a checked exception here, because this is a recoverable situation (user must choose a lower amount to withdraw). An implementation could be:


And as an illustration of an API/library where wrong usage of checked exceptions can result in cluttered code, have a look at this JSONObject class. If you have a look at the several put-methods you'll see this method throws a checked JSONException when the key is null. That means I always have to catch (or handle) this exception even if I know for sure that the key can never be null, like in this example:

So it requires 3-4 lines of extra code for a situation which can never occur! Another drawback: you can never test the catch-clause because it will never occur. So if you use a quality management platform (e.g. SonarQube) to measure your source code quality (and test coverage) you can never get a 100% score for this class, because of this checked exception.

Checked exceptions are nice and a very powerful language structure, but they must be used with great care; otherwise it will be a burden instead of a blessing!
 
Alexandru Dragoi
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Roel, I think I get the idea!
Indeed, for the BankAccount which cannot be directly called by the API users (may well be package-private), the IllegalArgumentException seems more suitable than a checked exception.
On the other hand, the BankAccountService makes part of the public API and it is better to throw a checked exception here, because the API users must have a way to respond.

Now regarding JSONObject, it looks horrible! And they cannot even change the API without breaking their clients code.
JSONObject seems to be doomed forever!
 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Alexandru Dragoi wrote:Now regarding JSONObject, it looks horrible! And they cannot even change the API without breaking their clients code.
JSONObject seems to be doomed forever!


It's not completely doomed: they can simply make JSONException a runtime exception instead of a checked one. That shouldn't break any client code.

In my current project I have to use this class. So I know what it means for your code if you have to use a badly designed API But I created a JSONUtils class with a few utility methods to gracefully handle this issue: e.g. the method put(JSONObject jsonObject, String key, Object value) checks if the key is null and if it's null a runtime exception is thrown (because it means 1 of the developers has made a mistake during development). So only in this utility class the JSONException can appear, but nowhere else. So this "workaround" decreases code cluttering and allows us to achieve 100% test coverage. That's how it should be designed in the 1st place.
 
Alexandru Dragoi
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for this discussion Roel!
That was more than enough for me to understand well what I needed to understand!
 
Talk sense to a fool and he calls you foolish. -Euripides A foolish tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic