A simple RPN Calculator app

The app we are going to implement is a simplified version of an RPN Calculator. The UI will have an upper section, which will show the four upper values in the stack in reversed order, and a lower part with the numbers 0 to 9, the four basic operations, and an Enter key, which will put the value in the stack.

When we create the app using the wizard in Xcode, we must remember to check the two boxes to add Unit and UI tests.

The view in the storyboard mimics a simple calculator with the basic operations and four entries for the stack; as we mentioned earlier, the stack is upside down, with the topmost element at the bottom. The button with the e represents Enter, which will push the elements in the stack up and insert an empty value in the topmost place:

In Chapter 11, Implementing Dependency Injection, we stressed the importance of separating the UI from the business logic so that our view controller just connects the UI elements and action to a business logic object, which we model with a protocol:

class ViewController: UIViewController {
@IBOutlet var line3: UITextField!
@IBOutlet var line2: UITextField!
@IBOutlet var line1: UITextField!
@IBOutlet var line0: UITextField!
private let rpnCalculator:RpnCalculator = FloatRpnCalculator()

@IBAction func buttonDidTap(button: UIButton) {
guard let token = button.title(for: .normal) else {
return
}
rpnCalculator.new(token: token)
line0.text = rpnCalculator.line0
line1.text = rpnCalculator.line1
line2.text = rpnCalculator.line2
line3.text = rpnCalculator.line3
}
}

The code in the action takes the text from the button that has raised the action and passes it to RpnCalculator, which changes its status; then the status, represented by the first four elements in the stack, is shown in the UI.
As you can see, we use an implementation of RpnCalculator, called FloatRpnCalculator, that converts the result into a float.

Given the way ViewController calls the calculator, we already know how to define its interface:

protocol RpnCalculator {
var line3: String { get }
var line2: String { get }
var line1: String { get }
var line0: String { get }

func new(element: String)
}

Before writing the first test, we need at least to have the project compiling, and the simplest way to implement a compilable FloatRpnCalculator is as follows:

class FloatRpnCalculator: RpnCalculator {
var line3: String = ""
var line2: String = ""
var line1: String = ""
var line0: String = ""

func new(element: String) {
}
}

We already know that this isn't the code that can satisfy our requirements, but we want to be driven by the tests without planning too much how to write the production code.