Codea Calculator -- in "Agile" style

Yeah, didn’t mean to aside it… just finished the article on the way home. It’s a good layout and example of TDD. Something I’ve always encouraged others to do, but never had quite the self discipline for myself. Although my minds always worked that way (aside from not writing automated tests). I’ve always coded on a write a tiny bit, run and test kind of model, just with the testing being manual. Which is all fine for solo self projects, but TDD for big stuff and especially teams can make a big difference.

Also to @Ignatz TDD is great and very good for the backend, it often starts getting a bit hinky when you hit the UI, in the web world you can start building some BDD/ATDD type testing with tools like Selenium, but it often starts getting a bit tightly bound to the specific elements of the UI, not the broader functionality you want to test.

Some answers for Codeslinger. Getting pretty far from Codea, so if the mods want this thread closed, I’m OK with it.

  1. Starting at 0 instead of space. One starts where one starts. My calculator starts at blank. Will make no difference to the style of development I’m describing.

  2. You’d start simpler. OK by me: one starts where one starts.

  3. You might have started with digits. I started with two digits, which was enough to give me most of the learning that was there to be had. I might have gotten in trouble by not doing more digits. As it happens, I didn’t.

I like when that happens, because it gives me a chance to show what you do when you can’t get a test to run, or when a bug shows up. Didn’t happen. That’s nice.

  1. First takes no inputs, then takes all inputs. Isn’t that bad? I don’t see why. There is no rule in TDD on what you test first, or how big a bite you take. The rules are to write a test, write only code to make it pass, and consider refactoring when the test goes green.

Even if I broke those rules – and I don’t think I did – my purpose was to show how I program and how I think and what I do. Seems to me that went just fine.

  1. Same question rephrased. Asked and answered.

  2. How do you know you’ve written enough tests? What can I say beyond experience. If you never get done, you’re writing too many. If bugs are found downstream, you’ve written too few. The idea is to build up skill and judgment.

  3. I don’t think I suddenly pulled tests that were lying around and shouted surprise, so, again, I’m not sure what you’re at here. As for BDD vs TDD. as one of the original users of Detroit School TDD, I pretty much follow that style. There are lots of other ways to write tests and code.

  4. Why is self.temp never initialized? It didn’t need it. If a test had shown that it needed it, we’d have done it.

  5. Why not limit the digits part to digits right now? Because we can’t do everything right now. I’d do it when it seemed to be the next most important thing to do.I’m trying to maximize my learning. I know how to limit the calculator as to digits, so it’s not very interesting to me.

10 How do we know what the calculator can do for sure? 0. We never know what a program does “for sure”. To get close: 1. Be there: I know what it does. 2: Read the tests: they say what it is guaranteed to do. 3: Read the code. 4: Improve tests and code if they need it.

  1. As i mentioned earlier, the results may look like chance but in fact every test and every line is what I intended. Another programmer might have intended and done other things. I would enjoy reading such an article from some other programmer.

  2. “Give your very best.” I look forward to your article on this subject.

hi Ron.
Thanks for your answers, debates are always very informative.
I you get the discussion closed, please dont forget about the UI post!

A question about your process: you say the program structure ‘emerges from the test’. When i program, i start small with testing each line and the program grow smoothly. A structure emerges. But when i continue to add features, at some point, the struture that emerged when the program was small is no longer fitted to the one that emerges with the bigger one… So i have to rewrite everything, and that is very hard.
I feel that the TDD will not change anything to that, or make it even worse maybe? it will certainly make the redesing process safer, because the tests are there. But not anticipating the final state of the bigger program, using the relevant design patterns, could be less nefficient?
what do you think?
Thanks.

Hi Jmv38,

The TDD cycle is red/green/refactor. The “redesign” phase comes every few minutes, as we look at the code we’ve just made work and see how to revise it.

In this example, much of the revision came a little ways in (remember this is only 40 lines of code and about 25 of test so far) where we got the idea of pulling out the operations into a separate function table. Happens we got that idea from dave, but we could have had it from our pair partner, our own brain, wherever. What we saw in the code was the repetitive character of the code for each operator key. We had that code that looked like this:

  if key == "*" then
      self.op = function(d,t) return d*t end
      self.first = true
  elseif key == "/" then
      self.op = function(d,t) return t/d end
      self.first = true

And we were troubled by the duplication. So we extract it into some structure, extract again, and finally wind up with the individual arithmetic operations in a table and everything else in a doPending() function that does all the common bits.

What’s happening here is that we’re identifying ideas (abstractions, if you like the word) and building code to represent them. We create generality, just a bit at a time, as we need it.

Turns out that the more we do in this mode, bit by bit, the closer the program stays to a good structure. We don’t always manage that, though, and sometimes things get a bit out of hand – and we want to rewrite.

