TweetFollow Us on Twitter

March 96 - THE VETERAN NEOPHYTE: Killing Time Killers

THE VETERAN NEOPHYTE: Killing Time Killers

Bo3b Johnson

So I'm sitting at my desk, mouse in hand, digging through the guts of my Mac, trying to track down yet another pathetic bug. The only trouble is, this is getting dull. I've done it a thousand times, and I always win; it's just a question of how much time the old ball and chain is going to eat up this time. Worse, the wind is blowing 20 knots right outside my window, and for the windsurfers in the crowd, you know the exquisite torture of good wind that you aren't allowed to transform into mind-blowing speed.

Maybe for you it's that you'd like to get home to see your insanely great mate. Or you've got kids whose names you can't pronounce. It's even likely that some of you just graduated from college and are still astonished that they pay you for something that's so much fun. But you're thinking, "If I can get this bug fixed quickly, I can get back to writing that rad Marathon hack to make the other net players slower than me." Perhaps your boss has started to notice that you spend a lot of time on the job but you don't really get very much done. Getting a little nervous? What if he's thinking of pulling the plug on your baby because you're too slow?

Or maybe you shipped the 1.0 version, but it had a few too many bugs, and MacWEEK was so incensed that they broke with the tradition of objective journalism and are calling for your head. People who bought your software with actual money have been calling every day, filling your answering machine with unveiled threats. It seems that you left a bug in there that just cost several thousand people each about two weeks of valuable time, reentering their data.

In particular, recognize that the wasted time from programming errors and bugs gets exponentially more expensive the further into the process you get. If I make a syntax error, I just fix it and recompile. If I toss buggy code over the fence to the testers, now I'm wasting their time. If I ship software with occasional crashing bugs that I just can't quite track down, I'm wasting thousands of people's time.

The point is, there are lots of ways to waste time while programming. I'm here today to offer some ideas on how to save time through better programming habits, so that you can take up windsurfing, or maybe the electric guitar, or learn how to pronounce your kids' names, or gain "the power to crush the other kids" while playing Marathon. Whenever I mention windsurfing, substitute your favorite quality-of-life enhancer.

I'll use some real life examples, and we'll see what sorts of lessons we can learn from them. I've categorized these ideas in three ways. First, there are some obvious time wasters that can be eradicated; these aren't really bug related, just daily time wasters. Considering how much time bugs cost, the second category consists of high-value rules that can find bugs quickly and painlessly. Finally, there are the super-value rules that prevent bugs from happening at all. Be sure to consider how these ideas might apply in your specific circumstances.

RIGOROUS, YET REUSABLE

OK, I'm in the midst of writing the MMU tables for Blat, and I realize that I've already got a similar table. Not being a fool, I know not to rewrite code I've already written, so I open that file and casually copy and paste the table into my current work. Oh no, not another copy and paste casualty! Apparently I missed changing those two table entries, and with MMU tables that means the machine hangs before MacsBug loads. Seems like every time I paste in code there's something I miss, making it not compile -- or worse, causing a malfunction.

Even with small chunks of code, I've found it helps to review the pasted code line by line, carefully, and not to assume that since it ran before, it'll run now. Some subtle assumptions may have changed, and even though reusing code is certainly superior to writing it again, don't be misled into thinking this is risk free. A more powerful technique is to seriously modularize code, so that when I copy and paste I take an entire routine, not just a few lines. With a well-defined interface, the chances of blowing it are greatly reduced. This means adopting the habit of writing each routine with the idea that I'm going to reuse it later. This radically improves every routine I write.

New rule: Reuse code modules, not code fragments. If the code has to be altered, inspect it as if it were new (which it is).

VERBOSE, YET LUCID

While in the guts of Font/DA Mover, I ran across some very strange code that didn't make any sense to me at all -- and it wasn't documented. It was never executed as far as I could determine, but I painstakingly figured out that it was looking for System file 3.2 and, if found, would patch the OS to fix a font bug. I would have saved a full day of effort had there been a comment in that funny little splat of code. Like I'm supposed to know what the bugs in System 3.2 are off the top of my head?

