Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a result with several values the Java way [duplicate]

Tags:

java

I am used to developing in Python, but for work reasons have to do it in Java. I am facing a task that would be trivial in Python, and I'd like some advice on how to handle this in Java the proper way.

I need to parse a duration string. It can be in milliseconds (235ms) or seconds (32s). And it can also be "< 1ms" as a special case.

The parsing happens at least three times in the code so I'd like to separate it into a method. But my code does need to know, not just the resulting value in ms, but also whether it was in ms or s and whether it was <1ms (0 is a different value).

In Python I would just return a tuple:

return (value_in_milliseconds,is_in_seconds,is_under_1ms) 

In C I would define a struct of these three values and return it. In Pascal I'd define a record.

In Java I can't return a tuple and I can't define a record so what do I do?

The only thing I can think of is creating a class representing a duration value. The constructor would take the string and parse it. The class would have fields: int milliseconds, boolean inSeconds, boolean under 1ms .

But this sounds terribly heavyweight - is there a better solution?

like image 800
Mikhail Ramendik Avatar asked Apr 25 '17 19:04

Mikhail Ramendik


People also ask

Can Java method return multiple values?

You can return only one value in Java. If needed you can return multiple values using array or an object.

How can a method return more than one value?

We can return more than one values from a function by using the method called “call by address”, or “call by reference”. In the invoker function, we will use two variables to store the results, and the function will take pointer type data. So we have to pass the address of the data.


2 Answers

Don't pass around a set of flags that must be consistent between them to make a sensible state. What if is_in_seconds and is_under_1ms are both true? And why would a variable that contains the word milliseconds ever be interpreted as seconds? How wrong-looking that will be in the code. Wrong-looking code is not good if you can do anything about it--we're supposed to write code whose appearance of rightness/wrongness matches reality—the Principle of Least Astonishment applied to code, and perhaps even the Pit of Success for subsequent developers whose brains will explode on that.

This sounds like maybe a bit of the Primitive Obsession code smell/antipattern, perhaps from your Python background? (I know next to nothing about Python so feel free to disregard this guess.)

Solution: make a real domain-level object that represents the idea of an approximate duration.

One possible implementation of that:

  1. Create a DurationScale enum that has members Second, Millisecond, SubMillisecond.

  2. Create a class ApproximateDuration, that takes a duration integer and a durationScale enum value.

  3. Now consume this object in your other code. If you need to sum a series of these durations, make a class that knows how to interpret each one and add them together. Or add methods to this class.

An alternative to some concept like DurationScale could be MarginOfError which can be expressed in some arbitrary number of milliseconds, itself. This could allow you to use a strict mathematical formula to increase the margin of error appropriately as you sum different ApproximateDuration objects together into a new ApproximateDuration object.

Note: You can see some further discussion on why I recommend this approach.

The implementation you settled on is also a good way to handle it, where you explicitly state the lower and upper bounds:

public final class ApproximateDuration {    private final int lowMilliseconds;    private final int highMilliseconds;     public ApproximateDuration(int lowMilliseconds, int highMilliseconds) {       this.lowMilliseconds = lowMilliseconds;       this.highMilliseconds = highMilliseconds;    }     public int getLowMilliseconds() {       return lowMilliseconds;    }     public int getHighMilliseconds() {       return highMilliseconds;    } } 

Note that putting the word Milliseconds in the variables and property names is important, as is the immutability of this class.

like image 60
ErikE Avatar answered Sep 30 '22 13:09

ErikE


It's no different than a C struct but you'll somehow at the least end up inheriting from Object

class Blah {    public String value_in_milliseconds;    public String is_in_seconds;    public String is_under_1ms; } 
like image 40
jiveturkey Avatar answered Sep 30 '22 12:09

jiveturkey