Better way to catch trouble points - java

User submits a CSV file which is consumed by a program. Values which are used throughout the program come from the CSV, natually if values are missed it is a problem. Below is my solution.
Ip on top
private List<String> currentFieldName = new ArrayList<String>();
As part of the method:
try {
setCurrentFieldName("Trim Space");
p.setTrimSpace(currentLineArray[dc.getTRIM_POSITION()].equals("yes") ? true : false);
setCurrentFieldName("Ignore Case");
p.setIgnoreCase(currentLineArray[dc.getIGNORE_CASE_POSITION()].equals("yes") ? true : false);
} catch (NullPointerException e) {
throw new InputSpreadsheetValueUnassignedException("\"Type\" field not set: " + currentFieldName);
}
And the method which keeps track of a current field being looked at:
private void setCurrentFieldName(String fieldName) {
currentFieldName.clear();
currentFieldName.add(fieldName);
}
The idea there is that if user fails to submit value and i will end up getting null, before throwing an exception, i will know what value was not assigned.
So, this being said, specific questions:
Is what i have shown below an acceptable solution?
Can you suggest something more elegant?

First thing that comes to my mind is that using an ArrayList to represent the name of a single field is superfluous.
Why not just define a private String currentFieldName; and inside your try { } do currentFieldName = "Trim Space" etc?
Also,
p.setTrimSpace(currentLineArray[index].equals("yes") ? true : false);
can just as well be expressed as
p.setTrimSpace(currentLineArray[index].equals("yes"));
If your code goes through many columns, you could definitely make it more elegant. If not, your time might be better spent on other parts of your project.
The answer to whether or not your solution is acceptable depends on the requirements, and a test suite would be the ideal party to provide the yes or the no.

Related

modify underlying result/value of async object

