Archive for October, 2006

October 31st 2006

REALbasic Documentation Generator

Many of you who have read the NUG or frequented the forums remember talk and an early beta of RBDocGen by Joe Ranieri. He asked me to post a link to his poll to try to guage interest in it.

For those who aren’t familiar with RBDocGen, it’s a utility that can be used to generate documentation from your REALbasic classes, similar to DoxyGen or JavaDoc. It reads your native rbp project, and it is extremely customizable via RBScript. This is mostly useful for people who release classes or modules for other users, and need to provide documentation. Instead of maintaining documentation externally, you can add special comments to your method, or add notes which will be turned into HTML documentation.

If this sounds interesting and you would like to see this product be released, I urge you to go place a vote on his poll. The more people interested, the more motivation he has at releasing it publicly. And FYI, I already voted :)

Thanks!

2 Comments »

October 30th 2006

Un-advertised Side Effects are Bad

Today’s fun bug fix is gvarthhh. This bug is that after using AppendStyleRun with text that is of a different size than the editfield’s settings, the scroll bar won’t properly be updated until you click on a partially visible line at the bottom.

It didn’t take me long to fix the bug, but the reason there was a bug was due to a bad coding practice that thankfully I don’t run into very often. That is, un-advertised side effects.

What do I mean by un-advertised side effects? Simple really:

Sub UpdateLineHeightMeasurement()
// do some nifty calculations
End Sub

Sub GetLineCount()
UpdateLineHeightMeasurement()
// Do some other stuff
End Sub

UpdateLineHeightMeasurement has side effects, and those side effects are predictable because the method is named clearly. However, it is unclear that GetLineCount might also update the line height measurement. This is bad because these two situations behave differently:

// Situation 1
totalHeight = mLineHeight * GetLineCount()
// Situation 2
totalHeight = GetLineCount() * mLineHeight

Now, everyone knows from elementary math that multiplication is associative, which means that a * b = b * a. However, we’ve gone and broken our math in the case that mLineHeight is “stale”. The first time situation 1 runs, it’ll be using the old value of mLineHeight. The next time it runs, it will use the updated value. Situation 2 adds to the confusion because if you’re using it in this order everywhere except for one spot, you’ll be fooled into thinking that the line works great always.

This is what the bug boiled down to. The fix? Calculate the line height before doing the calculation, and put a hairy note in there about GetLineCount. Unfortunately there is a partially good reason for this side effect: GetLineCount will potentially ask ATSUI to do line breaks, and once it does that, everything is already set up to query for the line height also. The ultimate fix? In Cocoa we’ll be using the Cocoa EditField, which will allow us to not have to optimize our code very much, because it’s already optimized underneath the hood.

The moral of this story is to name your methods clearly, and try to avoid innocently-named methods that have some slightly obscure side effects. It will only get worse if one day you begin using a method with un-advertised side effects, and propogate the behaviors even further. A scary and steep slope, definitely best to avoid.

3 Comments »

October 29th 2006

Why REALbasic?

One thing that people often ask me is why I use REALbasic. While I’m about to go into my reasons, I really want to hear from you about a few things:

  1. Why do you use REALbasic instead of some other environment?
  2. If you could have one wish granted, what would you add to REALbasic?
  3. Still picking only one thing, what would you change in REALBasic if you?

I suppose I’ll start it off.

  1. I use REALbasic because I feel the most productive in it. I learned it back in version 2.0, and while I have learned other langauges since, I always come back to REALbasic in the end. It was easy enough for me to learn back then (my first programming language after HyperCard), yet it has been powerful enough for most tasks since.
  2. I’m going to break my own rule and list two related items: multiprocessing capabilities and an optimizing compiler. These two features would add an immense amount of power to REALbasic, and give little advantage to writing a plugin.
  3. Well, the change is underway. The biggest change that I would want to have is using Cocoa for all of our UI. Luckily, my wish is being worked on. Aside from that, I wish there was a way to get some consistency back in the 0- or 1-based arrays, but we can’t do that without breaking code.

So readers, don’t be shy. Let me hear what your opinions are!

21 Comments »

October 28th 2006

Book: How to Win Friends and Influence People

I have been listening to audio books on the way to work for the past couple months, and I have been wanting to write up reviews of books that I enjoy that are somewhat on-topic for this blog. Luckily, most books I listen to are on-topic. If you do decide to buy a book, purchasing through Amazon by clicking the link below will give some credit back to me, which will help me recouperate some of the cost in hosting this website.

The first book I want to cover is called How to Win Friends & Influence People by Dale Carnegie. This book is a classic, which was originally written in 1936. The topic of this book, however, doesn’t change with time. It touches on the fundamental principles in social interaction, aka “handling people.” Why should you, a programmer, be interested in such a process? Because no matter how much of a recluse you are, you have no doubt at one point needed to get something from someone and had trouble doing it.

