How not to perform encryption

An answer from StackOverflow by a “Senior iOS Developer”:

I just ended up taking two keypairs. One of them I used to encrypt the other one. Then I broke up the encrypted form into many shards and stashed them all over the place… in the cloud… on servers… in obfuscated strings on my app… etc.

None of the strings involved in the encryption or keys is in string or binary format in the compiled app. It is all generated programatically in a quite obfuscated fashion.

At runtime we use arcane math functions to build method names that call hidden methods around the app to assemble the first key, then we go get the encrypted shards of the second key from all over the internet and decrypt them with the first key, then we use the second key to decrypt the important client data.

Then we use a special sauce method where none of the code that’s involved in this obfuscation is anywhere in our repository. It gets loaded in dynamically at a special time. :D That’s all I will say about that.

—and—

I know using someone else’s encrypting software would be faster and easier but this is more fun, plus it can run on my phone. … you are basically saying there are better ways to do it, and I’m just saying mine is not a bad way.

Posted in Uncategorized | Leave a comment

Code Quality



“I honestly didn't think you could even USE emoji in variable names. Or that there were so many different crying ones.”

Posted in Uncategorized | Leave a comment

Open Office

Screen Shot 2015 03 18 at 11 02 59 AM

Posted in Uncategorized | Leave a comment

Offices to Clown Car

Dilbert Clown Car

Headphones are the new office.

Posted in Uncategorized | Leave a comment

Return multiple objects from a method


With the new literals in Xcode 4.4 (and presumably a version for iOS) returning multiple objects from a method becomes almost as easy as in Python. The last example below returns a tuple with very little ceremony in a manner reasonably close to Python. The only thing missing is automatic unboxing into multiple variables.

Below are seven methods running from the oldest form supported bt K&R “C” so true tuple returning supported by the latest LLVM 4.x compiler and Xcode 4.4.

The oldest method is to return the results via reference variables
This method violates Apple coding guidelines that returning results via method references is to be avoided whenever possible.

@implementation ViaReferenceVars

- (void)userName:(NSString **)userName userID:(NSString **)userID {

    // …

    *userName = computedUserName;

    *userID   = computedUserID;

}

- (void)test {

    NSString *userName;

    NSString *userID;

    [self userName:&userName userID:&userID];

    NSLog(@”ViaReferenceVars – name: ‘%@’, userID: ‘%@’”, userName, userID);

}

@end

Return via ivar properties
Pollutes ivar space

@interface ViaIVars ()

@property NSString *userNameProperty;

@property NSString *userIDProperty;

@end

@implementation ViaIVars

- (void)userNameUserID {

    // …

    self.userNameProperty = computedUserName;

    self.userIDProperty   = computedUserID;

}

- (void)test {

    [self userNameUserID];

    NSLog(@”ViaIVars – name: ‘%@’, userID: ‘%@’”, self.userNameProperty, self.userIDProperty);

}

@end

Return via class

@interface DataModel : NSObject

@property NSString *userName;

@property NSString *userID;

@end

@implementation DataModel

@end

@implementation ViaClass

- (DataModel *)userNameUserID {

    // …

    DataModel *nameAndID = [DataModel new];

    nameAndID.userName = computedUserName;

    nameAndID.userID   = computedUserID;

    return nameAndID;

}

- (void)test {

    DataModel *dataModel = [self userNameUserID];

    NSLog(@”ViaClass – name: ‘%@’, userID: ‘%@’”, dataModel.userName, dataModel.userID);

}

@end

Return via class factory

@interface DataModel1 : NSObject

@property NSString *userName;

@property NSString *userID;

+ (id)userName:(NSString *)userName userID:(NSString *)userID;

@end

@implementation DataModel1

+ (id)userName:(NSString *)userName userID:(NSString *)userID {

    DataModel1 *nameAndID = [DataModel1 new];

    nameAndID.userName = userName;

    nameAndID.userID   = userID;

    return nameAndID;

}

@end

@implementation ViaClassFactory

- (DataModel1 *)userNameUserID {

    // …

    return [DataModel1 userName:computedUserName userID:computedUserID];

}

- (void)test {

    DataModel1 *dataModel = [self userNameUserID];

    NSLog(@”ViaClassFactory – name: ‘%@’, userID: ‘%@’”, dataModel.userName, dataModel.userID);

}

@end

Return via dictionary
Meets Apple coding guidelines, messy

@implementation ViaDictionary

- (NSDictionary *)userNameUserID {

// …

    return [NSDictionary dictionaryWithObjectsAndKeys:computedUserName, @"name", computedUserID, @"id", nil];

}

- (void)test {

    NSDictionary *nameAndID = [self userNameUserID];

    NSLog(@”ViaDictionary – name: ‘%@’, userID: ‘%@’”, [nameAndID objectForKey:@"name"], [nameAndID objectForKey:@"id"]);

}

@end

Return via dictionary literals
Meets Apple coding guidelines, neat, concise

@implementation ViaDictionaryLiterals

- (NSDictionary *)userNameUserID {

    // …

    return @{@”name”:computedUserName, @”id”:computedUserID};

}

- (void)test {

    NSDictionary *nameAndID = [self userNameUserID];

    NSLog(@”ViaDictionaryLiterals – name: ‘%@’, userID: ‘%@’”, nameAndID[@"name"], nameAndID[@"id"]);

}

@end

Return via array (new style)
Closest to python style

@implementation ViaArrayLiterals

