Tuesday, October 9, 2012

Swapping in an SSD for an HDD

Following this blog post and a great SSD from Other World Computing, I was able to install an SSD into my Macbook Pro, giving it new life, boosting its speed and expanding its storage space.  In addition, OWC sells a CD frame replacement in which your old HDD can be installed. This is great, however, it creates a complex situation.  Your HDD needs to be copied to your SSD and that means either going through an external drive (USB case), and that can run slowly, or you can build your Macbook Pro up with the new drive configuration and get it all done at once.

Being a bit adventurous and wishing to make the fewest copies possible, I elected for the latter. Of course, this created more work for me because of some difficulties I ran into, but I learned a little bit about unix drives and UUIDs.

If you're going to change your Mac's HDD to an SSD and move your HDD into the CD drive bay, here's how to do it:

  1. Backup your Computer
  2. Hardware Change
    Follow breakdown and installation instructions for SSD swap for HDD and HDD placement in the CD bay. NOTE: (if most Macbooks are similar) your HDD has two pairs of stubby bolts that hold it in position in the main drive bay. Be sure to remove them and move them to the SSD. Put the HDD into the CD replacement frame and install both the HDD and the SSD.
  3. Boot to Single User Mode
    When you power up the Mac, hold down the Option key until the screen displays a choice of drives from which to boot. Before selecting the drive, hold down COMMAND-S. Continue to hold down CMD-S while selecting the drive. This puts the computer in single user mode and makes the HDD read only. You're about to copy that drive, you don't want a lot of extraneous processes running and modifying the filesystem. Even better, read only prevents changes to the drive. Try running "ps -elf" and you should see only a couple of processes.
  4. Copy the Drive
    Follow the instructions at link above for copying the drive. Note: author makes a comment about not copying empty drive space (0s for HDD v. 1s for SSD being important). I don't know how important this is.
    Be sure you know which drive is which. Most likely, you HDD is /dev/disk1 and your SSD is /dev/disk0. This has everything to do with which hardware SATA link they are connected to and not which drive was used for booting the OS (first, mount the drive, then read it, then boot the OS, so /dev/disk* order is deterministic).
    Copy command looks like: dd if=/dev/disk1 bs=1024 count=### of=/dev/disk0
  5. Change UUID
    At this point, the drive is an exact copy, which creates a problem. If you reboot now, your machine will not work. Both drives look exactly the same to the system because of the shared UUIDs. Using hsf.util, change the UUIDs on the new SSD (there are most likely two of them) before reboot. This program lives in /System/Library/Filesystems/hfs.fs/.
    hsf.util -k rdisk0s2 ## Shows UUID for rdisk0s2, if it has one.
    hsf.util -s rdisk0s2 ## Generates new UUID for rdisk0s2.
  6. Reboot
That's it. You should be done. Leave your machine in this configuration for a week or so until you decide that you're happy with the new hardware configuration and the system feels stable. If you plan carefully and you still have Snow Leopard on your machine, you can leave your HDD with Snow Leopard and install Lion or Mountain Lion on the SSD. Then, you can dual boot your Mac using both drives, with Mountain Lion being your preferred OS and Snow Leopard your occasional.

Why do this? You might have many reasons, like certain applications that work only on Snow Leopard. If you're building OSX ARC applications and you want to debug that ARC app on Snow Leopard, either you need a second machine (running 10.6.8) or you can boot your Macbook off of the second drive.

Good luck with your hardware upgrades.

PS: I also received great help from superuser exchange.

Saturday, April 7, 2012

Don't Write Crappy Apps

(Phone) Application Developer,

Why does the phone screen on your application lock up when I try to type or push a button? Sometimes, I see the spinner, but it won't let me back out of the screen?

It annoys me, so I deleted your application.

Sincerely,

- A. Former Customer

Do your applications do this?