Comments really are necessary to make code reusable and maintainable. I always write "strategy" comments, which say what the routine is trying to do, and avoid writing "tactical" comments, like what it's doing line by line. Remember, sometimes the time savings occur in the future, not at the moment. I've found that skipping comments is being penny wise and pound foolish. Usually the strategy comments help clarify my thinking on the routine as well, so there actually is a short-term gain.

New rule: Always write strategy comments. It's possible to decipher intent from the code, but why not just explicitly say it?

PLUMP, YET HONED

I used to think it was important to save every line of assembly code that was possible. The first program I wrote for the Mac was Anaclock, an analog clock program, and I remember thinking that if I changed the order of some routines I could save code. Don't we all get into that mode sometimes? If I just change these two lines, I can save an assignment, and blah blah. It must come from the old 128K Macs and Apple IIs.

Well, guess what? These machines are so stuffed full of junk nowadays that saving just one or two lines is as meaningless an effort as trying to decide how many demons fit on the head of a transistor. Worse, I spent my own valuable time deciding something that has zero impact. Sorry, no can do anymore. My philosophy now is: write it straightforward, easy to read, vanilla. I want to save my windsurfing time, not pretend that I know up front what needs optimizing. In the Anaclock example, the computer had an entire second between screen updates. When I actually measured execution time, all the time was spent in CopyBits updating the screen, and waiting in the main event loop for the next second to arrive. There was zero measurable time in my entire clock calculation and offscreen drawing code.

New rule: No premature optimization. Measure with performance tools first. Then optimize only where it counts.

TEMPERAMENTAL, YET DISCRIMINATING

During System 7 development, we once tracked down a bug, taking seven hours in the middle of the night to find it, and it wound up being a bad parameter passed to a ROM routine. Incredibly, I could have found that bug in about 15 seconds if I'd used the Discipline tool. Nowadays, I never debug something by hand unless it has passed all the debugging tools that Fred Huxham and I talked about in our article in develop Issue 8.

There are lots and lots of tools available now, and I use all of them. I don't care how hard they are to use; if they can find a bug in seconds that might take me hours or days, then I win. This includes such notorious tools as Blat and Jasik's debugger. I know Blat's a pain, since it doesn't work on all machines, but hey, it's too valuable to skip. Same with Jasik's debugger. Sure it's confusing, but it's got features no one else provides. Before throwing the software over to the testers, I make sure it passes all the tools.

High-value rule: Use the best tools, all the time. Don't spend time in a debugger when a test tool will hand you the answer on a silver platter.

SPECULATIVE, YET REWARDING

As part of a contract, my job was to make a program to save, print, and display 300 dpi bitmaps that were scanned in from a fax machine through new hardware. This was to be a low-cost scanner, and my software would be the initial scan-and-display code. Nothing too fancy, but it still required basic functionality. I bid 15 hours for the entire program. Was I crazy? Well, of course, but not for this reason. I used MacApp to give me the application functionality, and the FracApp300 sample program was a good starting point for 300 dpi bitmap handling. All I really did was add an object to talk to the scanning hardware, and I came in under bid!

Sometimes learning those new tough coding tools can really pay off. I generally try to sample every new tool and coding advance that comes along to see if it can help me save time. MacApp was clearly a massive win, because it focused my programming onto teensy parts to be added instead of all the Toolbox calls of a typical application. In addition, it was fully debugged and very robust, giving me a more solid final application. I try not to be wedded to any given style or approach; I just want to use the best stuff currently available.

High-value rule: Try new things. New ideas, approaches, tools, and programming styles can be like winning the free-time lottery.

PAVLOVIAN, YET TRAINABLE

