How to deal with history-sensitivity? - java

So I have written a Java program that has a function handInExam() that may not be called twice in a row, thus the program is history-sensitive. The problem that then occurs is that I need a variable canHandInExam to check whether this method has already been called and update this variable in each method, which leads to very poor maintainability. Below is a code snippet to show the problem.
public class NotAllowedException extends Exception {
public NotAllowedException(String message) {
super(message);
}
}
import java.util.Scanner;
public class Exam {
String[] exam;
String[] answers;
boolean canHandInExam;
public Exam(String[] questions) {
exam = questions;
answers = new String[exam.length];
canHandInExam = false;
}
// This method may only be called once in a row
public void handInExam throws NotAllowedException() {
if (canHandInExam) {
// Send exam to teacher
canHandInExam = false;
} else {
throw new NotAllowedException("You may not hand in this exam!");
}
}
public void otherMethod() {
// Do something
canHandInExam = true;
}
}
In this small example it is feasible to slightly adapt each method, however if you would have lots of methods you would need to adapt all of them. Since after all these methods you may again call handInExam() thus the variable canHandInExam would need to be set to true.
Is there a way to solve this problem in a way that is more maintainable? I am open to other possible programming languages that are not OO, but at this point I am unsure of what would be suitable.
I have considered using functional programming (e.g. Haskell) as those languages are not history-sensitive, however I did not know how to limit that you may only call a function once in a row. I tried searching for how to limit a function call to n times in a row both in Java and Haskell, but this ended up with only references to how to call a function n times.

If you speak about handing in an exam, than this doesn't mean that something is done with that exam, but that there is some entity to which the exam is given. So instead of storing within the exam whether it was handed in or can be handed in, something like this would be more appropriate:
//or whatever you call this
public interface Institution {
void handInExam(Exam exam) throws DuplicateExamException;
boolean isHandedIn(Exam exam);
}
Implementations of Institution store the exams that were handed in (possibly using a Set).

Related

Checking "rules" in Java without lots of if statements

I'm creating a springboot banking API and in order to create a transaction a bunch of "rules" have to be checked.
e.g:
Current logged in user can't withdraw money from another user's savings account
Amount can't be higher/lower than certain number
etc.
This causes my createTransaction method to contain a lot of if statements (12!). This is what my code looks like in pseudo:
public ResponseEntity<String> createTransaction(Transaction body) {
if (check rule 1) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("...");
}
if (check rule 2) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("...");
}
// etc...
// Transaction complies to set rules
return ResponseEntity.status(HttpStatus.CREATED).body("Transaction successful!");
}
I can post my actual code if necessary but I think this paints the picture without having anyone to read 100 lines of code.
Because I have around 12 if statements checking these rules, my function is quite lengthy and difficult to read/maintain.
Googling for a solution didn't bring up results I was looking for. I've tried implementing exceptions but this didn't remove the amount of if statements. Maybe a switch could improve a bit, but I'm wondering if there's a clean OOP solution.
My question is: How can I clean this code up (OOP style)?
Thanks in advance.
You should create a TransactionRule interface that allows you to implement specific transaction rules, and then use a stream to get the final result:
public interface TransactionRule {
public boolean isAllowed(Transaction someTransaction);
}
Example implementation 1:
public class SufficientBudgetTransactionRule implements TransactionRule {
public boolean isAllowed(Transaction someTransaction) {
// Custom logic e.g.
return someTransaction.wallet.value >= someTransaction.transaction.value;
}
}
Example implementation 2:
public class NotInFutureTransactionRule implements TransactionRule {
public boolean isAllowed(Transaction someTransaction) {
// Custom logic e.g.
return someTransaction.transaction.datetime.isBefore(OffsetDateTime.now());
}
}
Then, you can store all the TransactionRules in a List and check whether they all validate like so:
private final List<TransactionRule> transactionRules; // Fill these of course
public boolean allTransactionRulesMatch(Transaction someTransaction) {
return transactionRules.stream()
.map(transactionRule -> transactionRule.isAllowed(someTransaction))
.allMatch(result => result);
}

Java: Encapsulating if-return statement in a method call for cleaner, more concise code?