It's a sad state of affairs. I've used plenty of applications on and off the phone. I rarely encounter an app  written with a UI that screams perfection. Most of the time, applications are written with a UI as an after thought, with more concern placed on bug hunting than concern for the humans using the program. I'm not saying bugs shouldn't be hunted down and slain (that's what unit testing is for, really). What I am saying is that the User Interface, and only the User Interface, is what your customers see. It makes the first and last impression.

I've deleted applications from my phone after watching their launch screens, having never seen them run. Why? Really, really lousy UI. If the product development team couldn't take the time to make a good impression on me, to make the experience of using their product a pleasant (if not pleasurable) one, why should I bother with it? They don't care, why should I.

My greatest pet peeve (and one I share with the rest of the population) is far and away a non-responsive phone screen. When I hit a button or touch a keyboard key, the app had better react. I don't mean when the user enters text in a search box that the search results fill immediately. What I do mean is that when the application queries a back end server for data using the first three letters a user typed "myt", it had better not lock when the user wants to hit an "h"! Do the query in the background and make the screen I/O the primary activity.

If you find you have a long running operation that locks up the screen from user input (slow or delayed responsiveness) and you feel the urge to throw up an inactivity display (spinner), STOP, do not do it. Instead, redesign your screen and operation flow to move the computation into the background. You may need to re-architect your entire application, to do this. Yes, that can be a challenge. However, what's the alternative? An application delivered on time that irritates its users just because you didn't want to do the work.

For the record, inactivity spinners are fine things to have in an application. They signal to the user that the application is thinking really, really hard; so hard, it looks stuck. That's the nature of computation devices, it's the phone or computer's way of sticking up a (polite) finger and saying: "Just a moment while I work this out." However, just like a person, devices should be interruptible when a higher priority item comes along. Phone calls can interrupt your application at any time and you don't have a choice about responding to them. It's a good thing, too, because I bet most applications wouldn't bother to release control and using the phone would be a really horrible experience.

Apple's own applications suffer from this. Ironically, the AppStore app is horrible! If I've left the AppStore app on my phone in the "Update" tab, when I go back into the app, it locks up while checking to see if any of my apps need to update. I want to tab over to the search for a new app, but I have to wait for the stupid check (which could be run in the background) to complete before the application responds to my tab selections. Crappy!

On the other hand, the email app does a great job; it has to! Potentially, it has multiple message feeds, multiple message send queues, local data caching, updating of message status, etc. There's no way that application could not run operations in the background. It would be slower than molasses. One of the chief benefits of the phone (quality email on the go) would be unusable. In fact, I would venture to say that without the email application providing such an excellent user experience, the iPhone would never have been able to supplant Blackberry.

A great UI is that important.

So, what should you do? You'll have to do extra work, which means using threads, GCD (Grand Central Dispatch), or NSOperation queues. You'll have to be careful about using Core Data from different threads. You'll have to be careful about running graphics operations on the main thread. You'll have to handle UI operations promptly and never delay a screen update because the data is not ready. You're going to have to design and architect and think! If you don't do those things, you're going to have a crappy application. Your application, your work, says more about you than you realize. It says more about you than about the platform on which it runs. You will be judged, and you may be found wanting.

Don't write crappy apps.

Sunday, April 1, 2012

Core Data Primer for SQL Hackers

"If you have a background in database management ..., don't worry: if you use a SQLite store, Core Data automatically creates the intermediate join table for you."
 - Core Data Programming Guide > Relationships and Fetched Properties > Many-To-Many Relationships
The above opening line should be the first thing said to anyone with SQL experience when they first learn Core Data. A Join Table means Primary and Foreign Keys which means automatic Primary Key creation and management underneath the Data Model. Take a deep breath, relax, and read on.

You've been hacking on iOS, and now you need persistent storage. You know SQL, you want to use SQLite, but everything in xCode and advice from the web recommend Core Data. What do you do?

Core Data, xCode and Cocoa provide an ORM (Object Relational Mapping) that assists developers with mapping stored data into Objective C objects. This powerful tool is at once extremely helpful, incredibly seductive and a bit confining. A judicious use of the provided technology allows for rapid development that nears a finished feel for your application. Yet, if you wish to grab the database connection and perform a complex outer join with a group-by - no dice. At least, not with the information held by Core Data.

In researching Core Data, you'll find a lot of advice telling you that "Core Data is not a Database". Although simple to say, that's not quite correct. Core Data, when used with the xCode Data Model Builder and class generation is a (very convenient) alternative implementation to all of the work a developer would otherwise have to do. You are saved from the need to write client/server code, open cursors, perform partial data reads, create Primary Key/Foreign Key relations, create Primary Key sequence generators (select emp_sequence.nextval from dual;), build Intersection (Join) Tables, link up object graphs, etc.

Be sure to build your Data Model using xCode's modeling tool: File > New > Resource > Data Model. DO NOT CREATE PRIMARY KEYS. xCode creates these automatically when modeling relationships between entities (tables). If you really do need a monotonically increasing sequence generator, try this advice from Apple's Mailing List. If you require Primary Key like behavior, read more about uniqueID, a unique handle to an object (row), from Stack Overflow postings here and here

Inside your program, NSManagedObjectContext provides access to stored data. Use this context to create (insert) objects, fetch (query) objects (full table rows) and properties (columns). The web contains pages of advice for how to use this context. A word of caution - don't make this object a singleton (global variable). Pass it around to the objects that need it. The two most important reasons are (1) the context cannot be used on more than one thread and (2) the context provides rollback capability, so edit screens can be cancelled easily. Read this Stack Overflow Question for some advice.

It turns out that a simple select statement when performed in Core Data requires 13 lines of code! Thanks to Matt Gallagher for this explanation. Look for subsequent posts here that build upon what Matt did.

Matt has also written a great article on the differences between Core Data and a Database. Brent Simmons discusses when it might be appropriate to switch away from Core Data - Spoiler Alert: it rarely is. Derrick compares and contrasts Core Data and SQL. So does Alex in his answer at Stack Overflow.

If you decide you just cannot handle Core Data and want to roll your own solution, there are plenty of middle level APIs to help in your effort. Github holds the source code for FMDB (Flying Meat DB), a SQLite cover, written by Gus Mueller. You could also try Google's SQLite wrapper: Plausible Database.

May your queries by quick and your columns be indexed.

Saturday, March 31, 2012

Adding IVars to Library Classes in Objective C

For a recent project, I needed to add some data to one of the Core Data classes (NSManagedObjectContext) and found Tom Harrington's post regarding a bug work-around he implemented, which required adding a method for freeing a memory block upon class dealloc (a class he didn't control). He details how he creates a Category for NSObject and a separate class to hold an array of deallocators.