Sometimes it takes a while to recognize bad habits for what they are. While writing Bowser, which turned into Mouser and then MacBrowser, I wrote the source code parser by hand, to look for keywords. This was not a good strategy. It was quick and dirty, and stayed dirty, and was less quick all the time. It would be reasonable to expect that after modifying the parser for the eighth or ninth time to handle some stupid language exception, I would have gotten a clue that this was not the right approach. The right answer was to learn how the lex and yacc tools worked, since parsers for both Object Pascal and C++ already existed in that format.

After seeing similar bugs go by several times, it becomes clear that something must be done to stop that kind of bug. I don't want to spend time fixing the same problem over and over again, so now my goal is to permanently fix bugs so that they can't happen again. By this I mean changing how I do things, so that that specific bug will either be caught quickly or never happen again. It can be as simple as adding a test to a test suite to ensure that bugs of that form are caught immediately, or adding an assert to catch that error. Or it can be as hard as changing my programming habits to never use pointer math. Whatever it takes, I try to learn from each bug and make sure it can't happen again. Especially after I've done something twice, it's time to write a tool to fix that problem.

High-value rule: Learn from mistakes. If my dog gets bonked on the nose every time he gets near the door, he learns to avoid the door. I want to be at least as smart as my dog.

FASTIDIOUS, YET NOBLE

Another slant on the Bowser problem is that I wasn't really trying to make the parser right. If I'd been a little more quality conscious, I wouldn't have gone that route, because it was clear that the hand-built parser was clunky. As noted before, the longer a bug survives, the more expensive it will be. Early bug extinction is my goal, so I consciously try to write with quality in mind. Examples are: using the strictest coding rules, not using any tricky features of the compiler, using type-suggestive variable names, insisting on type checking, not using raw pointer variables, avoiding type coercion, adopting a simple easy-to-read style, writing clear module interfaces, and using full warnings in the compiler.

Since I started noticing how much time bugs cost, I've changed my mindset on them. I no longer automatically accept that code will just have bugs. I hate 'em. I want to kill 'em. Better, I want to kill 'em before they hatch. Since they take up my personal time, I feel it's only proper to take it personally when they show up.

Super-value rule: Write with quality in mind. As they say, the inner game of programming is so important.

UGLY, YET EVOLVED

Once upon a time, I was asked to fix a couple of bugs in Font/DA Mover and make it work with TrueType fonts, as an interim solution before System 7. The program was so disgusting to me that I just had to go in and clean it up. Move this here, change these names, document some pieces, take out the redundant code, modularize some pieces -- ah, how aesthetically pleasing. Oops . . . I just introduced a couple of bugs while I was "improving" the code. It felt like progress, but actually it was just motion. You know, like company reorgs.

What to do? Don't "improve" code, unless it's never been debugged. Any fully debugged code, no matter how shoddily written, is superior to newly written code, no matter how pristine. It went against my grain, but the right answer was to leave it gross. That heavily used Font/DA Mover code had thousands of hours of value in it, with literally millions of testers, that were all lost when I rewrote it. Rewriting it took time that I wanted to spend on something more valuable, like fixing the last few remaining bugs -- and then getting outside and windsurfing! Once I rewrote the code, it was like a new program, and thus needed a full development/testing/debugging cycle. I backed off to an earlier "skanky" version and just debugged that.

Super-value rule: Never rewrite something that's been fully tested. It may be ugly, but evolution is on its side.

BORING, YET ELEGANT

We all know about the "cool" things that C can do, and some tricky ways of using it, but sometimes isn't it a bit like juggling live weasels? When I found that using a #define had added an extra unwanted character to each place I used it, it no longer seemed so clever, and felt more like I was playing tricks on myself. Or how about that favorite of putting an actual assignment in an if statement? It's cleverly camouflaged, but there aren't any natural predators here, so I'm not sure this is needed. These simple examples obviously don't do justice to the possible tricks that we've all seen, but they all cost time and rarely add value.