I'm learning Java as well as studying books on code design.
I am wondering, is it possible in Java to have an if statement encapsulated in a method call that allows one to somehow exit the parent method if the boolean is false?
What I'm wondering is that if if I can further distill the following code
public void addStock (String stock) {
boolean stockNameIsValid = testStringForValidStockName(stock);
if (stockNameIsValid == false){
JOptionPane.showMessageDialog(getParent(), "Invalid text entered. Stock ticker names may only include upper-case alphabetical letters.", "Invalid Text Entry Error", JOptionPane.ERROR_MESSAGE);
return;
}
boolean stockAlreadyExistsInPanel = testForStockExistenceInListingPanel(stock);
if(stockAlreadyExistsInPanel == true){
JOptionPane.showMessageDialog(getParent(), "The same stock cannot be entered twice into the list of stocks being watched.", "Redundant Stock Error", JOptionPane.ERROR_MESSAGE);
return;
}
controller.addStockToDb(stock);
}
into something like
public void addStock(String stock){
giveErrorAndReturnIfStockNameInvalid(stock);
giveErrorAndReturnIfStockCannotBeFound(stock);
controller.addStockToDb(stock);
}
I'm wondering if doing this is possible because my IDE can't extract the code above any further, and having my code shaped in the second way above I think would communicate intent better and have a higher level of abstraction than the initial example.
I have this idea because I'm currently reading Uncle Bob's "Clean Code" book, and inside it says that methods ultimately should be as short as you can make them. If I encapsulate lower-level logic within method calls then it leaves the code reflecting higher-level logic. This makes the code easier to understand because it requires less of the developer's mental resources to get a general concept of what each part of the code does.
My goal here is to eliminate the reader from actually having to analyze the implementations details of the code here unless it's absolutely necessary. So instead of having to read through an entire method to comprehend it, the reader can instead get a more abstract representation of the logic of my code.
We have to use Exceptions, below pseudo code explains the same:
public void addStock(String stock){
try {
isStockNameValid(stock);
isStockExists(stock);
controller.addStockToDb(stock);
} catch(IllegalArgumentException exe) {
}
}
public boolean isStockNameValid(stock) throws IllegalArgumentException {
//check stock name is valid, if not
throw new IllegalArgumentException("Stock Name already exists");
}
public boolean isStockExists(stock) throws IllegalArgumentException {
//check stock exists, if not
throw new IllegalArgumentException("Stock Name already exists");
}
If parameter to addStock method is illegal, the methods could throw an illegal argument exception, for example:
public void giveErrorAndReturnIfStockNameInvalid(String stock)
{
// TODO: Check stock name
if(stock...)
{
throw new IllegalArgumentException("Stock has no valid name:"+stock);
}
}
notice this (IllegalArgumentException) is an unchecked exception, so you could get runtime exceptions uncaught if not handled in the calling method, another option could be to create a new domain specific exception like "InvalidStockException" and make it checked, so anyone using this method will be forced to add a try-catch block just in case something goes wrong and show the error message.

Java ChargeAccount program array

I am new to java. Working in the book titled starting out with java from control structure through objects.
My assignment is as followed: create a class method that accepts a charge account number as its argument. The method should determine whether the number is valid by comparing it to the following list of valid charge account numbers:
5658845, 4520125, 7895122, 8777541, 8451277, 1302850, 8080152,
4562555, 5552012, 5050552, 7825877, 1250255, 1005231, 6545231,
3852085, 7576651, 7881200, 4581002\
These numbers should be stored in an array or an ArrayList object. Use a sequential search to locate the number passed as an argument. if the number is in the array, the method should return true, indicating the number is valid. if the number is not in the array, the method should return false, indicating the number is invalid.
My question goes along, is the program I have enough, or do I have to create a separate class?
the problem i'm having is this chapter seems different from the previous. we just got done with chapter 6 which was classes and that required me to make a main project and a constructor. my question is, are arrays just one program? or am i missing something. the program seems to run okay. if you could clear this up for me that would be awesome.
My question is: in chapter 6, I had to create two programs. One the main and second the class for example. One was the constructor, the other was the main in which it spoke to the constructor.
Do arrays require two programs or is the program I wrote sufficient enough?
the program code is
import java.util.Scanner;
public class ChargeAccount {
static int[] validChargeAccountNumbers = {
5658845, 4520125, 7895122, 8777541, 8451277, 1302850, 8080152,
4562555, 5552012, 5050552, 7825877, 1250255, 1005231, 6545231,
3852085, 7576651, 7881200, 4581002
};
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// ask the user for an account number
System.out.print("Enter the account number: ");
// get the number from the user
int number = in.nextInt();
// check to see if the number is valid
if (ChargeAccount.isValid(number) == true)
{
System.out.println("Fraud account detected.");
} else
{
System.out.println("That number is invalid.");
}
}
public static boolean isValid(int number) {
for (int i = 0; i < validChargeAccountNumbers.length; i++) {
//checks if the numbers were in the list
if (validChargeAccountNumbers[i] == number) {
return true;
}
}
return false;
}
}
I apologize if any formatting is wrong. please ask me any questions.
As he said it is nothing to with learning Object Oriented Programming.
It is all about our how effectively we designed the code.
The above answer is perfectly fine, place the business logic code in one class ChargerAccount.java
And Create the rest of the code in another class to test the logic.
So it seems like this has to do with learning Object Oriented Programming.
In this case, you would have one file, ChargeAccount.java, which would contain that code, and maybe ChargeAccountTest.java, which would contain the rest of the code.
In OOP, constructors instantiate objects, like you did with the Scanner object, calling new Scanner() called the Scanner constructor. Research how to create constructors and how to call them in other classes.
public static void main(String[] args)
{
ChargeAccount account = new ChargeAccount();
//rest of code
}

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.

