Java Design Issue: Enforce method call sequence

JavaOopDesign Patterns

Java Problem Overview


There is a question which was recently asked to me in an interview.

Problem: There is a class meant to profile the execution time of the code. The class is like:

Class StopWatch {

    long startTime;
    long stopTime;

    void start() {// set startTime}
    void stop() { // set stopTime}
    long getTime() {// return difference}

}

The client is expected to create an instance of the StopWatch and call methods accordingly. User code can mess up the use of the methods leading to unexpected results. Ex, start(), stop() and getTime() calls should be in order.

This class has to be "reconfigured" so that user can be prevented from messing up the sequence.

I proposed use of custom exception if stop() is called before start(), or doing some if/else checks, but interviewer was not satisfied.

Is there a design pattern to handle these kind of situations?

Edit: The class members and method implementations can be modified.

Java Solutions


Solution 1 - Java

First there is the fact that implementing an own Java profiler is a waste of time, since good ones are available (maybe that was the intention behind the question).

If you want to enforce the correct method order at compile time, you have to return something with each method in the chain:

  1. start() has to return a WatchStopper with the stop method.
  2. Then WatchStopper.stop() has to return a WatchResult with the getResult() method.

External Construction of those helper classes as well as other ways of accessing their methods have to be prevented of course.

Solution 2 - Java

With minor changes to the interface, you can make the method sequence the only one that can be called - even at compile time!

public class Stopwatch {
	public static RunningStopwatch createRunning() {
		return new RunningStopwatch();
	}
}

public class RunningStopwatch {
	private final long startTime;
	
	RunningStopwatch() {
		startTime = System.nanoTime();
	}
	
	public FinishedStopwatch stop() {
		return new FinishedStopwatch(startTime);
	}
}

public class FinishedStopwatch {
	private final long elapsedTime;
	
	FinishedStopwatch(long startTime) {
		elapsedTime = System.nanoTime() - startTime;
	}
	
	public long getElapsedNanos() {
		return elapsedTime;
	}
}

The usage is straightforward - every method returns a different class which only has the currently applicable methods. Basically, the state of the stopwatch is encapsuled in the type system.


In comments, it was pointed out that even with the above design, you can call stop() twice. While I consider that to be added value, it is theoretically possible to screw oneself over. Then, the only way I can think of would be something like this:

class Stopwatch {
	public static Stopwatch createRunning() {
		return new Stopwatch();
	}
	
	private final long startTime;
	
	private Stopwatch() {
		startTime = System.nanoTime();
	}
	
	public long getElapsedNanos() {
		return System.nanoTime() - startTime;
	}
}

That differs from the assignment by omitting the stop() method, but that's potentially good design, too. All would then depend on the precise requirements...

Solution 3 - Java

We commonly use StopWatch from Apache Commons StopWatch check the pattern how they've provided.

IllegalStateException is thrown when the stop watch state is wrong.

public void stop()

Stop the stopwatch.

This method ends a new timing session, allowing the time to be retrieved.

Throws:
    IllegalStateException - if the StopWatch is not running.

Straight forward.

Solution 4 - Java

Maybe he expected this 'reconfiguration' and question was not about method sequence at all:

class StopWatch {
       
   public static long runWithProfiling(Runnable action) {
      startTime = now;
      action.run();
      return now - startTime;
   }
}

Solution 5 - Java

Once given more thought

In hindsight it sounds like they were looking for the execute around pattern. They're usually used to do things like enforce closing of streams. This is also more relevant due to this line:

> Is there a design pattern to handle these kind of situations?

The idea is you give the thing that does the "executing around" some class to do somethings with. You'll probably use Runnable but it's not necessary. (Runnable makes the most sense and you'll see why soon.) In your StopWatch class add some method like this

public long measureAction(Runnable r) {
    start();
    r.run();
    stop();
    return getTime();
}

You would then call it like this

StopWatch stopWatch = new StopWatch();
Runnable r = new Runnable() {
    @Override
    public void run() {
        // Put some tasks here you want to measure.
    }
};
long time = stopWatch.measureAction(r);

This makes it fool proof. You don't have to worry about handling stop before start or people forgetting to call one and not the other, etc. The reason Runnable is nice is because

  1. Standard java class, not your own or third party
  2. End users can put whatever they need in the Runnable to be done.

(If you were using it to enforce stream closing then you could put the actions that need to be done with a database connection inside so the end user doesn't need to worry about how to open and close it and you simultaneously force them to close it properly.)

If you wanted, you could make some StopWatchWrapper instead leave StopWatch unmodified. You could also make measureAction(Runnable) not return a time and make getTime() public instead.

The Java 8 way to calling it is even simpler

StopWatch stopWatch = new StopWatch();
long time = stopWatch.measureAction(() - > {/* Measure stuff here */});

> A third (hopefully final) thought: it seems what the interviewer was looking for and what is being upvoted the most is throwing exceptions based on state (e.g., if stop() is called before start() or start() after stop()). This is a fine practice and in fact, depending on the methods in StopWatch having a visibility other than private/protected, it's probably better to have than not have. My one issue with this is that throwing exceptions alone will not enforce a method call sequence.

> For example, consider this: > > class StopWatch { > boolean started = false; > boolean stopped = false; >
> // ... >
> public void start() { > if (started) { > throw new IllegalStateException("Already started!"); > } > started = true; > // ... > } >
> public void stop() { > if (!started) { > throw new IllegalStateException("Not yet started!"); > } > if (stopped) { > throw new IllegalStateException("Already stopped!"); > } > stopped = true; > // ... > } >
> public long getTime() { > if (!started) { > throw new IllegalStateException("Not yet started!"); > } > if (!stopped) { > throw new IllegalStateException("Not yet stopped!"); > } > stopped = true; > // ... > } > } > > Just because it's throwing IllegalStateException doesn't mean that the proper sequence is enforced, it just means improper sequences are denied (and I think we can all agree exceptions are annoying, luckily this is not a checked exception). > > The only way I know to truly enforce that the methods are called correctly is to do it yourself with the execute around pattern or the other suggestions that do things like return RunningStopWatch and StoppedStopWatch that I presume have only one method, but this seems overly complex (and OP mentioned that the interface couldn't be changed, admittedly the non-wrapper suggestion I made does this though). So to the best of my knowledge there's no way to enforce the proper order without modifying the interface or adding more classes. > > I guess it really depends on what people define "enforce a method call sequence" to mean. If only the exceptions are thrown then the below compiles > > StopWatch stopWatch = new StopWatch(); > stopWatch.getTime(); > stopWatch.stop(); > stopWatch.start(); > > True it won't run, but it just seems so much simpler to hand in a Runnable and make those methods private, let the other one relax and handle the pesky details yourself. Then there's no guess work. With this class it's obvious the order, but if there were more methods or the names weren't so obvious it can begin to be a headache.


Original answer

>More hindsight edit: OP mentions in a comment, > >>"The three methods should remain intact and are only interface to the programmer. The class members and method implementation can change." > > So the below is wrong because it removes something from the interface. (Technically, you could implement it as an empty method but that seems to be like a dumb thing to do and too confusing.) I kind of like this answer if the restriction wasn't there and it does seem to be another "fool proof" way to do it so I will leave it.

To me something like this seems to be good.

class StopWatch {

    private final long startTime;

    public StopWatch() {
        startTime = ...
    }

    public long stop() {
        currentTime = ...
        return currentTime - startTime;
    }
}

The reason I believe this to be good is the recording is during object creation so it can't be forgotten or done out of order (can't call stop() method if it doesn't exist).

One flaw is probably the naming of stop(). At first I thought maybe lap() but that usually implies a restarting or some sort (or at least recording since last lap/start). Perhaps read() would be better? This mimics the action of looking at the time on a stop watch. I chose stop() to keep it similar to the original class.

The only thing I'm not 100% sure about is how to get the time. To be honest that seems to be a more minor detail. As long as both ... in the above code obtain current time the same way it should be fine.

Solution 6 - Java

I suggest something like:

interface WatchFactory {
    Watch startTimer();
}

interface Watch {
    long stopTimer();
}

It will be used like this

 Watch watch = watchFactory.startTimer();

 // Do something you want to measure

 long timeSpentInMillis = watch.stopTimer();

You can't invoke anything in wrong order. And if you invoke stopTimer twice you get meaningful result both time (maybe it is better rename it to measure and return actual time each time it invoked)

Solution 7 - Java

Throwing an exception when the methods are not called in the correct order is common. For example, Thread's start will throw an IllegalThreadStateException if called twice.

You should have probably explained better how the instance would know if the methods are called in the correct order. This can be done by introducing a state variable, and checking the state at the start of each method (and updating it when necessary).

Solution 8 - Java

This can also be done with Lambdas in Java 8. In this case you pass your function to the StopWatch class and then tell the StopWatch to execute that code.

Class StopWatch {

    long startTime;
    long stopTime;

    private void start() {// set startTime}
    private void stop() { // set stopTime}
    void execute(Runnable r){
        start();
        r.run();
        stop();
    }
    long getTime() {// return difference}
}

Solution 9 - Java

Presumably the reason for using a stopwatch is that the entity that's interested in the time is distinct from the entity that's responsible for starting and stopping the timing intervals. If that is not the case, patterns using immutable objects and allowing code to query a stop watch at any time to see how much time has elapsed to date would likely be better than those using a mutable stopwatch object.

If your purpose is to capture data about how much time is being spent doing various things, I would suggest that you might be best served by a class which builds a list of timing-related events. Such a class may provide a method to generate and add a new timing-related event, which would record a snapshot of its created time and provide a method to indicate its completion. The outer class would also provide a method to retrieve a list of all timing events registered to date.

If the code which creates a new timing event supplies a parameter indicating its purpose, code at the end which examines the list could ascertain whether all events that were initiated have been properly completed, and identify any that had not; it could also identify if any events were contained entirely within others or overlapped others but were not contained within them. Because each event would have its own independent status, failure to close one event need not interfere with any subsequent events or cause any loss or corruption of timing data related to them (as might occur if e.g. a stopwatch had been accidentally left running when it should have been stopped).

While it's certainly possible to have a mutable stopwatch class which uses start and stop methods, if the intention is that each "stop" action be associated with a particular "start" action, having the "start" action return an object which must be "stopped" will not only ensure such association, but it will allow sensible behavior to be achieved even if an action is started and abandoned.

Solution 10 - Java

I know this already has been answered but couldn't find an answer invoking builder with interfaces for the control flow so here is my solution : (Name the interfaces in a better way than me :p)

public interface StartingStopWatch {
	StoppingStopWatch start();
}

public interface StoppingStopWatch {
	ResultStopWatch stop();
}

public interface ResultStopWatch {
	long getTime();
}

public class StopWatch implements StartingStopWatch, StoppingStopWatch, ResultStopWatch {

	long startTime;
	long stopTime;

	private StopWatch() {
		//No instanciation this way
	}

	public static StoppingStopWatch createAndStart() {
		return new StopWatch().start();
	}

	public static StartingStopWatch create() {
		return new StopWatch();
	}

	@Override
	public StoppingStopWatch start() {
		startTime = System.currentTimeMillis();
		return this;
	}

	@Override
	public ResultStopWatch stop() {
		stopTime = System.currentTimeMillis();
		return this;
	}

	@Override
	public long getTime() {
		return stopTime - startTime;
	}

}

Usage :

StoppingStopWatch sw = StopWatch.createAndStart();
//Do stuff
long time = sw.stop().getTime();

Solution 11 - Java

As Per Interview question ,It seems to like this

Class StopWatch {

    long startTime;
    long stopTime;
	public StopWatch() {
   	start();
  	}

    void start() {// set startTime}
    void stop() { // set stopTime}
    long getTime() {
stop();
// return difference

}

}

So now All user need to create object of StopWatch class at beginning and getTime() need to call at End

For e.g

StopWatch stopWatch=new StopWatch();
//do Some stuff
 stopWatch.getTime()

Solution 12 - Java

I'm going to suggest that enforcing the method call sequence is solving the wrong problem; the real problem is a unfriendly interface where the user must be aware of the state of the stopwatch. The solution is to remove any requirement to know the state of the StopWatch.

public class StopWatch {

	private Logger log = Logger.getLogger(StopWatch.class);
	
	private boolean firstMark = true;
	private long lastMarkTime;
	private long thisMarkTime;
	private String lastMarkMsg;
	private String thisMarkMsg;
	
	public TimingResult mark(String msg) {
		lastMarkTime = thisMarkTime;
		thisMarkTime = System.currentTimeMillis();
		
		lastMarkMsg = thisMarkMsg;
		thisMarkMsg = msg;
		
		String timingMsg;
		long elapsed;
		if (firstMark) {
			elapsed = 0;
			timingMsg = "First mark: [" + thisMarkMsg + "] at time " + thisMarkTime;
		} else {
			elapsed = thisMarkTime - lastMarkTime;
			timingMsg = "Mark: [" + thisMarkMsg + "] " + elapsed + "ms since mark [" + lastMarkMsg + "]";
		}
		
		TimingResult result = new TimingResult(timingMsg, elapsed);
		log.debug(result.msg);
		firstMark = false;
		return result;
	}

}

This allows a simple use of the mark method with a result returned and logging included.

StopWatch stopWatch = new StopWatch();

TimingResult r;
r = stopWatch.mark("before loop 1");
System.out.println(r);

for (int i=0; i<100; i++) {
	slowThing();
}

r = stopWatch.mark("after loop 1");
System.out.println(r);

for (int i=0; i<100; i++) {
	reallySlowThing();
}

r = stopWatch.mark("after loop 2");
System.out.println(r);

This gives the nice result of;

> First mark: [before loop 1] at time 1436537674704
> Mark: [after loop 1] 1037ms since mark [before loop 1]
> Mark: [after loop 2] 2008ms since mark [after loop 1]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMohittView Question on Stackoverflow
Solution 1 - JavaWaogView Answer on Stackoverflow
Solution 2 - JavaPetr JanečekView Answer on Stackoverflow
Solution 3 - Javavels4jView Answer on Stackoverflow
Solution 4 - JavaAdamSkywalkerView Answer on Stackoverflow
Solution 5 - JavaCaptain ManView Answer on Stackoverflow
Solution 6 - JavatalexView Answer on Stackoverflow
Solution 7 - JavaEranView Answer on Stackoverflow
Solution 8 - JavaDavid says Reinstate MonicaView Answer on Stackoverflow
Solution 9 - JavasupercatView Answer on Stackoverflow
Solution 10 - JavaNeeLView Answer on Stackoverflow
Solution 11 - JavaAbhishek MishraView Answer on Stackoverflow
Solution 12 - JavaQwerkyView Answer on Stackoverflow