Tips for Troubleshooting Your Application

danyowdee edited this page Jul 2, 2012 · 7 revisions

Tips for Troubleshooting Your Application

Admissions and (Gentle) Admonishments

As RestKit grows in functionality and appeal, it gains more users who are rightfully eager to put it to use in their applications. We love new users (and old ones, too). In many ways, RestKit's growth is dependent on the growth of its user base. More new users have new ideas and interesting use-cases, so they make requests which yield many new advancements, features and functions on our TODO list. That's a Good Thing. Yet, RestKit's development must be methodical. Some user demands cannot be met or addressed because it might do greater harm to the framework as a whole, jeopardizing the project development of users elsewhere. In other cases, the requests are so application-specific that only a couple of users would see the benefit of the development effort. If either of these cases describe your situation, this isn't to say you are left out in the cold ... we are thrilled to see so many forks of the framework on GitHub ... it is social development after all. So fork the framework to make it do what you need it to do and then write us to show off your skills!

Lately, we've seen a large number of posts on the RestKit User's Group from folks that are having a difficult time tracking down bugs or complex issues. Some issues are simply due to the fact that RestKit is still under very heavy development. For instance, some behaviors that were recommended 5 months ago are either ill-advised today, or simply don't work at all because the framework has changed so much. With that in mind, some of the posts we've seen lately are developers who were trying to build applications with the latest branch of RestKit while reading through old tutorials, old StackOverflow suggestions, or even old posts in the discussion board. We're working on that these items as we speak. Right now our highest priority is to update the documentation and tutorials (the ones we have control over, at least) to reflect the latest advancements in the RestKit framework and to account for all the changes in Xcode or the new SDKs from Apple.

That said, there are many times that the issues users are running into aren't necessarily a result of dated examples, tutorials, and the like. Rather, they may be related to programmer behavior, development styles, and lack of sufficient testing patterns. I wanted to put together this document, to offer it as a learning tool. I learned a great deal while working through an object mapping / Core Data relationship issue that a user was experiencing on the board. After several posts back and forth within the community, his problem was unsolved and it seemed like it might be a lost cause. The issues were complex and the logs were fairly ambiguous, if not unrevealing. So after a request, he kindly sent me his project hoping that I could assist with the mapping problem. I did assist with the mapping problem, but In the interest of giving him more than he bargained for, I didn't stop there. Taking a lesson from Will Shipley's fabulous Pimp My Code endeavor, I went to work with a constructive critique of his project, which yielded the following notes...

Take No Offense, But Do Take Care

  • Keep a clean project. Ideally, you'll never be in a situation where you need to hand your project off to someone else, but it happens to the best of us, so you want to make it as painless as possible. In the event that you need to send someone an example of your project (for RestKit or otherwise), take some time to make sure you're sending them something they can build and run quickly. If your project is a mess, if they have to spend a few hours amassing all the various submodules and fixing compiler errors, chances are they won't want to help. It's simply not worth their time. Moreover, the chances are extremely remote that you actually need all of that extra stuff to exhibit the problem that's plaguing you. Give them only enough to build and run your app, but give them exactly enough.

  • Stay up to date. To the extent that you need submodules and third party libraries, make sure they're not dated. As I mentioned previously, RestKit is under heavy development and we're always fixing (and occasionally breaking) things. So do try to stay up on the master branch. If you have several compiler warnings (or errors), make sure you address those to the extent that you can before sending off the project.

  • Use the tools Steve gave you. If you are experiencing BAD_ACCESS or other memory related issues, use some of the memory debugging tools that you have available in Xcode, like Zombies. Xcode 4 makes it very easy (once you find it) to turn on and off memory scramblers and retention checkers while debugging your app.

  • Don't force it. Many times you are be trying too hard to do something, but is actually easier once you look around for the convenience methods ... So, instead of writing something like this:

    NSPredicate* predicate = [NSPredicate predicateWithFormat: @"subCatId=%@",subCategory.subCatId];
    NSMutableArray* predicates = [[NSMutableArray alloc] initWithObjects:predicate, nil];
    self.brands= [restKitManager loadObjectsFromDataStoreWithPredicates:predicates andDataObjectAsString:@"KABrand"];
    [self setupIndexDataWithTableItems:brands andDataObject: [KABrand class]];
    [predicates release];

You can boil all that down with this:

    self.brands = [KABrand findByAttribute:@"subCatId" withValue:subCategory.subCatId];
    [self setupIndexDataWithTableItems:brands andDataObject: [KABrand class]];
  • Think small. Really small. I think a large part of the difficulty with debugging some of the projects that are using RestKit is because folks are pulling in a large amount of data in a debug session. It is tough to figure out mapping issues when you have 190MB data streaming through the object mappings. Create a small, but representative set of data to use for testing purposes. If you're trying to figure out the problem with Core Data relationship hydration, create a few flat JSON files that only have a hand full of objects. It drastically cleans up your console logs. Basically, if you can get relationships working on a handful of objects, you can get them working on a million.  But working from the inverse is pretty much impossible.  It's always a great idea to break down your data into a small representative sample for testing purposes.

  • I mean it ... SMALL! It's always hard to debug a detailed process amidst the noise of a large application.  The endeavor to debug/decipher a small issue within a complex application is monumental. For the user's project that prompted my notes was quite large; there were so many things going on in the configuration and functioning of it that it literally took me seven non-stop hours to get to finish line.  Just like you break down your data, you should break down your application when you are running into brick walls debugging.  I've found it immensely helpful to have a very small, limited functionality project that I can use to run through problems with.  In my test project, I've stripped out all the unnecessary UI and overall heft, to get the application down to the bare essentials.  When I've worked out how to handle a problem there, then I can bring over the changes to the main project.  The point is that with so many things happening, it's hard to focus on the little things that are tripping you up. Which brings me to my next point ... maybe you don't need an interactive application at all to find where the problem areas are ...

  • The most important advice I can give ... Seriously, seriously, seriously consider deploying unit tests ... you can even start small there too, plus Apple is making that easier with Xcode 4.  Take one class and start building tests and expectations for it, ... then you can throw in curve balls to see what happens.  For instance, create a table, give it 1 row worth of data, and then ask it how many rows it has.  You'd expect it to be 1, but when your unit test flat out tells you it's 0, you've just saved yourself a few hours of debugger time.  Stuff like that is easy and it pays off in the extreme amount of time you'll save down the road when you start changing things up.  Unit tests make it easier to develop your application, not harder.

  • Increase logging levels There is lots of useful 'debug' and 'trace' level logging in RestKit that you switch on when you need to understand what's going on in inside. For detailed configuration options investigate the Support/RKLog.h file, but to get you started you can add the name 'RKLogLevel.RestKit', and value 'Trace' (without quotes) to the 'Environment Variables' section in the “Arguments” tab of your App’s Xcode scheme, and add the line RKLogConfigureFromEnvironment(); before the call to UIApplicationMain() in you main.m. If you need finer granularity, you can add any number of valid combinations of subsytem-name/log-level pairs for the environment variables…

I hope this helps you as much as it helped me. I'm by no means perfect ... I'm quite guilty of a few errors I've discussed here, but at least this will serve as a reminder and a word of encouragement when it seems like your development cycle has taken a turn for the worse.

Greg