I tweaked Tom's approach slightly, to get the following design methodology: Adding IVars to a Class (and it's subclasses). A future post will explain in detail why I needed these extra parameters, but briefly, I want to extend NSManagedObjectContext, a class I do not own, with methods that short cut the work required to build and execute fetching from Core Data. Adding a little bit of state and/or default values to the context (instead of passing that data into/out of the method calls) simplifies matters. Making IVar access transparent eases the burden on the caller. Since I don't own the class definition, I needed another method to associate data and Tom's post pointed the way.

Example Code

CompactFetch.h - Category declaration

@interface NSManagedObjectContext (CompactFetch)
@property (assign,nonatomic) NSUInteger defaultFetchLimit;
@property (retain,nonatomic,readonly) NSError* lastError;
@end

In our header, we create a category, CompactFetch, for NSManagedContext. Notice the two properties created. These property declarations do not use @synthesize for their implementations. The nice thing about making them properties, is that code can use dot-notation to set or get their values. In addition, the code is KVC compliant. Note, you can use objects here, just be careful with assign & retain.

CompactFetch.m - IVar class declaration

@interface CompactFetchIVars : NSObject
@property (assign,nonatomic) NSUInteger defaultFetchLimit;
@property (retain,nonatomic) NSError* lastError;
+ (CompactFetchIVars*)fetch:(NSManagedObjectContext*)moc;
@end

Next, we create a class, CompactFetchIVars, which mirrors the @property declarations on the Category. Again, be sure to match up the assign & retain annotations. Although the property names need not be the same, keeping them that way reduces confusion.