OK, so it's clear that being "clever" often winds up being a way to play tricks on myself. Is there anything wrong with doing it simply, in a straightforward, vanilla style? I know for sure I'll get it done sooner and, even better, the programmer who has to maintain this code won't have to waste a bunch of time understanding mindless tricks (remembering of course that that maintenance programmer might very well be me, two years after I forgot what tricks I was playing). And let's just forget the malarkey about it saving code. Is it really worth saving 10 whole bytes out of a 16 meg machine, at the expense of wasting my time? I want to count cycles and bytes only in places where it makes a measurable difference.

Super-value rule: Write vanilla code. Doing it simply, and the same way each time, also makes it more likely to be correct.

ASSERTIVE, YET FRIENDLY

Back in the deep dark Macintosh past, I wrote the driver for an external RAM disk called DASCH. This high-speed serial link required some different debugging tactics than I'd used previously, because I couldn't step through the code; it was time critical. Any slight perturbation in speed would overrun and cause an error, but I still needed to debug it. It was like a "look Mom, no hands" type of debugging. Code inspection is OK, but I wanted to be sure it worked as I read it. Have you ever read a piece of code that took a branch you didn't expect?

The answer, although I didn't use the name at the time, was to use asserts. These have been talked about a fair amount, and you've probably used primitive asserts under the name of DebugStr. Nowadays, the most powerful combination I've used is to hook together asserts with a failure handler like MacApp's catch/fail mechanism. Asserts make it easy to build a debug-only version that checks every stupid thing that can go wrong and lets me know right up front during testing, but doesn't compile into the final version. The catch/fail stuff makes it easy to handle every possible error in a graceful way. (See the article "Using C++ Exceptions in C" in this issue.)

If something absolutely positively cannot fail, I use a debugging-version assert to catch the occasional times when it does fail, so that I can surprise myself early and not spend hours tracking down the "impossible" error. One great thing to check with asserts is input parameters, to catch those inevitable times when some routine passes in rubbish.

Super-value rule: Use asserts along with a failure handler. Catching bugs as they happen is vastly superior to backtracking 15 miles after the program crashes.

ENDING, YET BEGINNING

I'm not going to pretend that this is all there is to the idea of saving time, but hopefully the idea seems worth pursuing. It has certainly helped me get better at my carving jibes and, not incidentally, better at programming at the same time. Higher-quality code, fewer bugs, earlier ship dates, happier customers, and more free time. Yup, I'd say it's been worth it. If you've got some additional time-saving ideas, I'd naturally be interested in trying them too, so write me at bo3b@rahul.net.

RECOMMENDED READING

  • Writing Solid Code by Steve Maguire (Microsoft Press, 1993).
  • Debugging the Development Process by Steve Maguire (Microsoft Press, 1995).
  • "Macintosh Debugging: A Weird Journey Into the Belly of the Beast" by Bo3b Johnson and Fred Huxham, develop Issue 8, and "Macintosh Debugging: The Belly of the Beast Revisited" by Fred Huxham and Greg Marriott, develop Issue 13.
  • Zen and the Art of Windsurfing by Frank Fox (Amberco Press, 1988).

BO3B JOHNSON (bo3b@rahul.net) is completely whacked out about windsurfing, and takes summers off in order to windsurf every day. But since it's winter, he's doing consulting so that he can pay for his next windsurf board and windsurf trip to Aruba. Bo3b prefers to be addressed as "Bob," since the 3 is silent.*

Where's Dave? That other Johnson, who usually writes this column, is probably at the public library researching his obsession du jour, taking his dogs for very long walks, or reclining on the couch reading a book. Since he's cut back his working hours, we're having guest Neophytes write this column. We can't promise they'll all be Johnsons, however.*