Rewriting is always very hard, as you say. In my experience, in business it is rarely really the right thing to do. The reasons include that it takes a long time before the people paying see progress, and generally whatever made us do it poorly last time is still there, so we wind up with another ball of worms.

It’s better (though sometimes less fun) to refactor the program from not so good to better, and that can always (always) be done incrementally. That way, we get better code and more features together. This keeps the money people happier.

An article about that is here: http://xprogramming.com/articles/refactoring-not-on-the-backlog/

However, especially when we are programming for fun, there is great value to writing things in different ways. I still find that rewriting the whole program is a pain, so I try not to do it. But rewriting bits in different ways, we can learn a lot about our design, and about the language.

TDD is not about not designing … it is about designing all the time, and improving the design all the time. If we improve the design all the time, it stays alive longer. And if we engage our code in the design process, we tend to get cleaner and simpler designs.

YMMV, of course. I’m not here to tell anyone what they should do. I’m here showing you what I do and what happens, and I’m willing to chat about why I do it and such as long as it’s useful and interesting.

Ron,

like @Jmv38, I’m trying to find common ground between the way I think most of us would do this, and the way you do it.

If I were a very green teenage programmer, I believe there is no way in the world that I could use your approach, because it requires insight and experience. To build a decent calculator, I would need to plan the whole job quite carefully (just as if I were tiling a bathroom for the first time, I would be reading instructions from a book, whereas an experienced handyman just gets started).

Jmv38 and myself have more experience, but we are still not used to winging it quite as much as you have. So I see the following approach as a good compromise, providing an initial structure that tries to avoid later refactoring, while still getting full value from tests.

I would probably design the job something like this

  • a number is a series of numeric characters delimited by an operator. It can be prefixed by a minus operator

  • a binary calculation consists of a number followed by a binary operator, followed by another number (which, when terminated by any operator, triggers calculation)

  • the calculator displays the result of the last calculation and all keystrokes since

I know this isn’t complete, it just shows that I would break the job into much larger chunks than you started with. And I think this is where Jmv38 is coming from, too.

Then to use a test driven approach, I would set up a series of tests for each of those segments.

I can see that if you do this a lot, you might find yourself not needing to plan so much up front, which I think is where you have got to. But I’m not sure I could jump straight into Agile from where I am now, even without the complications of writing tests for graphic programming.

Finally, I noticed that after quite a few hours, your calculator was very incomplete. I don’t mean that as a criticism, but if one of the advantages of Agile programming is speed, it didn’t come across that way. I’m sure more than one of us thought it should be possible to code a complete calculator well within that time. I think it would be very useful to clarify this to avoid any misunderstandings.

I think the point of the TDD approach is you have to think about your solution MORE to write tests first than you would if you just started cutting code.

Also, to the speed question, it’s a lot faster if not writing an article at the same time. Also, TDD tends to be slower at first when the program is tiny, the speed payback comes as the program gets bigger, because you end up with better decoupling (normally just a side effect of having making it easier to write the tests) and also you can make changes on your big solution with confidence because the testing will catch anything you do wrong.

Also, when working in a team, you can ignore the things others have built more, because if you didn’t know about something and you broke their code, the tests would catch it.

So Ignatz, you are right, it’s not quicker in a raw speed sense, although with practice it’s not too much slower, but in the long run it’s good.

Like @Jmv38 and @Ignatz, I think that I would not really go into a program without planning it out. Later, once I have initial structure I wing some parts, but I usually end up thinking things out with some paper and a pen.

My question is, have you always programmed like this, and if not how did you get used to this style of just going in and making structure as you go?

Thanks for your answers Ron!
And i am still quite interested to read you own way to develop UIs with agile method!
thanks!
[ps] i’ve noticed how easily i could pickup your code, modify it, and correct for my bugs, without even trying to understand the global picture of your code, nor worrying about not doing it. That’s certainly a +1 for you TDD approch. However i am currently programming an fft ui in python, a langage i almost dont know anything about, and i am certainly not doing it by writing tests first! I feel totally unable to apply your method… yet! New method + new langage? Too much for me at once.
[edit] on the other hand, if i knew how to test ui, which is a big part of my fft project, i might finally adopt the TDD, because i can maybe make visible progress without too much initial ‘structure design’… Very attractive option…

Hi Jmv …