Look at the class method, +fetch:, the heart of our design. It takes an NSManagedObjectContext and returns an instance of our class. We use this class method to attach new ivars (new data) onto the Core Data class. By the way, this @interface resides in the .m file, there's no reason to expose the caller to this detail.

Now, for CompactFetchIVars's class definition:

CompactFetch.m - IVar class definition

@implementation CompactFetchIVars

@synthesize defaultFetchLimit, lastError;

+ (CompactFetchIVars*)fetch:(NSManagedObjectContext*)moc
{
  static void *compactFetchIVarKey = &compactFetchIVarKey;
  CompactFetchIVars *ivars = objc_getAssociatedObject(moc, &compactFetchIVarKey);
  if (ivars == nil) {
    ivars = [[CompactFetchIVars alloc] init];
    objc_setAssociatedObject(moc, &compactFetchIVarKey, ivars, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [ivars release];
  }
  return ivars;
}

- (id)init
{
  self = [super init];
  return self;
}

- (void)dealloc
{
  self.lastError = nil;
  [super dealloc];
}

@end

A typical class definition, we have @synthesize and init/dealloc. Note, -dealloc silently releases lastError through the nil assignment (via the synthesized property).

What's +fetch: up to? objc_getAssociatedObject retrieves an object previously associated with the target class, our NSManagedObjectContext. If this is the first time through, there is no association and nil is returned. In that case, we must create and associate an instance of our class, CompactFetchIVars, with the context. objc_setAssociatedObject performs the association. Note that both the get & set association calls require a key (in this case, compactFetchIVarKey), and despite the documentation, that key need not be a string. The functions use the key's unique location in program memory (assigned by the compiler) to determine uniqueness of the key.

CompactFetch.m - Category definition

@implementation NSManagedObjectContext (CompactFetch)

- (NSUInteger)defaultFetchLimit
{
  return [CompactFetchIVars fetch:self].defaultFetchLimit;
}

- (void)setDefaultFetchLimit:(NSUInteger)limit
{
  [CompactFetchIVars fetch:self].defaultFetchLimit = limit;
}

- (NSError*)lastError
{
  return [CompactFetchIVars fetch:self].lastError;
}

- (void)setLastError:(NSError*)error
{
  [CompactFetchIVars fetch:self].lastError = error;
}
//...

Finally, we implement the get/set methods for the Category we attached to NSManagedObjectContext. In them, we use the +fetch: class method to retrieve (or create, associate and retrieve) the instance of CompactFetchIVars attached to the NSManagedObjectContext. Then, we get or set the parameter, as appropriate. Under the covers, this goes from a method call on the Core Data instance via the Category through to the attached IVar instance. The runtime knows to call -dealloc on both NSManagedObjectContext and CompactFetchIVars, when retain count goes to zero. DO NOT RETAIN a reference from the IVar class to the attached class; any back track should be assign only, or a retain cycle is created and memory leaks.

Friday, March 16, 2012

Trip Report: Salesforce.com's Cloudstock

Cloudstock

On March 15th, I attended Salesforce.com's Cloudstock (& Cloudforce).

First off, Marc Benioff has built an incredible company - for the industry, for their customers and for their employees. I know at least a handle of current and previous employees that have nothing but good things to say about their employer.

As for the event, if you are even remotely involved in High Tech, I would encourage you to attend.  They did a 2.5 hour keynote in the morning that featured C-level employees, customers and, of course, Marc. Marc is inspiring and paints a great picture of where we are in the technological evolution of computing (mainframe, PC, client-server, web, mobile, social). It's not an earth shattering story (if you've been around awhile, you know it), but what is apparent is Salesforce's ability to pivot and take advantage of the last three.

Confession: I left the keynote after 90 minutes, that was enough for me.

Mid-day, the expo floor opened. There were two main sections: Cloudstock and Cloudforce. The former was for developers, so I headed over there. I never did make it to Cloudforce.

