1

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.

SpaceTrucker
  • 13,377
  • 6
  • 60
  • 99
Sophie L.
  • 11
  • 2
  • I think you should remove the section about other languages in you last paragraph, as this tends to make your question too broad. – SpaceTrucker Nov 30 '17 at 11:46
  • If you set `canHandInExam = true` in every method other than `handInExam` then this will not work, because you can call `handInExam`, then `otherMethod`, then again `handInExam`, then again `otherMethod`, and so forth (indefinite number of times). You need to set it to `true` only once in constructor, and then set it to `false` in `handInExam`. But this will only prevent `handInExam` from executing twice, other methods can be called freely even after `handInExam` is already called. – Yoory N. Nov 30 '17 at 12:05
  • I've re-read your question, and it seems that you do want to allow `handInExam` to be called twice, but only if `otherMethod` is called in between, is that right? – Yoory N. Nov 30 '17 at 12:23
  • @YooryN. I do indeed want to allow `handInExam` to be called twice if another method is called inbetween. – Sophie L. Nov 30 '17 at 12:33
  • @SpaceTrucker I agree that the last section makes the question quite broad but the reason why I added it is because I believe that history-sensitivity might be an issue inherent to OOP. Thus while OOP might provide some work-arounds, maybe it can be solved more elegantly in other types of languages. – Sophie L. Nov 30 '17 at 12:35
  • Then I don't see much difference between sending the same Exam multiple times and sending modified version of the Exam from the same student. In both cases you need some sort of deduplication to decide which version of the said exam is final and needs to be verified. If you're trying to reuse single Exam object across multiple students, then it is a bad idea in general and sometimes leads to subtle bugs, when some fields are forgotten to update and contain unrelated data. It's better to create new Exam object per student. – Yoory N. Nov 30 '17 at 13:33
  • @YooryN. Maybe the example I have given is not the best, but my main focus is on how to deal with the history-sensitve aspect which may occur in different ways in programs. Another example could be a class that implements a protocol in which we can call the method `sendData` only after a connection has been established. – Sophie L. Nov 30 '17 at 18:08

1 Answers1

0

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).

SpaceTrucker
  • 13,377
  • 6
  • 60
  • 99
  • While I think that this is a neat design solution, I feel like this does not completely solve the problem. If we would have another method that cannot be called twice in a row, would you then make another interface? And if this does not have a clear abstraction such as `Institution` what would you then do? – Sophie L. Nov 30 '17 at 18:04