Nearly all of the principles are really quite simple and nothing too profound. Some of them you have heard before, and others you may never have thought of. The moment that you hear the principles, they will make sense to you. The way the principles are presented is in a very anecdotal fashion — each principle is accompanied by several real-life experiences of people who employed the techniques and the reactions and results afterwards.

The basic theory is that everyone loves to help out other people, but we often do things or don’t do things to encourage the cooperative nature inside each of us. By employing the teachings of this book, you are able to unlock a power that allows you to influence even the hardest-set minds.

These techniques are not specifically for business, but for life in general. However, the principles carried over to the workplace will help immensely. I haven’t had a situation in need of these techniques, nor have I had a chance to adapt to using these techniques, but the stories used made this book a pleasure to read. Because of the far reaching implications of this book, I recommend it to everyone, no matter what your occupation is.

Comments Off

October 26th 2006

Tracking down bug vubriomt

This is the first post in a new category of mine that I’ll post to when fixing interesting bugs. What is interesting? Well, the ones that make you scratch your head and say, “what the heck would cause that?” I won’t be posting about every bug, and I also won’t be posting any source code. However, hopefully the tidbits shown here will teach everyone about intricacies of certain areas of each operating system (most likely OS X in my case), as well as insights on design flaws or good designs, depending on the situation :) Enjoy!

The bug that I fixed this morning that had me scratching my head was vubriomt. The gist of the bug is that if you use a SaveAsDialog and give it more than 4 types, it will crash. Now this is really odd — in all my years at REAL Software, I have never seen anyone use a fixed size buffer without at least an assert (and even those situations are rare!). I had a glimmer of hope that perhaps that was the bug.

Quite a few crashing bugs are really easy to fix — just run them under the debugger, and when it crashes, you see the offending line. However, this one was crashing in NavCreatePutFileDialog, the Carbon call to create the SaveAsDialog. We simply pass in an options stucture, and it didn’t like part of it.

I track down where we created the options structure, and more specifically the file types list. Nope, no fixed size buffer. We were simply setting it to the result of CFArrayCreate. Next spot to check, assigning the CFStrings. It looked like we could be leaking those (further investigation showed me that we aren’t), and finally, the array creation.

That was it! Someone forgot to multiply the number of elements by sizeof( CFStringRef * ), so we were creating a buffer that was only 5 bytes large instead of 20 bytes. However, why did it only crash after 5 types?

This is the interesting part — on Mac OS X malloc automatically aligns to 16 bytes and pads out allocations to 16-byte offsets. So, when we ask malloc to allocate a buffer of 4 bytes, the buffer returned will actually be 16 bytes long. However, a buffer overrun is a buffer overrun — this is simply an implementation detail that is subject to change. But this explains why the crash happened *after* four types: four types can sufficiently fit into 16 bytes just fine, it’s the fifth type that would overwrite the allocated space.

On Mac OS X, there is an option to use guard malloc to run your application. This slows down your application, but will cause your application to crash as soon as you overwrite your buffer. This would have been my next step if I hadn’t already spotted the error. To do this, you’re going to want to launch your application from the terminal. Try this:

Work-Intel-iMac:~/Desktop jonjohnson$ export DYLD_INSERT_LIBRARIES="/usr/lib/libgmalloc.dylib"
Work-Intel-iMac:~/Desktop jonjohnson$ ./My Application.app/Contents/MacOS/My Application
Allocations will be placed on word (4 byte) boundaries.
- Small buffer overruns may not be noticed.
- Applications using AltiVec instructions may fail.
GuardMalloc-11
Bus error

And now, if we look at the crash log (or run it under GDB since it was the framework crashing), I can see that it crashed where the source of the problem was! This is a good reason to occasionally test your program out while using guard malloc — it may highlight some obscure bugs that you would cause crashes in ways that are hard to believe.

2 Comments »

October 23rd 2006

Finished Painting

Here’s a few before (even before I moved in) and after pictures of my weekend and this evening projects:













Still a few projects left for these two rooms — ceiling fan, mounting a few pictures, burnishing the venetian plaster in the kitchen/dining room, and putting up a tile backsplash.

But now I’m worn out :)

2 Comments »

October 23rd 2006

Good Weekend

Well, I had a pretty good time away from work. I took off Wednesday through Friday, giving me in essence a 5-day weekend. I’m still digging through all the messages piled up in my inbox, so forgive me if yours is one of them.

I purposely didn’t use my computer much except for in the mornings to goof around with the NetFlix challenge. I have a lot of potentially unique ideas on how to solve the problem, and I’ve written up a quick program that takes about one hour to parse the data into a binary format and gather some very simple information in the process, and then on subsequent runs it loads up instantaneously using “mmap”. The entire data set in my binary format still takes up a whopping 1.3 gigs.

I didn’t end up using REALbasic for it though. I started out using the REALSQLDatabase, but to import the records using Insert with an occasional commit took nearly four hours when run. This isn’t a condemnation of the REALSQLDatabase — it’s darn fast. However, a generic database can never see the speed of a custom format that gets highly optimized. The REALSQLDatabase must be able to expand and contract with new and deleted records. My format is set in stone — the test data never changes.