One thing that stood out, among many stand out items, was the high quality conversations I had with every person I met at the show.

The Expo

DataSift.com - Far and away, the most impressive product was from DataSift.com. Imagine your company wants to see every social media tweet, post, facebook, yelp, digg, etc. about itself. Furthermore, the data should be tagged and categorized by geo location, sentiment, and whatever else the marketing research department wants. You could build a feed reader for the 30 or so social media platforms and collect the portion of the data they send you (you won't get everything you want). Or, you could go through Data Sift's interface, build a simple query (via GUI or by hand), and have your data feed running in less than a minute. Output is in JSON and easily handled by current tools. Definitely, check them out.

Heroku - Salesforce bought Heroku, recently. Heroku is a cloud platform development platform whose backend runs in AWS. If you like to code in their provided languages (Java, Ruby, PHP), you can use their system "out of the box". If not, you can provide your own libraries for install. They also integrate with Database.com (another Salesforce acquisition). They have a dyno model, in which your system runs. They claimed this provides some higher levels of security. Securing cloud services against back-end attacks should be the chief security concern for every cloud application. I'm skeptical of the level of protection, however, they said a security white paper was forthcoming. Stay tuned.

StackMob - Another backend system, this one dedicated to running your server side operations without having to do any infrastructure work. Basically, think of having to write only the Java classes that respond to GET/POST calls for an Apache Tomcat plug-in with some nice glue into a SQL database. That's StackMob.

Database.com - I didn't speak with these folks at great length, but they have a nice product. Check them out.

Force.com - This is Salesforce's cloud development platform. They've pivoted hard into the social part of the web, leveraging their Chatter application and creating a social media datastream for the Enterprise. There's some great stuff in there that I won't review, you can check out their site. There are, however, some items worthy to note, they have two programming models for handling mobile: an SDK and a hybrid wrapper. The SDK provides calls into the force.com system and is to be integrated into a native application (iOS/Objective-C). The hybrid wrapper uses PhoneGap (below) to wrap HTML/JavaScript.

PhoneGap - These folks provide a shell that wraps HTML and JavaScript web pages. They have developed a JS library to provide native access to phone hardware (camera, GPS, etc.). If you like, you can even build your own native operations and map them to JS calls compiled into the wrapper. The wrapped code gets submitted to the application store. Although I'm a big fan of the mobile web, some applications do best using the mobile platform's look and feel and will continue to be coded in iOS or Java. I think if you're in a hurry, this is a good way to go.

Sencha - These folks have a back end web server that can build for the mobile web browser (HTML5/CSS) or for Desktop browser. I wasn't clear if the browser required a plug-in, but the mobile web pages they showed me looked quite clean. Worth checking them out if you want standard, mobile web browsing.

In the notable mention side, I'd like to put a plug in for Brain Engine and GitHub.

Brain Engine provides an augmented IDE that runs in the cloud and sits atop the Force.com infrastructure. As I have not done a lot of Force.com development, I couldn't tell you if they truly benefit the user, but they seemed convinced and seemed to know what they were talking about. In addition, we discussed a downfall of the Force.com platform, something they are not able to fix, either.

Apparently, Force.com doesn't have a good (or any) source control. All programs are checked into the DB, and there's no branching or merging. That has to be a nightmare for development. Salesforce should address this problem and their users should demand a change.

GitHub - They provide hosted source control and, also, an issue tracker. There are plenty of cloud based source control systems out there. My friend uses GitHub and is quite happy. YMMV.

Finally, an SalesForce architect and I were discussing securing at rest data on the phone and may have found what could a huge security misunderstanding for mobile development work. We are researching the problem and will write a paper, if true. Be on the lookout.

Monday, February 27, 2012

Objective C Explanation

I found the following post at Cocoa Dev an excellent introduction to the Objective-C programming system. It has cleared up quite a bit of confusion regarding accessors, object instantiation and properties.

http://cocoadevcentral.com/d/learn_objectivec/

I now need to find a good explanation of the memory management model (when and how to use garbage collection vs. code level memory mgmt).