- (NSArray *)userNameUserID {

    // …

    return @[computedUserName, computedUserID];

}

- (void)test {

    NSArray *nameAndID = [self userNameUserID];

    NSLog(@”ViaArrayLiterals – name: ‘%@’, userID: ‘%@’”, nameAndID[0], nameAndID[1]);

}

@end

Posted in Uncategorized | 3 Comments

Medical costs

A month ago my wife was bitten by a stray cat. A series or Rabies shots was found necessary so we went the hospital for treatment.

The initial treatment was a series of shots followed by subsequents shots at 3, 7, 14 and 28 days.

The hospital billed $18,621 in total, we were amazed when we saw the bills!
The insurance provider paid $6,911 and denied $11,213 which the hospital accepted.
We paid $497 in co-pay.

If we had not had insurance we would have had to pay the full amount of $18,621.

The interesting part is that because we had insurance the hospital accepted $11,213 less than if we had not had insurance. One has to wonder why a person paying out of his own pocket would be expected to pay that much more,over twice as much, for the same treatment.

So, is our medical system broken?

Posted in Uncategorized | 8 Comments

How to make your users hate you

Today I wanted to edit a file on my server. I tend to use Fetch so I fired it up, navigated to my WordPress directory, selected a .php file and clicked on the edit icon. Now I usually use BBEdit so boy was I surprised when it opened in “Ready Lisp”. Wow! I don’t use “Ready Lisp”

I looked through Fetch for an option to set the default editor and could not fine it. I remember that there is sone “funny” non-obvious method to set the editor. Finally I transferred the file to my computer and looked at the Finder Info on the file. Sure enough there is was, Apple had decided that “Ready Lisp” was the default editor for .php files. Huh? OK, in Apple’s infinite wisdom it had set “Ready Lisp” to be the default application for .php files as best as I can figure just because I had installed “Ready Lisp” and tried it once. Bad Apple!

But, just because Apple does something stupid that should not make Fetch do something stupid. Right? Shouldn’t Fetch be able to establish its own file editor associations. It used to be able to but someone at Fetch thought better. Better?

The concept of “Least Surprise” was certainly violated here.

Posted in Uncategorized | 1 Comment

Sort times for NSMutableArray

The impetus behind this sort timing test is from the Coursers “algo” course and in particular the Quicksort section. One comment was that sorting was so fast that the cost need not even be considered. It seem that on an iPad (version 3) sort times of short NSString objects in an NSArray are cheap for approximately n < 10,000.



The NSMutablearray contains unique strings of 8 digits in random order. The sort was statement was:
[ma sortUsingSelector:@selector(caseInsensitiveCompare:)];
where ma is the afore mentioned NSMutablearray.

Times were calculated in 1,2,5 step increments from 10 to 500,000 items on an iPad (version 3).

The three lines on the graph are:
Blue: the time in ms to sort the array
Green: n log(n) for a visual slope reference
Yellow: n^2 for a visual slope reference

It can be seen (and numerically verified) that the sort time is very slightly greater than n log(n). This is in agreement with sort times to be expected from the Quicksort algorithm.

The table below contain the sort times as well a n log(n and n^2 for comparison:

items iPad (3) ms iPhone 3GS ms n log(n) n^2
10 0.104 0.488 1 100
20 0.081 0.161 3 400
50 0.185 0.699 8 2,500
100 0.415 0.814 20 10,000
200 0.948 1.827 46 40,000
500 0.963 5.373 135 250,000
1000 2.963 12.247 300 1,000,000
2000 6.464 27.365 660 4,000,000
5000 14.330 83.051 1,849 25,000,000
10000 41.180 182.578 4,000 100,000,000
20000 196.408 406.931 8,602 400,000,000
50000 565.032 1,140.463 23,495 2,500,000,000
100000 1,244.928 2,487.088 50,000 10,000,000,000
200000 2,703.192 5,396.767 106,021 40,000,000,000
500000 7,476.271 15,125.481 284,949 250,000,000,000
Posted in Uncategorized | 7 Comments

Coursera UX in browser


Notice the size of the “Play/Pause” button relative the the “Previous” button (outlined in red). From this it seems obvious that the more important of the two is the “Previous” button. Also notice the close proximity of the two buttons that have very dissimilar actions.

Typically one actually used the “play/pause”button very often and the “Previous” button only on rare occasions. Additionally the “Previous” button does not indicate what it will go back to.

In practice, particularly on an iPad, when one wants to pause the video to consider the content being presented, unless one is very careful one ends canceling out of the current video and being tossed back to the previous video which will start playing. The user will need to pause the video again, carefully not to be sent back even further. When desiring to resume the user will have to click the “Next” button which will cause the desired video to start playing—but at the beginning. Next the user will have to try and find the approximate place where he was when originally attempting to pause the video in-order to resume.

The solution is really simple, separate the two buttons either vertically or horizontally.

The take-away: The UX designer needs to do two things: 1) Actually try a real usage case himself and 2) Have a new user try the UX, without any prompting, and observer. Of course this may require an iteration of the UX.

Perverse as I am, I can’t wait to bring this up in the upcoming “Human-Computer Interaction” course. :-)

Posted in Uncategorized | 3 Comments

UX in the Large

Sinage video (2 minutes) as great UX, excerpt from the BBC documentary The Tube This is a great example of well thought-out UX policy that is completely focused on the user with an overall benefit to the users as a whole.
Posted in Uncategorized | 1 Comment