| |||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||
Print This Article REALbasic University: Column 048
RBU Pyramid XXI: Wrapping UpRBU Pyramid is finished! Yeah! I'm sure we're all sick to death of card games, and it will be fun to go explore other topics, but before we do, I'd like to take this column to examine what we accomplished with RBU Pyramid, and analyze the success/failure of RBU during this project. Did you enjoy the creation of RBU Pyramid? Were the lessons too drawn out? Was the pace too slow, too fast, or just right? I'm interested in your opinion, of course, but I'll offer my own analysis as well.
My Original GoalsWow, we've spent a whopping twenty weeks working on RBU Pyramid. That's more columns than I originally anticipated (I was thinking of about a dozen), but then it's difficult to judge a project like this until you actually do it. (Guilt trip: Now that you see how complicated even a simple card game is to create, I hope you'll all remember to pay your shareware fees next time you're asked!) I know there are a few people who didn't like me spending so much time on a mere game, but I felt this was a valuable project for a number of reasons. First, I wanted to show the development of a complete, full-featured program, with support for multiple undos, a help system, saved preferences, graphics, a high score chart, etc. All the tutorials I've ever completed create something basic and ordinary. Many times it's an example program, not even finished! When I first started programming, I found I could easily finish a tutorial, but the real challenge was going beyond that: I'd decide I wanted to add a tiny extra feature or enhancement (like a fancier About Box), and then bang my head against the wall in frustration. If only there was source code showing me how someone else solved those same problems! I knew from the beginning RBU Pyramid was going to be an extensive lesson, but since it's the kind of thing I always wanted when I was learning to program, I wanted to write it. My second goal with this series was to demonstrate the actual process of writing a complete program. Beginning programmers often stumble through a project, learning as they go, wondering the entire time if they're even vaguely on the right track. I wanted to show that even seasoned programmers have to make complex decisions, compromises, and even mistakes. That's encouraging for beginners, and the process of second-guessing, revising, and correcting mistakes is valuable for everyone. The third goal I had in mind was to continue the RBU tradition of actually explaining why things are done the way they are. I hate tutorials that just say, Step 1, do this, Step 2, do that, etc. If that approach worked, everyone who's done a painting-by-numbers kit would be a famous artist! If there are multiple ways to do something, I like to justify the approach I'm taking. If we're learning about solving a particular problem, I like to explain the concepts behind that situation, and detail alternative solutions. So, how did I do? Did I meet my goals? Was the pace of learning too slow or too fast? Only you, my readers, can answer that question, and the answer might be slightly different for each of you. Overall, I'm pleased with the results of the project. The aspect of following a complete project from concept to completion worked very well: there were many small lessons that grew naturally out of the project context. Those small lessons -- explanations about data structures, bug fixes, exchanging data with a dialog, etc. -- are too small to have an article written about them, yet they crop up all the time in real-life projects and are often the thing that frustrates a beginning programmer. While the project dragged on a little longer than I'd anticipated, for the most part it was because certain aspects of the project just needed more explanation, and I don't regret taking the time to explain things. I do, however, wish I'd planned ahead just a tad bit more: I had my version of Pyramid almost but not 100% finished before I started this series, and that caused some problems in creating the tutorial. More significantly, I should have planned in advance exactly which parts of the program I was going to explain in which columns -- written a complete breakdown of the program in outline form. Since I didn't, the columns wandered a bit, and I ended up needing a series of "miscellaneous" columns to wrap things up. There was one thing I had expected to do in this series that I didn't. When I conceived of this type of tutorial, my original thinking was that it would follow, step-by-step, the moves I'd originally taken as I created the program. It would be like looking over my shoulder as I programmed. You'd see me make mistakes, revise my strategies, amd insert debugging code in an effort to track down odd glitches. I would still like to do that kind of tutorial someday, but it couldn't be on a project as complex as RBU Pyramid. There were several reasons I didn't do RBU Pyramid that way. First, for that kind of tutorial to follow my every move, I must document everything I do down to the smallest detail. In the case of RBU Pyramid, I'd already started writing the game before I'd decided to use it as part of a REALbasic University project. By that time I'd forgotten most of my early steps and it would have been artificial and inaccurate to go back and retrace my steps. Second, that level of detail would take too much time. It would be interesting to read and there'd be value in it, but for a weekly column it would take over a year to finish the game! For example, look at the undo system I created for RBU Pyramid. For the column, I presented that across a couple lessons and that was that. In real life, of course, I added the undo system after the game was almost done (not a good strategy) and it took me some degree of hassle to figure out how to wedge that into my existing design. There were some major bugs and I spent several long Saturdays playing RBU Pyramid and attempting to undo in an effort to figure out which actions didn't undo properly. If I'd documented my entire process, it would have taken four or five columns. And that's just for one feature! Finally, I questioned how much value there'd be for you to wallow in my mistakes. Yes, it might ease your ego a little to know that even a (hem) pro like me makes mistakes, and yes, you might find my debugging techniques helpful in your own bug hunting expeditions, but in many ways reading about that might be like reading two or three rough drafts of Moby Dick! So in the end, I decided to present a fairly straightforward, finished solution (minus a few bugs), and in retrospect, I still feel that was the correct decision.
What We LearnedSo what did we learn in developing RBU Pyramid? It's surprising, when you go back and through the twenty lessons, how much we covered. Here are a few of the key techniques and skills we studied:
While the tutorial was specific to RBU Pyramid, the basic techniques we covered are not. You can reuse many portions in other programs: the Preference system, the About Box/Splash screen system, the code that saves a palette's size and location, the help system, the background pattern drawing, the undo system, the hotCanvas custom canvas, etc. Remember, REALbasic makes it easy to reuse code: you can drag a custom class, module, or window from your project to your hard drive to create a copy of that on disk. Then you can easily drag that into another project to reuse it.
That's a WrapWell, that's enough of a wrap-up for RBU Pyramid. I hope you enjoyed the project and learned something, and I hope you find time in your busy schedule to actually play the game occasionally. Next week we'll have a little change of pace, and then we'll get back into a series of smaller, simpler, "one-shot" lessons for a while.
Next WeekA special surprise...
LettersProving that you can learn something new every day, I received a couple letters from people explaining what's going on with the Symbol font weirdness I mentioned in last week's column. First, from Avi Drissman:
I also received this nice explanation from the manager of Apple Computer's Font & Language department (sorry about the special characters not being correct, but this is the way they came through in the email and I'm not sure what they're supposed to be -- you still get the message, however):
Thanks for both of these explanations -- Mac OS X is quite a different beast than regular old Mac OS. Finally, we've got an interesting question from a reader in France:
Your English is no doubt better than my long-neglected French, Jacqueline! (Mon français est terrible! ;-) Your question is a good one: I've often seen situations where an item needed a "refresh" to work properly, and it can be a mystery as to when it's needed and when it's not. All the refresh command does is force the item in question to redraw. In your case, your code did work -- the actual score was reset to zero -- it just didn't update the visible score the viewer saw. Forcing the redraw made the new score display. Normally REALbasic "knows" when an item needs refreshing and handles it automatically. I don't know the specific order that RB follows when it decides to refresh something, and I haven't analysed exactly what's happening in this case, but my suspicion (and this is my unqualified and non-scientific answer) is that the change is happening too fast. In your case, you put the initialization stuff at the end of the method, while I put it at the top. In my case, several other things happen before the end of the method (a fresh deck of cards is dealt, for instance). That gives the initialization change time to "sink in." My theory is that in your case, the value of the score is changed at the very end, but the program has already moved past the "drawing the score" portion of the program and so it draws the old value. Scientifically, this is bunk: it doesn't make any sense at all. I mean, when you change the value of a variable, it should be changed immediately. And a drawing routine that updates the score ought to reflect that immediately. But I've seen too many times where that wasn't the case and that's how I developed my "sink in" theory. I certainly don't take my theory seriously, but it does make a good rule of thumb. Even you must have instinctively sensed it because you added a refresh command when you saw your scores weren't updating: why else would you think of adding that as a way around the problem? So the short answer is I don't know why this happens sometimes. But forcing a field to refresh, unless you're in the middle of a long loop, is generally harmless. (In the middle of a loop it will make your loop 100 times slower.) So refresh away and don't worry about it: it's generally a minor problem (though it can be disconcerting to debug). And maybe some RB expert out there has a better answer: I'd be happy to publish it in a future column. About the Column REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers. Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.) About the Author See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
| |||||||||||||||||||||||||||||||