So I'm currently doing a first year university assignment and I'm a little stuck on one of the questions. It goes as such.
Modify the setType() and setPlan() methods to return a boolean true/false if the chosen type or plan was invalid. I.e if the type was "Bogus", ignore the type, and return a "false" to the call. Modify the Test class to add an "if" statement that will report a false call.
My current line of code for the method looks like this:
public void setType(String newType) {
switch (newType) {
case "Basic":
mType = newType;
break
case "Enhanced":
mType = newType;
break
default:
break
}
My question is, how do I go about adding an if statement and does anything need to be changed to make the void method return a true/false value?
Try this:
public boolean setType(String newType) {
switch (newType) {
case "Basic":
case "Enhanced":
mType = newType;
return true;
default:
return false;
}
}
You don't actually need an extra if statement for doing this, and you can check two or more cases in a switch by using a fallthrough (two or more consecutive case).
You could define an array with all valid types in some globally accessible spot in your app:
public static final String[] VALID_TYPES = {"Basic","Enhanced"};
and then have a method that just iterates all those types and checks if a given value matches one of them:
public static boolean isValidType(String candidate){
for(String validType : VALID_TYPES){
if(validType.equals(candidate)){
return true;
}
}
return false;
}
The nice thing about this - in contrast to using switch statements - is that you can easily modifiy the list of valid types (add/change/remove types) without the need to touch your method that checks a given type for validity. So it's easy to maintain and less error-prone (in a switch, you might forget to add a case statement for each possible value, or you might forget to add a break statement somewhere, etc)
Best practice would say this is "parameter checking", and it's cleaner too to fail early:
public boolean setType(String newType) {
if (!newType.matches("Basic|Enhanced")) {
return false;
}
type = newType; // or whatever you need to do
return true;
}
Options for testing also include:
if (!Arrays.asList("Basic", "Enhanced").contains(newType))
which also neatly handles newType being null without extra code.
But the best way to deal with this is to use an enum, which would not allow bad values in the first place.
The other answers are good. Here's my take. The ternary operator, ? and : expression, is logically an "if then else".
public boolean setType(String newType) {
boolean result = (newType.equals("Basic") || newType.equals("Enhanced"));
mType = result ? newType : mType;
return result;
}
public class YourClass{
private String mType;
private static final List<String> VALID_TYPES = Arrays.asList("Basic","Enhanced");
public boolean setType(String newType){
if(!VALID_TYPES.contains(newType)){
return false;
}
mType = newType;
return true;
}
}
And similar for the setPlan method, just define another list of VALID_PLANS.
And about your test class:
if(!yourClassObject.setType("Some Invalid Type")){
System.err.println("Invalid type!");
}
adding a boolean property of class,like this:
public class Test
{
private boolean flag;
}
Related
I am a little confused on "how to do this properly":
// return true: if present and number of lines != 0
boolean isValid(Optional<File> optFile) {
return optFile.ifPresentOrElse(f -> return !isZeroLine(f), return false);
}
private boolean isZeroLine(File f) {
return MyFileUtils.getNbLinesByFile(f) == 0;
}
I know the syntax is not correct and not compiling, but it's just for you to get the idea.
How can I turn this into 'clean code'?
i.e. avoid doing:
if (optFile.isPresent()) {//} else {//}
Dealing with boolean return type(easily inferred Predicates), one way to do that could be to use Optional.filter :
boolean isValid(Optional<File> optFile) {
return optFile.filter(this::isZeroLine).isPresent();
}
But, then using Optionals arguments seems to be a poor practice. As suggested in comments by Carlos as well, another way of implementing it could possibly be:
boolean isValid(File optFile) {
return Optional.ofNullable(optFile).map(this::isZeroLine).orElse(false);
}
On another note, ifPresentOrElse is a construct to be used while performing some actions corresponding to the presence of the Optional value something like :
optFile.ifPresentOrElse(this::doWork, this::doNothing)
where the corresponding actions could be -
private void doWork(File f){
// do some work with the file
}
private void doNothing() {
// do some other actions
}
I have a sequence of methods that I need to run sequentially, using the result of each method as a parameter in the next. However, I also check that the result of each method is "good" before calling the next method (if it's "bad" then I exit the method early. The methods return an empty Optional if they were not successful.
Is there a refactoring that I can perform to improve the code? Chain of Responsibility feels a little overboard.
private boolean isSequenceSuccessful() {
Optional<byte[]> result1 = doSomething();
if (!result1.isPresent()) {
return false;
}
Optional<byte[]> result2 = doAnotherThing(result1.get());
if (!result2.isPresent()) {
return false;
}
Optional<byte[]> result3 = doSomethingElse(result2.get());
if (!result3.isPresent()) {
return false;
}
return doMoreStuff(result3.get());
}
I don't want to use Exceptions to control the flow of the method because that's a code smell (I expect to sometimes get "bad" results).
You can write it shorter using Optional and mapping:
private boolean isSequenceSuccessful() {
return Optional.of(doSomething())
.flatMap(result1 -> doAnotherThing(result1))
.flatMap(result2 -> doSomethingElse(result2))
.map(result3 -> doMoreStuff(result3))
.orElse(false);
}
Or using method references even shorter:
private boolean isSequenceSuccessful2() {
return Optional.of(doSomething())
.flatMap(this::doAnotherThing)
.flatMap(this::doSomethingElse)
.map(this::doMoreStuff)
.orElse(false);
}
It depends what you prefer. If you want to keep the intermediate result variables use the lambda version.
Since the methods doAnotherThing and doSomethingElse do return an Optional<byte[]>, Optional.flatMap is needed to continue the mapping. Otherwise you could change the return type of these methods to return byte[] solely. Then you would use Optinal.map only, which would be more consistent.
The mapping will only be performed as long as a value is present in the Optional. If all mappings could be applied the value of the last is returned as result. Otherwise the processing will fail fast and bypass all remainig mappings to the last statement orElse and return it's value. This is false according to your code.
You could use the map method:
private boolean isSequenceSuccessful() {
Optional<byte[]> result = doSomething().map(this::doAnotherThing)
.map(this::doSomethingElse);
if (result.isPresent()) return doMoreStuff(result.get());
else return false;
}
Look at the template pattern which I sometimes refer to as the pizza pattern because it is analogous to making a pizza. (eg. createDough(), putIngredients(), bake(), package(), deliver()). This might apply to your case. There are several examples and implementations out there but pick and choose which applies best to you. In your example above, I would create an abstract class and create concrete classes/implementations. Example to give you an idea:
public abstract class SequenceChecker {
// ...
public boolean isSequenceSuccessful() {
Optional<byte[]> result1 = doSomething();
Optional<byte[]> result2 = doAnotherThing(result1);
Optional<byte[]> result3 = doSomethingElse(result2);
return doMoreStuff(result3);
}
protected abstract boolean doMoreStuff(Optional<byte[]> result);
protected abstract Optional<byte[]> doSomethingElse(Optional<byte[]> result);
protected abstract Optional<byte[]> doAnotherThing(Optional<byte[]> result);
protected abstract Optional<byte[]> doSomething();
// ...
}
Use Optional::flatMap.
private boolean isSequenceSuccessful() {
Optional<Boolean> result = doSomething()
.flatMap(this::doAnotherThing)
.flatMap(this::doSomethingElse)
.map(this::doMoreStuff);
return result.isPresent() ? result.get() : false;
}
I have two similar, but of different types, blocks of code in Java:
private Integer readInteger() {
Integer value = null;
while (value == null) {
if (scanner.hasNextInt()) {
value = scanner.nextInt();
} else {
scanner.next();
}
}
return value;
}
private Double readDouble() {
Double value = null;
while (value == null) {
if (scanner.hasNextDouble()) {
value = scanner.nextDouble();
} else {
scanner.next();
}
}
return value;
}
Is it possible to make just one method which would work for both of them?
I'd say, use a generic method, combined with the functional interfaces introduced in Java 8.
The method read now becomes a higher order function.
private <T> T read(Predicate<Scanner> hasVal, Function<Scanner, T> nextVal) {
T value = null;
while (value == null) {
if (hasVal.test(scanner)) {
value = nextVal.apply(scanner);
} else {
scanner.next();
}
}
return value;
}
Calling code becomes:
read(Scanner::hasNextInt, Scanner::nextInt);
read(Scanner::hasNextDouble, Scanner::nextDouble);
read(Scanner::hasNextFloat, Scanner::nextFloat);
// ...
So the readInteger() method can be adapted as follows:
private Integer readInteger() {
return read(Scanner::hasNextInt, Scanner::nextInt);
}
You could have something with three methods:
One which says if there is a value of the right type
Another which gets the value of the right type.
Another which discards whatever token you have.
For example:
interface Frobnitz<T> {
boolean has();
T get();
void discard();
}
You can pass this into your method:
private <T> T read(Frobnitz<? extends T> frob) {
T value = null;
while (value == null) {
if (frob.has()) {
value = frob.get();
} else {
frob.discard();
}
}
return value;
}
And then just implement Frobnitz for your Double and Integer cases.
To be honest, I'm not sure this gets you very much, especially if you've only got two cases; I'd be inclined just to suck up the small amount of duplication.
A lot of people have answered that you can use generics, but you can also simply remove the readInteger method, and only use the readDouble, as integers can be converted to doubles without data loss.
This is about code duplication.
The general approach is to turn similar code (you have) into equal code that can be extracted to a common parameterized method.
In your case what make the two code snipped differ is the access to methods of Scanner. You have to encapsulate them somehow. I'd suggest to do this with Java8 Functional interfaces like this:
#FunctionalInterface
interface ScannerNext{
boolean hasNext(Scanner scanner);
}
#FunctionalInterface
interface ScannerValue{
Number getNext(Scanner scanner);
}
Then replace the actual invocation of methods in scanner with the functional interface:
private Integer readInteger() {
ScannerNext scannerNext = (sc)->sc.hasNextInt();
ScannerValue scannerValue = (sc)-> sc.nextInt();
Integer value = null;
while (value == null) {
if (scannerNext.hasNext(scanner)) {
value = scannerValue.getNext(scanner);
} else {
scanner.next();
}
}
return value;
}
There is one more problem that the type of the value variable differs. So we replace it with its common supertype:
private Integer readInteger() {
ScannerNext scannerNext = (sc)->sc.hasNextInt();
ScannerValue scannerValue = (sc)-> sc.nextInt();
Number value = null;
while (value == null) {
if (scannerNext.hasNext(scanner)) {
value = scannerValue.getNext(scanner);
} else {
scanner.next();
}
}
return (Integer)value;
}
Now you have to places with a big equal section. You can select one of those sections starting with Number value = null; ending with the } before return ... and invoke your IDEs automated refactoring extract method:
private Number readNumber(ScannerNext scannerNext, ScannerValue scannerValue) {
Number value = null;
while (value == null) {
if (scannerNext.hasNext(scanner)) {
value = scannerValue.getNext(scanner);
} else {
scanner.next();
}
}
return value;
}
private Integer readInteger() {
return (Integer) readNumber( (sc)->sc.hasNextInt(), (sc)-> sc.nextInt());
}
private Double readDouble() {
return (Double) readNumber( (sc)->sc.hasNextDouble(), (sc)-> sc.nextDouble());
}
Comments argue against the use of custom interfaces against predefined interfaces from the JVM.
But my point in this answer was how to turn similar code into equal code so that it can be extracted to a single method rather that giving a concrete solution for this random problem.
Not an ideal solution but it still achieves the necessary removal of duplicate code and has the added benefit of not requiring Java-8.
// This could be done better.
static final Scanner scanner = new Scanner(System.in);
enum Read{
Int {
#Override
boolean hasNext() {
return scanner.hasNextInt();
}
#Override
<T> T next() {
return (T)Integer.valueOf(scanner.nextInt());
}
},
Dbl{
#Override
boolean hasNext() {
return scanner.hasNextDouble();
}
#Override
<T> T next() {
return (T)Double.valueOf(scanner.nextDouble());
}
};
abstract boolean hasNext();
abstract <T> T next();
// All share this method.
public <T> T read() {
T v = null;
while (v == null) {
if ( hasNext() ) {
v = next();
} else {
scanner.next();
}
}
return v;
}
}
public void test(String[] args) {
Integer i = Read.Int.read();
Double d = Read.Dbl.read();
}
There are some minor issues with this such as the casting but it should be a reasonable option.
A totally different approach from my other answer (and the other answers): don't use generics, but instead just write the methods more concisely, so you don't really notice the duplication.
TL;DR: rewrite the methods as
while (!scanner.hasNextX()) scanner.next();
return scanner.nextX();
The overall goal - write it as a single method - is only possible if you accept some amount of additional cruft.
Java method signatures do not take into account the return type, so it's not possible to have a next() method return an Integer in one context, and Double in another (short of returning a common supertype).
As such, you have to have something at the call sites to distinguish these cases:
You might consider passing something like Integer.class or Double.class. This does have the advantage that you can use generics to know that the returned value matches that type. But callers could pass in something else: how would you handle Long.class, or String.class? Either you need to handle everything, or you fail at runtime (not a good option). Even with a tighter bound (e.g. Class<? extends Number>), you still need to handle more than Integer and Double.
(Not to mention that writing Integer.class and Double.class everywhere is really verbose)
You might consider doing something like #Ward's answer (which I do like, BTW: if you're going to do it with generics, do it like that), and pass in functional objects which are able to deal with the type of interest, as well as providing the type information to indicate the return type.
But, again, you've got to pass these functional objects in at each call site, which is really verbose.
In taking either of these approaches, you can add helper methods which pass the appropriate parameters to the "generic" read method. But this feels like a backwards step: instead of reducing the number of methods to 1, it's increased to 3.
Additionally, you now have to distinguish these helper methods somehow at the call sites, in order to be able to call the appropriate one:
You could have overloads with a parameter of value type, rather than class type, e.g.
Double read(Double d)
Integer read(Integer d)
and then call like Double d = read(0.0); Integer i = read(0);. But anybody reading this code is going to be left wondering what that magic number in the code is - is there any significance to the 0?
Or, easier, just call the two overloads something different:
Double readDouble()
Integer readInteger()
This is nice and easy: whilst it's slightly more verbose than read(0.0), it's readable; and it's way more concise that read(Double.class).
So, this has got us back to the method signatures in OP's code. But this hopefully justifies why you still want to keep those two methods. Now to address the contents of the methods:
Because Scanner.nextX() doesn't return null values, the method can be rewritten as:
while (!scanner.hasNextX()) scanner.next();
return scanner.nextX();
So, it's really easy to duplicate this for the two cases:
private Integer readInteger() {
while (!scanner.hasNextInt()) scanner.next();
return scanner.nextInt();
}
private Double readDouble() {
while (!scanner.hasNextDouble()) scanner.next();
return scanner.nextDouble();
}
If you want, you could pull out a method dropUntil(Predicate<Scanner>) method to avoid duplicating the loop, but I'm not convinced it really saves you that much.
A single (near-)duplicated line is way less burdensome in your code than all those generics and functional parameters. It's just plain old code, which happens to be more concise (and, likely, more efficient) than "new" ways to write it.
The other advantage of this approach is that you don't have to use boxed types - you can make the methods return int and double, and not have to pay the boxing tax unless you actually need it.
This may not be of advantage to OP, since the original methods do return the boxed type; I don't know if this is genuinely desired, or merely an artefact of the way the loop was written. However, it is useful in general not to create those objects unless you really need them.
Reflection is an alternative if you don't care about performance.
private <T> T read(String type) throws Exception {
Method readNext = Scanner.class.getMethod("next" + type);
Method hasNext = Scanner.class.getMethod("hasNext" + type);
T value = null;
while (value == null) {
if ((Boolean) hasNext.invoke(scanner)) {
value = (T) readNext.invoke(scanner);
} else {
scanner.next();
}
}
return value;
}
Then you call
Integer i = read("Int");
I have the following code:
void f(String t)
{
if(t.equals("a"))
{
someObject.setType(ObjectType.TYPE_A);
}
else if(t.equals("b"))
{
someObject.setType(ObjectType.TYPE_B);
}
// 50 more similar code
}
Is there any simple way to rewrite the if-else condition so as not to have that much code?
You should use something to eliminate the repetition of someObject.setType(ObjectType....)) If ObjectType is an enum, then write a method there similar to valueOf that will achieve that. See if you like this kind of solution:
void f(String t) { someObject.setType(ObjectType.byName(t)); }
enum ObjectType {
TYPE_A, TYPE_B;
public static ObjectType byName(String name) {
return valueOf("TYPE_" + name.toUpperCase());
}
}
Use a Map (which you'll have to populate) that maps from String to whatever type your ObjectType.TYPE_x values are.
I would add this as a functionality of the enum:
public enum ObjectType {
TYPE_A("a"),
TYPE_B("b");
private String stringType;
private ObjectType(String stringType) {
this.stringType = stringType;
}
public String getStringType() {
return this.stringType;
}
public static ObjectType fromStringType(String s) {
for (ObjectType type : ObjectType.values()) {
if (type.stringType.equals(s)) {
return type;
}
}
throw new IllegalArgumentException("No ObjectType with stringType " + s);
}
}
...
void f(String t) {
someObject.setType(ObjectType.fromStringType(t));
}
If you can refactor t into a char, you could use switch instead (Java 6):
void f(char t) {
switch(t) {
case 'a`:
someObject.setType(ObjectType.TYPE_A);
break;
case 'b':
someObject.setType(ObjectType.TYPE_B);
break;
// ...
}
}
As Marko pointed out, you could go with String too in Java 7.
It isn't that much shorter, but more elegant. Moreover, I think it might be faster too, as switch works close to O(1) with jump tables (Can somebody confirm whether this is true?), whether a number of if statements is O(n).
Fore more complex implementations than just a single setType you might think of a State Pattern implementation too.
1.You can go for Switch statement if you have number of if conditions more than 3.
2.you can convert your if else statements to ternary operations
The other suggestions are great - particularly smarter enums and maps. But the first most basic refactoring I would tackle here is to extract a method to return the enum directly and have the caller perform nothing more than the setType to that method's return value.
void f(String t) {
final ObjectType type = findType(t);
if (type != null)
someObject.setType(type);
}
ObjectType findType(String t) {
if (t.equals("a")) return ObjectType.TYPE_A;
if (t.equals("b")) return ObjectType.TYPE_B;
// 50 more similar code
}
In some cases this will be sufficient in and of itself; in others the findType() method may lead you to a simple map- or enum-based solution.
I import data from a XML file to use it internally. Now there is an uint value, which is (according to the XSD) not required. Now here is the question: How do map this behaviour in my class (it is unclear, if the Value is present or not, but I need to know at runtime)
Basically I see 3 solutions:
Solution 1: Use values of which we know that they are invalid to flag the Value as 'not-set':
public class Solution1 {
private int optionalVal;
public boolean isSetOptionalVal() {
return (optionalVal>=0);
}
public void setOptionalVal(int val) {
optionalVal = val;
}
public void unSetOptionalVal() {
optionalVal = -1;
}
public int optionalVal() {
if(isSetOptionalVal()) {
return optionalVal;
} else {
return -1;
}
}
}
Solution 2: Use the boxed class and set it to null if the value is 'not-set':
public class Solution2 {
private Integer optionalVal;
public boolean isSetOptionalVal() {
return (optionalVal!=null);
}
public void setOptionalVal(int val) {
optionalVal = val;
}
public void unSetOptionalVal() {
optionalVal = null;
}
public int optionalVal() {
if(isSetOptionalVal()) {
return optionalVal;
} else {
return -1;
}
}
}
Solution 3: Use an additional variable that describes the value as 'not-set':
public class Solution3 {
private int optionalVal;
private boolean optionalValSet;
public boolean isSetOptionalVal() {
return (optionalValSet);
}
public void setOptionalVal(int val) {
optionalVal = val;
optionalValSet = true;
}
public void unSetOptionalVal() {
optionalValSet = false;
}
public int optionalVal() {
if(isSetOptionalVal()) {
return optionalVal;
} else {
return -1;
}
}
}
These are my proposals to solve the issue, but I don't really like any of those.
Solution 1 seems very hacky, maybe there is somewhere a point where I can't determine the invalid value.
Solution 2 is actually the solution I am using, but I only need the additional information for some of the memeber variables, so I have either to use some variables as boxed types and some as primitive (which seems inconsistent) or I have always to use the boxed types (which I don't really like).
Solution 3 seems to be the cleanest, but here I am worried, that at some place the bool isn't set correctly, which would be a hard to find error (I already have a lot of code, and found the problem, that some elements are not set in the XML just recently)
So...what would you prefer as a solution to solve the "Optional Value"-problem - is there maybe an even better solution?
How is this problem generally handled?
I'd choose option 2, using the Integer class, and leave the conversion between int and Integer to autoboxing. The advantage of this approach is that it keeps everything concerned with your optional value in a single variable.
The first option is a magic value, and if the unused value becomes a used value later, it becomes a nightmare to maintain.
The third option means having to keep track of both the int and the boolean that keeps track of the question whether it is used. If you're going to do this, consider making it a class in and of itself... but then you might as well use Integer.
Solution 2 is by far the cleanest. That's exactly what null is for, and using primitive types for some values and wrapper types for others communicates that there's a difference - theres nothing inconsistent about it.
I'd also prefer solution 2, which is what we generally use as well.
Just a note though: your getters/setters should reflect that, i.e. they should look like this (which might actually be the case in your code but not in your post):
public void setOptionalVal(Integer val) {
optionalVal = val;
}
public Integer optionalVal() {
return optionalVal;
}
Since you already have null as the indicator whether the optional value is set or not, I'd not introduce another value (-1 in your case). If you need a default value that's most likely dependent on the user of that object.