So now with that done, I started implementing my various heuristics, and I’m theoretically ready to take an input of customers and what movies to predict their ratings of. But I guess that will probably wait until tomorrow night.

Alas it is back to me catching up on hundreds of incoming emails, building up my incoming to-do list, and starting to knock those items off the list.

4 Comments »

October 18th 2006

Vacation and NetFlix

My in-laws are in town visiting and I’m taking the rest of the week off to hopefully have a little fun and take a break from work. We’re going to do some fun stuff like go to the riverwalk in San Antonio, visit the Lyndon B. Johnson Library, perhaps see a movie at the Alamo Drafthouse, and eat some good Texas food.

I’m thinking of using my mornings before everyone else gets up to attempt a very fun problem — the NetFlix Challenge. In the background I am downloading their dataset: over 600MB compressed! Ever since I heard the announcement it had been on my mind how I would optimally suggest a movie based on prior ratings, and I wonder how my algorithm compares to CineMatch. I don’t really have high hopes of getting the $1 million prize, but rather I just find these types of algorithmic problems fun to attempt solving.

Has anyone else tried the NetFlix challenge?

2 Comments »

October 17th 2006

bool vs Boolean

This mostly affects plugin authors, but it also does affect any REALbasic users that are writing declares that have structures containing the “bool” datatype.

For plugin authors, you must be careful of what you put in the structure you use to represent your control or class’s data. The sizeof( yourStructure ) must be the same on all platforms because the IDE can only gather information about the one the IDE is able to load. For example, if the sizeof( yourStructure ) on Windows is 72, and on the Mac, it is 86, there will be problems when building on Windows for the Mac because the IDE will tell the compiler that your object is only 72 bytes large, and on the Mac it will promptly overwrite that buffer.

How does this size-mismatch happen? The most common cause is definitely the use of the C-Preprocessor inside of the structure declaration. This is common because on the Mac your control may have an HIViewRef while on Windows it will be an HWND, or you may need extra data on Linux to represent your control. There are two good solutions to this. The first is a little more fragile, which is to simply add padding by adding dummy variables to your structure where needed. The second is the preferred method if you’re writing a C++ plugin: make the structure only contain a pointer to a C++ class that you create in the class/object’s constructor. This allows you to easily use the bridge pattern as well to separate platform-specific logic.

The other cause is less common but harder to debug: Let’s examine this structure:

struct {
  bool mEnabled;
  REALstring mTitle;
};

Now, this structure is the same on Windows, Linux, Classic PEF, Carbon PEF, and Carbon Mach-O i386. However, on Carbon Mach-O PowerPC, the bool datatype is 4 bytes long, as opposed to 1 byte. In this situation, I urge you to use the Boolean datatype. It’s a built-in typedef on the Mac, and the SDK defines it for Windows and Linux. It will be the same on all platforms, which will alleviate these problems.

These small issues may not sound like a huge deal, but buffer overruns can yield endless weird issues, the most obvious being crashes.

Comments Off

October 16th 2006

Why Re-titling the Help Menu No Longer Works

In REALbasic 2006 release 4, we both fixed a bug and introduced a new one. The previous bug was that when adding help books or when running on unreleased versions of operating systems, REALbasic-built applications would have two help menus. The reason is that the OS would provide a help menu automatically, but REALbasic made no attempt to use it and created its own instead.

What is interesting is that we had code to handle this situation on Mac OS 9 because Mac OS 9 automatically had a help menu with the balloon help items. So, my fix was to make us use the OS 9 code on Mac OS X after fixing it up a little bit to behave more nicely.

Unfortunately, between our users adoption of Mac OS X and declining support of Mac OS 9, our users began shipping localized applications, and at runtime would set the text of the Help menu to the localized text. In release 4, this causes an infinite loop.

I fixed the infinite loop for release 5, but we can’t support setting the text of the help menu. The OS will not allow us to set the text, because it will automatically localize itself for you, similar to how Preferences, Quit, and Hide/show behave already. While we could always allow the previous behavior when the OS didn’t automatically provide a help menu, this would cause your application to behave differently on Leopard (based on the features announced in the WWDC keynote) than it does on previous versions of Mac OS X. Since this issue will be an issue for everyone in the future, we decided not to have the two-code paths and always use the system-provided help menu.

The question remains, how do you localize your help menu? Two paths, one more simple than the other:

  • Simplest: add a single dynamic constant to your application with the localizations for each of the languages you are localized for. It doesn’t even need to be used anywhere — just have it in your project.
  • Still simple, but slightly harder: Change your entire project over to dynamic constants. Your application will have all the languages built into the application, and will switch automatically to the preferred langauge of the user.

REALbasic uses the dynamic constants to let the OS know what languages the built application is localized for. When the OS picks the preferred language to present the user with, the intrinsic menu items are automatically localized to this langauge. You now have the best of both worlds: a single download for all languages, and a help menu that changes its title automatically based on the language the user is running under.

Comments Off

Next »