Thanks to Jeff Barbose, Jim Friedlander, Brian Hamlin, Fred Huxham, Dave Johnson, Jim Reekes, and Patty Walters for their terribly helpful review comments.*

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Hopper Disassembler 4.5.0- - Binary disa...
Hopper Disassembler is a binary disassembler, decompiler, and debugger for 32- and 64-bit executables. It will let you disassemble any binary you want, and provide you all the information about its... Read more
Adobe Acrobat Reader 19.010.20064 - View...
Adobe Acrobat Reader allows users to view PDF documents. You may not know what a PDF file is, but you've probably come across one at some point. PDF files are used by companies and even the IRS to... Read more
Airmail 3.6.53 - Powerful, minimal email...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL, Outlook.com, Live.com. Airmail was designed... Read more
iFinance 4.5.4 - Comprehensively manage...
iFinance allows you to keep track of your income and spending -- from your lunchbreak coffee to your new car -- in the most convenient and fastest way. Clearly arranged transaction lists of all your... Read more
Microsoft Office 365, 2019 16.20 - Popul...
Microsoft Office 365. The essentials to get it all done. Unmistakably Office, designed for Mac Get started quickly with new, modern versions of Word, Excel, PowerPoint, Outlook and OneNote-... Read more
Microsoft Remote Desktop 10.2.4 - Connec...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
Spotify 1.0.95.289 - Stream music, creat...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
Dropbox 63.4.100 - Cloud backup and sync...
Dropbox is an application that creates a special Finder folder that automatically syncs online and between your computers. It allows you to both backup files and keeps them up-to-date between systems... Read more
Little Snitch 4.2.4 - Alerts you about o...
Little Snitch gives you control over your private outgoing data. Track background activity As soon as your computer connects to the Internet, applications often have permission to send any... Read more
Skype 8.36.0.52 - Voice-over-internet ph...
Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more

Latest Forum Discussions

See All

148Apps year end round-up: These are the...
We've reached the fifth month of the year in our round-up of all of the top games for iPhone and iPad that came out in 2018. If you've missed the other entries in this massive list, don't you worry, because we're going to give you links to them all... | Read more »
148Apps year end round-up: These are the...
Oh hi there, and welcome to the fourth part of our series about the very best iPhone and iPad games that came out in 2018. We've made it to April, which is when Fortnite came out. So, yeah, Fortnite is at top of this part of the list. Not really a... | Read more »
148Apps year end round-up: These are the...
It's Monday, and our round-up of the best games of 2018 has landed on March. There were some pretty amazing developments in the third month of the year, mainly thanks to the launch of PUBG and the start of the Fortnite beta (technically Fortnite... | Read more »
Twinfold guide
Twinfold may look like a cheap Threes! clone at first glance, but it's so much more than that. It's actually a rather deep roguelite with a really satisfying difficulty curve and almost endless replayability. Since the game's depth does take some... | Read more »
Which of these iPhone and iPad games sho...
On a normal week we like to give you the chance to vote for your game of the week on Thursday. But since this clearly isn't a normal week, we've decided to give you the chance to vote for our game of the week on Friday. You're welcome. [Read more... | Read more »
Munchkin.io ends 2018 in style with a ne...
While it can sometimes seem like we are drowning in a sea of battle royale games, few struggle to actually deliver the kind of fun and frantic experience you’d expect from a refined entry in the genre. Well step aside from those other games because... | Read more »
Choose a side in Rift of Raigard, the ne...
If you’re an RTS player that’s constantly underwhelmed by most genre entries on mobile, or sick of putting up with stingy F2P models and cheaters, Rift of Raigard is the base building game for you. Developed by a team of creators who are equally... | Read more »
148Apps year end round-up: These are the...
Our round up of the best games of the year has rolled along to February. Which makes sense, since we started off with January - click here and you'll be able to read the top 5 in its entirety - and February was definitely a doozy, we can tell you... | Read more »
The top 5 best gifts for mobile gamers t...
Since it's the most wonderful time of the year according to most adverts, and since the most wonderful time of the year is all about the giving and receiving of presents (and probably some other stuff, we guess), we thought it was high time we... | Read more »
Dragalia Lost - Resplendent Refrain Sabn...
Dragalia Lost's latest event, Resplendent Refrain, is an event that favors light Adventurers in an all new raid dungeon. This dungeon has four teams of four face off against the mighty Sabnock, which is probably the toughest raid fight in the game... | Read more »

