HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavaMinor

Fully-working alternative to String.format(...)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
formatalternativeworkingfullystring

Problem

PLEASE NOTE:

The code below has "commented out" code; however, no code is actually commented out!! Check my GitHub link below. I did that solely to highlight the relevant code sections. Code in my MainActivity and BaseCalculatorActivity, for example, are tightly linked to Android. Those are irrelevant to the alternative String.format() approach. What is important there is the Publish code; therefore, those sections are not commented out.

Original Question

Now, we get taught that reusability is very important in university; however, when I applied what was taught before, I found out by SO users that my code was not reusable - well part of it was at least.

So my main goal here is to create a reusable part of my application. Secondary goal would be to make sure most (all important parts) are reusable.

Here is my entire project on GitHub.

Alternative

I have been working on an enhancement toString.format, String.printf (and alike function) that embodies the behavior, but reworks it into the modern age. Java's String.format() function was inspired by older languages that had printf and other similar functions. I have liked the idea behind printf-like functions for a while, but I hate having to always look at the JavaDoc and other documentation for the format flags. I have never been able to create a complex (keyword) String.format() expression on the first go, and I bet most other people cannot either. They try one thing; It fails, they consult the documentation and retry - it fails. It is stressful, does not follow OOP design and is hard to maintain.

So I have been working on a solution that is more readable and encapsulates the behavior into a separate single entity.

Everything has pros and cons. This is no different. Yes, it is more verbose than printf-like flags; however, it can be incredibly readable and possibly self-documenting if you try. There is very little boiler-plate code, and it follows many of the object-oriented principles.

Let'

Solution

OperationClick

About half of the code in this class is commented out. Why? It looks a bit like you did it one way first, and then decided to do it another way. But some of the disabled code is required by the non-disabled code. This is quite confusing.
ExpressionState

This is basically only boilerplate code, a wrapper for a mathematical expression. (The boilerplate part here is not necessarily your fault, Java is a very verbose language)
MainActivity

Again with the disabled code. This makes things very confusing for me as a reviewer.

Here you are creating a Publish object just to make it available for the garbage collector afterwards:

new Publish(result).as(Expression.class)


Consider a static method something like this:

Publish.publishResult(result, Expression.class)


The old method that you don't like:

this.txtResult.setText(String.format("%s %s %s = %s", result.getFirstNumber(), result.getOperator(), result.getSecondNumber(), result.getTotal()))


Can easily be replaced by result.getFormattedString("%s %s %s = %s"); or simply result.getString();
Display inner class

// Inner class is needed for Java 7. Java 8 might be cleaner with possibly no Inner class?? but Android does not support it!!


First of all, Android supports some Java 8 features if you're using a gradle plugin. (Don't know if it would support this)

Secondly, did it ever occur to you that perhaps the method you are trying to place here does not belong here at all? The Display class can just as well be placed as it's own class in it's own file. No need to be an inner class inside this interface at all.
Static variable

protected static ExpressionState state;


DING DING DING - threat static variable has been detected. This static variable is a big no-no. When you are accessing this variable you are breaking the Tell, don't ask principle. You should pass methods the information they need to do their job, they should not access static variables outside their scope to grab information.

As there can only be one version of a static variable, this value can never have two separate values, limiting you to only one available ExpressionState at a time (and don't even think about making a static Map to solve that!!)

This static variable is the biggest problem in your current code.
Expression enum

provides a more modern and readable approach that is more maintainable because it does not rely on a cryptic or error-prone syntax of formatting. In fact, you could use almost any form of formatting that you are used to.

Overall, I disagree. This approach is actually very limiting as I can not create a new enum at runtime. What if I wanted to create a dynamic format? I might want to let the user specify how he or she wants to see the output. They can't create an enum at runtime. All possible formats must be specified at compile-time.

Modern? Sure, enums are nice. But enums should not be used for this.

Readable? Sure, it is quite readable.

Maintainable? No. Disagree. Sure, it's easy to create a new enum if I want a new format, but it is quite a lot of boilerplate code needed.

I have liked the idea behind printf-like functions for a while, but I hate having to always look at the JavaDoc and other documentation for the format flags

Once you have used some of the format flags enough, you will remember them. %s, %d and %f is the most common ones you need to know. Specifying number of digits and stuff are a bit more advanced, but after a while you'll learn that %.3f gives you a float formatted to 3 decimals.

There is very little boiler-plate code, and it follows many of the object-oriented principles.

There is actually quite a lot of boilerplate code involved here.
Other alternatives

I was considering suggesting making a StringPatternBuilder / StringPattern class to programmatically specify a string pattern. However, in the end I don't think it can beat the String.format method.

I'm sad to say it, but I don't find your code either re-usable or useful enough to be an alternative to String.format.

Code Snippets

new Publish(result).as(Expression.class)
Publish.publishResult(result, Expression.class)
this.txtResult.setText(String.format("%s %s %s = %s", result.getFirstNumber(), result.getOperator(), result.getSecondNumber(), result.getTotal()))
// Inner class is needed for Java 7. Java 8 might be cleaner with possibly no Inner class?? but Android does not support it!!
protected static ExpressionState state;

Context

StackExchange Code Review Q#62443, answer score: 7

Revisions (0)

No revisions yet.