Codea Calculator -- in "Agile" style

I wrote a simple calculator object, not unlike dave’s, but I did it with tests, simple incremental design, refactoring – all that “Agile” stuff. And I wrote an article about it.

The program is small, and I think rather nice. The article contains almost everything I thought as I wrote the program, so it is long. Quite long.

Here’s a link, if I know how to paste a link. Comments welcome here or by email. Good luck.

http://xprogramming.com/articles/codea-calculator/

I’m delighted you did that, Ron, because I’ve been wondering how an Agile programmer like yourself would approach our kind of projects. And providing all that detail really gives a feel for the whole process.

I was surprised that you didn’t include more obvious tests to start with, to avoid programming dead ends, but I’m guessing that while you might do this in a bigger project, even then, your initial tests would still only be a fraction of the ultimate test suite. So I can see how you keep developing the test suite as you go.

I’m wondering how you would run tests in a visual program like Codea, where, for example, my key test is whether I see a dungeon wall when the program loads, and whether I can move about correctly. When you’re working in 3D, I’m not sure how to run automated tests, other than on sub systems which return numeric or string values. It’s difficult to tell Codea to run something and check that the picture looks correct!

I did something today which feels quite a lot like your refactoring. I had coded my player character as part of the general code initially (because you never see him, and basically he is just the camera), and that was working, but felt messy. So I took all that code into a class, which took a couple of hours to straighten out. I was thinking I should have done it that way to start with, but your approach seems to suggest that it is OK to start coding simply, as I did, and add more structure as you need it, even if it means reworking. I need to think about that.

(Incidentally, when it comes to swapping information from my PC to the iPad, I keep Notepad open with a file saved to a Dropbox folder, which I also have open in my iPad’s Dropbox app, which I simply then refresh). It is a nuisance not having a direct link between them.

Thanks for a great post. I hope you do more.

An additional thought. It is possible to write a very short calculator indeed by simply appending all the keystrokes, including operators, and passing the string to the loadstring function which can execute it as Lua code and return the result. Then the calculator could handle exponents, brackets and any functions such as sin and cos, with minimal additional code (eg to rename math.cos as cos).

This example code takes input via a text parameter and prints the answer when the button parameter is pressed. The answer should be correct as long as Lua’s arithmetic syntax is followed.

parameter.text("Input")
parameter.action("Calculate",function() print(loadstring("return "..Input)()) end)

It is a bit of a cheat, though!

@RonJeffries thanks for the article. I haven’t read it yet (just back from work, and tired) but it looks great! I am eager to be fresh enough to read it. Maybe tomorrow.

ignatz, I would almost always write application-focused tests such as i started with here. I would not generally write tests for some object that i think i’m gonna need.

tell me what kind of tests you were thinking i might do … i’ll talk about whether i would, or not, and why.

and sure, we can do load string … but that’s no fun :slight_smile: well, a different kind of fun.

as for refactoring, as you probably found, the longer we wait, the harder is gets to do. more places to change, and things are more tangled together. so one of the things we learn to do is to spot objects “trying to happen” as soon as we can.

we think of this as the design “emerging” and the code “telling us things”, but of course what’s really happening is that we are creating the design in an evolutionary way, and observing what the code looks like.

or maybe it’s alive, that’s always possible :slight_smile:

Hello @RonJeffries i’ve read your Agile post. That is very interesting, thanks.
Just to let you know, I found a typo:

Let’s look at doPanding()

I have questions:

1/ Codea is for interactive programs with touch() actions from the GUI. How would you set up tests for the GUI? I mean testing that good GUI elements are correctly responding? The way i do it is visual/manual but i would prefer to write automatic tests as you show.

@Jmv38 - I asked the same question, lol

Practically, I don’t think you can write tests for visual results, but perhaps what you can do is write tests for the sub systems that produce numeric or text output.

2/ my preference for refactoring would have been:

function Calculator.mult(d,t) return d*t end
function Calculator.divide(d,t) return t/d end
function Calculator.minus(d,t) return t-d end
function Calculator.add(d,t) return d+t end

function Calculator:press(key)
    if key == "*" then
        self:doPending(self.mult)
    elseif key == "/" then
        self:doPending(self.divide)
    elseif key == "-" then
        self:doPending(self.minus)
    elseif key == "+" then
        self:doPending(self.add)
    elseif key == "=" then
        self:doPending(nil)
    else
        if self.first then
            self.temp = self.display
            self.display = ""
            self.first = false
        end
        self.display = self.display..key
    end
end

I made 2 errors while writing thing this. Thanks to your tests i corrected them in seconds.
What is your comment on my refactoring above? ‘not needed, so dont do that’?

@ignatz sorry, i didnt read you post. I wanted to write down my questions before i forget them. I’ll read you post. Thanks.

3/ i actually prefer this refactoring, because it maked the code clearer to me:

local operations = {}
operations["*"] = function(d,t) return d*t end
operations["/"] = function(d,t) return t/d end
operations["-"] = function(d,t) return t-d end
operations["+"] = function(d,t) return d+t end

function Calculator:press(key)
    local f = operations[key]
    if f then
        self:doPending(f)
    elseif key == "=" then
        self:doPending(nil)
    else
        if self.first then
            self.temp = self.display
            self.display = ""
            self.first = false
        end
        self.display = self.display..key
    end
end

Again, i am very interested in your comments (and especially i you think i am wrong!)

@Jmv38 - I just thought it was funny we both thought of the same thing! :wink:

@Ignatz Ron didnt develop and test the user interface of his calculator in his post. I was surprised of that, because there is no real calculator app in the end, while it was in his initial drawing on top of his post. I wish he would bring the task to 100% completion, so we can benefit from his huge experience.
Maybe the reason for not finishing was the Codea GUI toolbox is so empty (we have to re-code buttons and decent textbox from scratch all the time).

@Jmv38 - I think you’re right. Writing a GUI would have been a waste of his time.

I like your suggested alternative above, because it allows changes (eg addition of more functions) without messing with the press function or making it any larger. (But what do I know?).

@ignatz i dont think it would be a waste of his time: he is doing teaching here, and teaching us how to do develop a GUI with codea is not a waste of time, it is actually very important. And if he wants to benefit of all the pleasure codea can bring him, he will have to learn the GUI stuff for himself anyway.
I guess we just have to be patient and wait for his sequel… He is probably already writing it right now! :wink:

@Jmv38 - personally, I think time spent on a UI is a waste of (my) time, because if I want a conventional UI app, I can use pythonista, Excel or whatever.

The beauty of Codea is the graphics. Spending a lot of time on UI is like trying to program a game in Excel. You can maybe do it, but why? Why not use the best tool for the job?

That’s just my view, I know some people will disagree and that’s fine. Vive la difference!

wrt the calculator, you can set up a very simple UI using text parameters, that will be fine for this exercise, I think.

@RonJeffries - before this post disappears off the page, I thought I’d write it up, here

@ignatz i agree with your choice of using the right tool for a given task.

But the post of Ron is (i think) about teaching us something, (he does not really need to develop this calculator, right?, he could just use excel) so developping the GUI would be just another toy project to teach us how we should proceed in the Agile. Style when we need to develop touchable elements for a Codea projet, which is mandatory for any game.

As you mentionned in your initial post, checking the 3D projection is correct is very important too for games, but it is even more challenging! I wonder if he will come up with something for that…