How to remove large if-else-if chain [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Long list of if statements in Java
I was tasked to work with some code, and there is a giant if-else-if chain (100+ else-ifs) that checks Strings.
What are some good techniques to update this code as to where the if-else-if chain can be shrunken down to something much more manageable.
The chain looks something like this:
if(name.equals("abc")){
do something
} else if(name.equals("xyz")){
do something different
} else if(name.equals("mno")){
do something different
} ......
.....
else{
error
}
You can extract the code in each branch to a separate method, then turn the methods into implementations of a common base interface (let's call it Handler). After that, you can fill a Map<String, Handler> and just look up and execute the right handler for given string.
Unfortunately the implementation of 100+ subclasses for the interface requires quite a lot of boilerplate code, but currently there is no simpler way in Java to achieve this. Implementing the cases as elements of an Enum may help somewhat - here is an example. The ideal solution would be using closures / lambdas, but alas we have to wait till Java 8 for that...
Some options / ideas:
Leave it as it is - it's not fundamentally broken, and is reasonably clear and simple to maintain
Use a switch statement (if you are using Java 7) - not sure if this gains you much though
Create a HashMap of String to FunctionObjects where the function objects implement the required behaviour as a method. Then your calling code is just: hashMap.get(name).doSomething();
Break it into a heirarchy of function calls by sub-grouping the strings. You could do this by taking each letter in turn, so one branch handles all the names starting with 'a' etc.
Refactor so that you don't pass the name as a String but instead pass a named object. Then you can just do namedObject.doSomething()
With Enums, you can have a method per instance.
public enum ActionEnum {
ABC {
#Override
void doSomething() {
System.out.println("Doing something for ABC");
}
},
XYZ {
#Override
void doSomething() {
System.out.println("Doing something for XYZ");
}
};
abstract void doSomething();
}
public class MyActionClass {
public void myMethod(String name) {
ActionEnum.valueOf("ABC").doSomething();
}
}
It is still kinda messy (big enum with 100+ entries, even it all it does is dispatching), but may avoid the HashMap initialization code (100+ puts is also messy in my opinion).
And yet another option (for documentation purposes) would be reflection:
public interface Action {
void doSomething();
}
public class ABCAction implements Action {
#Override
public void doSomething() {
System.out.println("Doing something for ABC");
}
}
public class MyActionClass {
void doSomethingWithReflection(String name) {
try {
Class<? extends Action> actionClass = Class.
forName("actpck."+ name + "Action").asSubclass(Action.class);
Action a = actionClass.newInstance();
a.doSomething();
} catch (Exception e) {
// TODO Catch exceptions individually and do something useful.
e.printStackTrace();
}
}
}
Each approach has it's trade offs:
HashMap = Fast + Kinda messy ("set-up" code with hundred of puts)
Enum = Fast + Kinda messy 2 (huge file).
Reflection = Slower + runtime error prone, but provides clean separation without resorting to clunky big HashMap.
Like Matt Ball said in his comment, you can use a command pattern. Define a collection of Runnable classes:
Runnable task1 = new Runnable() {
public void run() { /* do something */ }
};
Runnable task2 = // etc.
Then you can use a map from your keys to runnables:
Map<String,Runnable> taskMap = new HashMap<String,Runnable>();
taskMap.put("abc", task1);
taskMap.put("xyz", task2);
// etc.
Finally, replace the if-else chain with:
Runnable task = taskMap.get(name);
if (task != null) {
task.run();
} else {
// default else action from your original chain
}
you can use the switch statement , but Switch statements with String cases have been implemented in Java SE 7
the best solution is to use the command pattern
This is a popular Arrow Anti-Pattern and Jeff discusses some approaches to handle this very nicely in his post here.

Categories

Resources