I am using Kotlin in a webserver app and I have a line of code as follows:
.onComplete { jsonResult: AsyncResult<JsonObject>? ->
Now what I want to do is change the underlying JsonObject wrapped in the AsyncResult, so that it is going to be reflected further downstream.
var res: JsonObject? = jsonResult?.result()
if (res != null) {
if (res.getInteger("files_uploaded") > 0) {
res.put("URL", "Some URL")
}
}
I was then imagining to update the underlying JSON object in the result but not sure how to do that.
please take note that single quotes are missing and ` appear as \` because the code formatting. I tried to leave what seemed least confusing...
You should be able to make changes in the conditional statement
if (res !=null) {
res being the JsonObject:
console.log(res);
would show you what's in there. You may need to use
let resXmodifiedX = JSON.parse(res);
One approach is to write a function and pass res to that function which you can do if it is in the console.log(res).
Some notes on what's below:
place the function somewhere consistent maybe at the bottom of the file...
objects often have multiple levels res.person.name, res.contact.email, or whatever...
use multiple for loops:
let level = res[key]; for(child in level) {
you don't need to do this if you know exactly what object attributes you need to update.
you can set the value directly but you always want to test for it before trying to set it to avoid errors that stop execution.
let toBe = toBe =>`${toBe}`;
let update = (res)?toBe(update(res)):toBe('not Found');
This option is really only if you know for sure that data will be there and you can't proceed without it. Which is not uncommon but also not how JSON is designed to be used.
The code below is a concise way to make some simple changes but may not be an ideal solution. To use it xModify(res) replaces console.log(res) above.
function xModify(x) {
let resXmodifiedX = JSON.parse(x);
let res = resXmodifiedX;
for (key in res) {
res[key] = key=='name'? \`My change ${res[key]}\`: key=='other'? \`My Change ${res[key]}\`:res[key];
resXmodifiedX = JSON.stringify(res);
return resXmodifiedX;
}
That will update res.name and res.other otherwise res[key] is unchanged. If you do not need to parse res change let res = xModifiedx; to let res = x; remove the first line and change the last two lines to return res;
function xModify(x) {
let res = x;
for (key in res) {
res[key] = key=='name'? \`My change ${res[key]}\`: key=='other'? \`My Change ${res[key]}\`:res[key];
return res;
}
If your data is numeric which is not generally the case in a web server response scenario this is a terrible approach. Because it is probably a string I used the template variable as a way to easily add a complex pattern in place of a string. My change ${res[key]} not a real world example. Any valid JS code can go in the ${ } (template variable). I've been defaulting to the first pattern more and more.
let me = (bestCase)?`${'the best version'} of myself`:`${'someone'} I'm ok with`;

Java Error/Exception handling with returning value

So my friend and I are programming Blackjack in Java, and we wanted to test our input fields for the correct input(e.g only number input). So we sat at his PC and he wrote this solution:
public static boolean testeTextFieldInt(JTextField textField, int geld) {
if (!textField.getText().isEmpty()) {
try {
if(Integer.parseInt(textField.getText())>0 && Integer.parseInt(textField.getText())<geld ) {
return true;
}
} catch (NumberFormatException e) {
return false;
}
}
return false;
}
now I disagree with this solution, because your code shouldn't depend on an error, or am I getting this wrong? so i sat down and wrote this:
public static boolean checkInput(JTextField textField, int spielerGeld, String eingabe) {
boolean matched = false;
switch (eingabe) {
case "num":
if (!textField.getText().isEmpty() && textField.getText().matches("^[0-9]*$")) {
int geldinput = Integer.parseInt(textField.getText());
if (geldinput > 0 && geldinput < spielerGeld) {
matched = true;
}
}
break;
case "string":
if (!textField.getText().isEmpty() && textField.getText().matches("^[a-zA-Z]*$")) {
matched = true;
}
break;
default:
break;
}
return matched;
}
Keep in mind, we yet dont have any textfields we have to check, but I just implemented it to get a grasp of how you could do multiple checks within one method.
So now my question is, what code is "better"? and what could we/I do better?
Thanks in advance!
EDIT1:
So as some already have mentioned, you say my method is not build up after the Single responsibility principle.
But if split up into 'checkInputIsnumber' and checkInputIsString' would the first solution(my friend), still be the "better" one?
EDIT2:
Better is defined as in, the method should be of low cyclomatic complexity, easy readability and be easy to maintain in the long run.
The first approach is much better than the second one.
Single responsibility: You should avoid creating methods that do more than one thing.
Open–closed principle: Your 'validation' is not extensible. Try creating a Validator interface and then an implementation per validation type.
Switch statements increase cyclomatic complexity and make testing harder.
Also, don't use textField.getText() everywhere, it's quite possible that it will change between calls. Assign it to a local variable or even better use a String as your argument and not JText. As Fildor pointed out you correctly avoid using exceptions for flow control and it is indeed better to have a single return point. Having said that, for simple cases when you just parse/check and return, it is acceptable.
You should put every check in a single function. After a while your "all in one function" will be unreadable an unmaintainable. Also it easier to change the checks if they are in single functions. Using try/catch for control flow is no good idea. It is expensive at runtime. It is not a good style and most developers won't expect control flow in a catch block.Excpetions are for exceptional situations.

Is it acceptable to throw exceptions when not getting expected JSON data?

Working on an android app which gathers data from the Open Weather API as a JSON. However the JSON does not always contain the same keys (ie. sometimes cloud data or a weather description is included, sometimes it isn't).
Right now my code looks like (with some extra getters/setters I didn't include here):
public class WeatherDescrip {
private String weather;
private String weather_Desc;
private String icon;
public WeatherDescrip(JSONObject weatherObj) {
try {
weather = weatherObj.getString("main");
} catch (JSONException e) {
weather = null;
e.printStackTrace();
}
try {
weather_Desc = weatherObj.getString("description");
} catch (JSONException e) {
weather_Desc = null;
e.printStackTrace();
}
try {
icon = weatherObj.getString("icon");
} catch (JSONException e) {
icon = null;
e.printStackTrace();
}
}
}
Basically if the JSON I get from the API call doesn't have the necessary key I let the program throw an exception, which will usually happen with at least one piece of data each time the app is run (there is more done like this).
If anyone could please let me know whether this is an acceptable way to code, and possibly how to better implement this I would much appreciate it.
If you haven't noticed I'm also a total noob, sorry in advance if this is a terrible way of doing this.
Many Thanks
This is generally not the correct forum for asking opinions, as you're asking for subjective opinions, there's technically no way to gauge a 'correct' answer, although you're free to select whatever answer you choose, if any ;-)
But in the nature of good will, I'll give you a few of my opinions.
Firstly, Exceptions are for just that, exceptions. If you have a scenario where you are in control of the code, and are aware of a potential for something not to occur in an 'ideal' way (e.g. like this, you're receiving dodgy data), then code for it, i.e.
if (data.contains("somethingOfInterest")) {
consume(data);
} else {
getDataFromSomewhereElse();
}
Rather than throw an exception, and force your program to handle it somewhere else (or not). Here's some additional information on why it's not a good idea to use exceptions for control flow.
Also, and this is advice from personal experience; in most scenarios, it's a good idea to do as little as makes sense within an Object's constructor, as it's more ugly to recover if exceptions do occur inside a constructor's method body. Instead, it may be better to encapsulate the logic you have there in some other factory-esque class or method, passing only the gathered data to the constructor. Something like:
public class WeatherDescrip {
private String weather;
private String weather_Desc;
private String icon;
public WeatherDescrip(String weather, String weather_Desc, String icon) {
this.weather = weather;
this.weather_Desc = weather_Desc;
this.icon = icon;
}
}
...
public static WeatherDescrip createWeatherDescrip(JSONObject weatherObj) {
if (!weatherObj.containsKey("main")
|| !weatherObj.containsKey("description")
|| !weatherObj.containsKey("icon")) {
throw SomeNewMeaningfulException("That I understand and can explicitly handle");
or....
return getMyDataFromSomeWhereElse();
}
return new WeatherDescrip(
weatherObj.getString("main"),
weatherObj.getString("description"),
weatherObj.getString("icon")
);
}
I hope this helps.
It's acceptable to throw exceptions whenever you decide. You just need to play how you want to handle it.
Is it acceptable to crash the program and boot your user back to the home screen? Absolutely not. Ever
Just read your data and handle the exceptions gracefully - no icon? Display a default. No data? Tell the user there is a problem right now so they aren't misled by the old data being displayed.
An alternate to avoid the majority of exceptions is to use GSON and Retrofit (I've linked a useful set of tutorials, not the home of GSON or Retrofit). With GSON you can create a model object, automatically map the data and then on your getters always return a value even if the JSON was incomplete
Example:
class MyObj {
#SerializedName("main")
private String weather;
public String getWeather() {
String weatherResult = weather;
if (weatherResult == null || "".equals(weatherResult) {
weatherResult = getString(R.strings.weather_unavailable);
}
return weatherResult;
}
}
Throwing an exception is usually reserved for when an error occurs, rather than having it it being an expected result of running your code, since there is overhead in throwing an exception which can make your program execute (slightly) slower.
Realistically, it can be used whenever you like, however you like, but I might instead suggest using has() to check if the key exists before trying to access it. It's a more efficient way of achieving the same result, without having to throw or catch an exception.
if(weatherObj.has('description')) {
weather_Desc = weatherObj.getString("description");
} else {
weather_Desc = null;
}

Updating pre-existing documents in mongoDB java driver when you've changed document structure

I've got a database of playerdata that has some pre-existing fields from previous versions of the program. Example out-dated document:
{
"playername": "foo"
}
but a player document generated under the new version would look like this:
{
"playername": "bar",
"playercurrency": 20
}
the issue is that if I try to query playercurrency on foo I get a NullPointerException because playercurrency doesn't exist for foo. I want to add the playercurrency field to foo without disturbing any other data that could be stored in foo. I've tried some code using $exists Example:
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playername", "")));
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playercurrency", 20)));
My thought is that it updates only playercurrency because it doesn't exist and it would leave playername alone becuase it exists. I might be using exists horribly wrong, and if so please do let me know because this is one of my first MongoDB projects and I would like to learn as much as I possibly can.
Do you have to do this with java? Whenever I add a new field that I want to be required I just use the command line to migrate all existing documents. This will loop through all players that don't have a playercurrency and set it to 0 (change to whatever default you want):
db.players.find({playercurrency:null}).forEach(function(player) {
player.playercurrency = 0; // or whatever default value
db.players.save(player);
});
This will result in you having the following documents:
{
"playername" : "foo",
"playercurrency" : 0
}
{
"playername" : "bar",
"playercurrency" : 20
}
So I know that it is normally frowned upon on answering your own question, but nobody really posted what I ended up doing I would like to take this time to thank #Mark Watson for answering and ultimately guiding me to finding my answer.
Since checking if a certain field is null doesn't work in the MongoDB Java Driver I needed to find a different way to know when something is primed for an update. So after a little bit of research I stumbled upon this question which helped me come up with this code:
private static void updateValue(final String name, final Object defaultValue, final UUID key) {
if (!exists(name, key)) {
FindIterable iterable = players.find(new Document("_id", key));
iterable.forEach(new Block<Document>() {
#Override
public void apply(Document document) {
players.updateOne(new Document("_id", key), new Document("$set", new Document(name, defaultValue)));
}
});
}
}
private static boolean exists(String name, UUID key) {
Document query = new Document(name, new Document("$exists", true)).append("_id", key);
return players.count(query) == 1;
}
Obviously this is a little specialized to what I wanted to do, but with little revisions it can be easliy changed to work with anything you might need. Make sure to replace players with your Collection object.

How to refactor to avoid passing "special values" into a Java method?

I'm sure there must be a standard way to do this, but my attempts to search Stackoverflow have failed.
I have a method like:
public void processSomeWidgetsForUser(int userItemId) {
Iterator<Widgets> iter = allWidgets.values().iterator();
while(iter.hasNext()) {
Widget thisWidget = iter.next();
if (userItemId == -1 || thisWidget.getUsersItemId() == userItemId) {
widget.process();
}
}
}
As you can see -1 is a "special value" meaning process all. Doing this saves repeating the loop code in another method called processSomeWidgetsForAllUsers.
But I dislike special values like this because they are easy to misuse or misunderstand, which is exactly the situation what I'm having to fix now (where someone thought -1 meant something else).
I can only think of two ways to improve this.
have a constant, containing -1 called something like
Widget.ALLWIDGETS which at least is self-documenting, but doesn't
stop code from using a -1 (if someone integrates old code in, for
example)
change the method to take a list of all user ids to
process, which can be empty, but that doesn't seem great
performance-wise (would need to retrieve all user ids first and then loop through
removing. Also what happens if the number of widgets in the list changes between
retreiving the ids and removing
Is there a better way? I'm sure I'm missing something obvious.
The above code has been changed slightly, so may not compile, but you should get the gist.
Although somewhat redundant, a fairly neat self-documenting approach could be to have 3 methods rather than one;
Make your original method private, and make one small change which would be to add your static final int EXECUTE_ALL = -1 and use that in your original method, then add the two new methods;
public void processWidget(int wID) throws IllegalArgumentException {
if(wID == EXECUTE_ALL) throw new IllegalArgumentException();
originalMethod(wID);
}
public void processAllWidgets() {
originalMethod(EXECUTE_ALL);
}
It makes your class a little more cluttered, but as far as the exposed methods go, it is clearer and hopefully foolproof. You could alter it not to throw an exception and just ignore any invalid ids, that just depends on your situation.
This approach of course has the major downside that it changes how the class appears to other classes, breaking everything that currently uses the, now private, originalMethod().
Number 1 would work very nicely. Be sure to document what the variable is though, so future coders (possibly yourself) know what it means.
/**This is the explanation for the below variable*/
public final static int ALL_WIDGETS = -1;
Have an external method like so:
static boolean idRepresentsAll(int id) {
return id == -1;
}
In this case, if you decide to replace it with a different mechanism, you only replace your magic number one place in your code.
At the very least, you would want to do something like this:
public static final int ID_REPRESENTING_ALL = -1;
You can change the method signature to accept a boolean for when you want to process them all.
public void processSomeWidgets(boolean doAll, int userItemId) {
Iterator<Widgets> iter = allWidgets.values().iterator();
while(iter.hasNext()) {
Widget thisWidget = iter.next();
if (doAll || thisWidget.getUsersItemId() == userItemId) {
widget.process();
}
}
}
This makes it more explicit, and easier to read in my opinion as there are no special values.

Categories

Resources