Price Scanner via MacPrices.net

Get a 2017 12″ MacBook for $200-$240 off MSRP...
Apple has Certified Refurbished 2017 12″ Retina MacBooks available for $200-$240 off the cost of new models. Apple will include a standard one-year warranty with each MacBook, and shipping is free.... Read more
Two weeks until Christmas, and B&H contin...
B&H Photo has new 13″ MacBook Pros on sale for up to $200 off MSRP as part of their Holiday 2018 sale. Their prices are the lowest available for new 13″ MacBook Pros from any Apple reseller.... Read more
Apple Watch Series 3 sale! Get a GPS only mod...
Get an Apple Watch Series 3 GPS only model for $50 off MSRP today on Amazon, with 38mm Watches starting at only $229. Shipping is free: – 38mm Apple Watch Series 3 GPS only: $229 $50 off MSRP – 42mm... Read more
Flash deal: Apple HomePods for $249 at B&...
B&H Photo has Apple HomePods on sale for $249 as part of their Holiday 2018 sale. Their price is $100 off Apple’s price and the lowest available from any Apple reseller. Shipping is free: –... Read more
12″ 1.2GHz Space Gray MacBook on sale for $11...
B&H Photo has new 2017 12″ 1.2GHz Space Gray MacBooks on sale for $150 off MSRP this week, just $1149. Shipping is free: – 12″ 1.2GHz Space Gray MacBook: $1149 $150 off MSRP Amazon lowered their... Read more
Roundup of Sprint Holiday 2018 sales: Deals o...
Sprint is offering a number of deals this Holiday 2018 season on Apple products, including the new 2018 iPhones, Apple Watch Series 4, and 9.7″ iPad: – $100 off an Apple Watch Series 4 when you add a... Read more
$190-$200 off on iPhone 6s & 6s Plus at T...
Total Wireless is offering the iPhone 6s starting at $199.99 through December 31, 2018. Sale prices are available on the following models: – $100 OFF on the 32GB iPhone 6s, now $199.99, free shipping... Read more
B&H offers clearance 2017 MacBook Airs fo...
B&H Photo has clearance 2017 13″ 1.8GHz MacBook Airs on sale for up to $200 off MSRP, with models available starting at $869. Shipping is free: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $869, $... Read more
Get last year’s 10.5″ iPad Pro, Certified Ref...
Apple has Certified Refurbished 2017 10.5″ iPad Pros available for $100-$170 off original MSRP, depending on the model. An Apple one-year warranty is included with each model, and shipping is free... Read more
Apple still offering Certified Refurbished 9....
Apple has Certified Refurbished 2016 9.7″ iPad Pros available starting at $469. An Apple one-year warranty is included with each model, and shipping is free: – 32GB 9″ iPad Pro WiFi: $469 original... Read more

Jobs Board

*Apple* Systems Specialist - Western Washing...
Apple Systems Specialist Apply now Work type: Permanent Full Time Location: Bellingham, WA Categories: Academic Affairs Position Title Apple Systems Specialist Read more
Senior Desktop Support Technician, *Apple*...
**Requisition ID** 18-1384 **Job Title** Senior Desktop Support Technician, Apple Support **Location** New York **Schedule** Full-time **Type of Position** Regular Read more
Best Buy *Apple* Computing Master - Best Bu...
**660853BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Location Number:** 001406-Allen Park-Store **Job Description:** The Read more
*Apple* Mobile Master - Best Buy (United Sta...
**660896BR** **Job Title:** Apple Mobile Master **Job Category:** Store Associates **Location Number:** 001017-San Angelo-Store **Job Description:** **What does a Read more
Sephora Product Consultant - *Apple* Blosso...
Sephora Product Consultant - Apple Blossom Mall Location:Winchester, VA, United States- Apple Blossom Mall 1850 Apple Blossom Dr Job ID:1056553 Date:Yesterday Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.