(I’m randomly answering posts here, yours is next. :slight_smile:

GUI testing with TDD is quite difficult. As I may have said somewhere around here, I usually try to put all the logic elsewhere in the system, so that the GUI is so baldly simple that it is safe to just code it. That may be a cop-out but I freely grant that I don’t know how to test most GUI things.

The same is true for other screen-related things, although perhaps not quite so true. I’ve been writing a Spacewar game (like the old one that ran on the PDP-1 ages ago). In that game, you have little graphical spaceships, made up of a few lines. I don’t know how to TDD that. I just drew lines on the screen until it looked good, guessing at the proportions. I finally came up with a triangular ship 30 pixels long, 15 wide at the back. And when it is running its engine, I put a little flickering line out behind for 5 pixels or something. And I made it flicker by putting a delay in the draw, turning the line on and off, and I fiddled the delay till I liked the look.

I know no way to TDD that. Same thing with how fast to change the angle of rotation when the player’s finger is on the turn button: I just fiddled it until I liked the rotation. And, honestly, I don’t even know how to do a TDD test to test the rotation code itself. I can rotate the ship 90 degrees or PI/2 radians and look at it. I don’t know how to read the pixels off the screen and see if they are where I wanted.

Now maybe someone who knows different things from what I know could TDD those things with great clarity and value. I myself do not know how to do much of it.

I may still write up what I do about the GUI and I’ll try some TDD as part of it, most likely. But I rather suspect that my conclusion will be that most of it isn’t worth-while.

TDD is easy to do in some places, like the “model” part of the calculator, and hard to do in others (like seeing if the pixels went to the right place when we view the dungeon map). Similarly, a screwdriver is really great for driving screws, and sucks for pounding nails. We use the tool where it helps us and mostly do well not to apply it to jobs where it isn’t a good choice.

Unfortunately, the power of any tool, like TDD, is only gained when we get good at using it. So I recommend to people who are at all interested: Try it. Try using it in different areas, on different problems. Feel free to stop using it any time you want. For extra good results, though, consider practicing until you’re sure some TDD expert would look at your work and say “Good TDD”. When you’re that good … you’re qualified to decide.

Of course, we can decide any time, and no harm done. But to really evaluate a tool, rather than just reject it, we should be good at using it.

I just thought it might be interesting to show what I did. I guess it has been: at least people keep commenting. :slight_smile:

JakAttack,

I understand about planning in advance on paper or similarly. I do it too, sometimes. And I’ve been programming (almost daily) for over a half century, so I can usually see pretty quickly how I’d approach a problem. So it doesn’t take much sketching before I"m ready. For someone less experienced, more sketching might pay off.

However, if you pay attention to what you really build compared to what you sketched, your experience might be like mine: the thing I build is quite similar to what I sketched, but almost always quite different too. The reason is that the coding tells me that things I thought were easy are hard, that other things I didn’t think of at all are easy. The coding tells me what the design should be like. So when I do my paper design, I don’t push it too far until I let the code be involved in my design decisions.

I have not always worked that way. I have degrees in math and computer / communication science, and I am well indoctrinated in the “big design up front” idea. But when I got involved with Agile, it became clear that we couldn’t work with all the waterfall style. We need to ship visible software every couple of weeks. That means starting with a simple design, growing it over time. So I had to learn to do it, and of course, since my chosen mission was to help others go Agile, I had to learn to explain it. That meant I had to figure out how it works and why. I’ve done fairly well at that, though I always find new things to learn.

Anyway, I just kept doing it and once you learn a bit of refactoring, it’s really quite fun and rewarding.

As always, though, I’m not here to tell anyone what they should do. I’m here to describe what I do, why and how I do it, and what happens when I do it. If people find that interesting, I encourage them to try the ideas and make them their own. If not, that’s fine too. :slight_smile:

Spacemonkey: very well put. I agree entirely. Or nearly so. :slight_smile:

Ignatz,

As spacemonkey suggests, it wouldn’t take so long if I were not writing down my every thought and experience. :slight_smile:

It’s worth considering, though, that at the size of the calculator, one might make it work by just whacking it in and maybe hammering on it a bit. It would then be hard to refactor and hard to be sure one hadn’t broken it, because we’d not have many tests to run.

It does take practice to work that way – just exactly as it took practice for you, and dave, and jmv, and all of us to work as we do. We’re as good as we are because of the many hours we put in. One certainly doesn’t have to start over to work in TDD style. But one does have to practice. That’s more fun if you get to sit with someone else and do it, especially if they know the approach well enough to kind of coach you along.

But there are plenty of places where I don’t TDD. I mentioned my spacewar game, which has no tests as far as I can remember without looking. I’m also building a Ruby/Sinatra/Kramdown/Rack thingie to replace the wordpress that runs my blog. So far, we haven’t written a single test for that. Soon, probably, we will. But up until now, TDD has not seemed like a thing that would help.

Since I’m rather practiced at it, I trust my guess that it wouldn’t help. And I’m expecting to discover soon that I should have started testing sooner than I have. That’s how life works.

Anyway … if it seems fun, try it. If not, not, either way is cool. We’re here to have fun, mostly. Don’t do stuff that isn’t fun, that’s my advice. :slight_smile:

There’s something very interesting emerging from this, for me at least.

I have been a spreadsheet specialist for many years, and spent a lot of time researching how to improve quality and reduce errors in the large consulting companies I worked in (and in our clients too).

I came to the conclusion that everything I read about it, and about software quality in general, could be distilled into a few very simple guidelines

  1. make it easy to check (ie peer review) and maintain

  2. make it safe for other people to use (eg clearly labelled, unambiguous)

  3. prove your answers correct as far as possible

and perhaps it shouldn’t surprise me that this has echoes of TDD (although I don’t think you could use TDD itself in spreadsheets).

@ronJeffries thanks for your comments. I appreciate your honest statement about TDD and UI.
@Ignatz testing excel spreadsheets… That is a real nightmare! Quality people are nowadays trying to enforce that these speasheets should be ‘verifyed’… meaning every formula should be verifyied… they really mean it… lol lol lol … X( X_X they never wrote a single useful excel spreadsheet in their lives but tell us useful people how we should work… I’ll stop here, or i think i am going to put myself in a position where, as a mod, a should ban myself!

@Jmv38 - without trying to sidetrack the main conversation, the problem with spreadsheets is they make it too easy for complete beginners to be highly dangerous. That is the real danger of making programming too easy, that people don’t think they need to learn any disciplines or techniques, but can just turn on the engine and start driving with no experience.

The way I approximate TDD in non-trivial spreadsheets is to create as many checks as possible (eg % add to 100, data reconciles correctly), then collect the tests in a Test sheet, with each test producing a true (OK) or false (error!) result in a column down the page. I then add the errors, and report the total number on the main results sheet so it can be seen clearly. (I admit I borrowed this idea from someone else).

The problem is that, a little like Codea, you can’t write checks for some of the really important things, like whether spreadsheet results are correct (because usually they are complex, and there may be logic errors, eg the tax got left out). The best you can do is write “reasonableness” checks that test if results are within certain bounds. Then you have a separate category on your Test sheet for these “warnings” (not errors, because they may be correct even if they appear unreasonable).

I once researched program testing techniques, and read a lot of stuff by Cem Kaner (do you know him, Ron?). He shows just how difficult it is to test effectively, through a series of very good papers and videos. I have all his stuff if anyone is interested.

I also found research showing that peer testing typically finds only 50% of errors, and group testing finds 80% of errors. That’s pretty scary.

My conclusion on spreadsheets is that the best way to make them accurate is to build them very carefully, then keep people away from them, by automating everything you possibly can. I have seen people mess up spreadsheets in every possible way.

I guess what I’m saying with all of this is that testing is really hard.

good ideas for testing. Good conclusions. +1.

There has been a little work on TDD for spreadsheets. Google will turn up some articles and papers if you’re interested. My own take is that it’s interesting, seems tedious, and would need better tools. Important problem, perhaps, because many decisions are made with spreadsheets and reported error rates in large sheets are quite high.

Couldn’t help reacting to appreciation for “honest statement about TDD and UI”. I hope everything I say is an honest reflection of what I actually think. :slight_smile:

Ron,

Spreadsheets are a two edged sword, in that their accessibility to relatively unskilled people makes it easy to get a lot of work done, but the quality…

Back to TDD - I watched a couple of basic videos about TDD, and they stress the need for careful planning before you start writing any tests.

This looks a lot more like what I suggested higher up, ie get the structure mapped out first, then start with the TDD. I think that’s why I found your calculator example a little puzzling, in that there didn’t seem to be much initial planning.

I think part of it is experienced developers do that planning of structure without appearing to. For example in Ron’s article he immediately jumped in with a calculator class that would recieve key presses and contain a display that shows the current values and results… While in the article he did that quite casually from a screen mockup on the back of a fag packet (as it were), the reality is the decision to write the calculator “model” as a seperate class and interact with it in that way is a major bit of design.

But for someone who does big OO code type stuff day in day out, using a pattern of class(es) completely isolated from any UI to do the logic is kind of not even a design any more, it’s just the way you do it.

I’m ill disciplined as I don’t do real code day to day, so I generally do old fashioned functions and spaghetti(ish) code and then refactor to classes later (as you may have seen from some of the messy code I’ve posted around the forum)

Ignatz and Spacemonkey: I’m wondering whose videos they were. (Also wondering why autocorrect insists I don’t know how to spell your name.)

Of course you can design ahead as much as you want, and yes, an experienced person has advantages. First, they can see a decent enough design quite quickly. Second, with refactoring experience, they can quickly morph the design as needed.

I am fascinated by the question of how little up front design one can do, and how much one can change a design using only small incremental refactorings. I have found that when starting greenfield, one can start incredibly simply and always wind up with a good design quite incrementally. So my articles, and my tome Extreme Programming Adventures in C# (not recommended), all try to show what happens when you start with nothing and pay attention to simple design principles. It works surprisingly well.

More a matter of inspiring and raising the question of how lean we can be, rather than instructions as to what others should do. Might, not should. :slight_smile: