I’ve been toying with Kinect hacks lately which led to my exploring OpenFrameworks. I had a copy on my hard drive from last year when I initially started toying, so today I thought I’d try to pull the latest from git and tinker a bit. I was surprised to learn that there where no Xcode projects for any of the example apps. After stumbling around a bit I found a post in the forum that reveals how you have to build and run the _DeployExamples located at: apps/devApps/_DeployExamples/deployExamples.xcodeproj. If you’re as surprised as I was then hopefully this will clear things for you. Also, note that the default scheme in the Xcode projects happens to be the library. This means that simply pressing the run button won’t do much aside from building the library. You have to manually select the “.app” scheme from the scheme selection drop down if you want any of the projects to do anything. My first attempt at running the “_DeployExamples” app left me puzzled for this very reason. After selecting the application scheme from the scheme selector THEN pressing the run button, I was able to see the app running.
OpenFrameworks – Where are the XCode projects???
Posted in Programming | Tags: C++, OpenFrameworks
Fetch Keychain credentials from Ant
It’s been sooo long since I’ve done any serious Java coding. I thought I would never be back in the doc pages for Ant and Ivy. Alas, here I am, revisiting topics of yesteryear. I was stubbing my toe this morning on our artifact repository which requires manual entry of LDAP credentials and it was hurting a lot! The problem is how our custom version of Ivy does multiple authentication retries when it gets an error which effectively locks you out of the system for 30 minutes the 1st time you enter your password incorrectly. This was as unacceptable as my tacky solution of storing my credentials in a plain-text file on my hard drive. I thought it was high time I did something about my pain.
I thought to myself, “Self…”, (I always refers to myself in the 2nd person speaking on behalf of an undefined third person but using a capital “Self” as the proper noun.) “how come every other application on your Mac is smart enough to use keychain whenever you need to lookup your LDAP credentials? Surely there has to be a modern solute for your problem these days.” A quick Bing search revealed a shell command that I could execute on the command line and output either my user name or my password. The commands were slightly different but sufficient for the Ant exec task after a little massaging. The hardest part was, as always, escaping the quotes and special characters in the command. Here’s my working target which accepts a domain parameter to authenticate against:
<target name="keychain-credentials">
<property name="domain" value="mydomain.com"/>
<property name="uid.cmd">-c 'security find-internet-password -s ${domain} | grep acct | cut -d "\"" -f 4'</property>
<property name="pwd.cmd"><![CDATA[-c 'security 2>&1 >/dev/null find-internet-password -gs ${domain} | cut -d "\"" -f 2']]></property>
<exec executable="sh" osfamily="mac" outputproperty="uid" errorproperty="uid.error" failonerror="false" failifexecutionfails="false">
<arg line="${uid.cmd}"/>
</exec>
<exec executable="sh" osfamily="mac" outputproperty="pwd" errorproperty="pwd.error" failonerror="false" failifexecutionfails="false">
<arg line="${pwd.cmd}"/>
</exec>
<condition property="my.userid" value="${uid}">
<not><equals arg1="${pwd}" arg2="password:" trim="true"/></not>
</condition>
<condition property="my.password" value="${pwd}">
<not><equals arg1="${pwd}" arg2="password:" trim="true"/></not>
</condition>
</target>
Posted in Programming | Tags: ant, keychain, osx
Homecoming
I fired up InetlliJ in my first serious full time effort to develop Java code in several years. I now have a warm, familiar homecoming feeling. You know that feeling you get when returning to your parents house after graduating college or serving time in the military. Things are familiar but foreign. Your room has been converted into a guest room, toys are missing or misplaced, and things that used to seem so big and threatening (your mother for instance) no longer look like such a big deal. You have an overall idea how to get what you want, like dinner, but are intimidated or too ashamed/polite to go for it because it no longer feels like your home. You ask permission for silly things, like lemonade where you used to just barge in the house and yolk the refrigerator door practically off the hinges claw past the milk, grab the juice and guzzle directly from the container after a game of basketball. You ask because the rules may have changed or maybe the lemonade goes with a new medication that your parents are taking or whatever. Everything is off by one, the coffee table never used to sit against the wall that way. The loose door knob that used to jiggle when you turned it is now replaced with a fancy handle opener. The mess behind the shed has been cleaned up. That feeling. Now what happened to “AngryFruitSalad” color scheme?
Posted in Programming
Beware of iPhoto and Adobe Elements Organizer
It’s Wednesday and Finder reports you only have 13GB available on your 512GB SSD. You’ve been installing apps and crap all month in an attempt to ramp up on some new technologies because your role is changing. You also started playing with Photoshop Elements because you fancy yourself a designer in your free time. Hi, I’m Cliff. You’re here because you’re looking for a way to offload a quick 20-40GB worth of video you’d been shooting and saving from your iPhone. I’m here to warn you of a problem you didn’t know you had.
Let’s start with Adobe, because I’m seriously angry with them! If you use any Adobe software regularly then you’ll understand what I mean when I say Adobe has made it their personal mission to inconvenience us all in any and everyday they can possibly imagine! Earlier today I was nagged to upgrade my Flash for the ninety-hundredth-twoth time with a promise that the upgrade will take less than a minute on broadband and that no restart was required. I reluctantly clicked away and agreed to release control of my Mac to the Adobe engineering staff believing the promise that I would once again regain control in under a minute without losing state in my web browsing session. A “.pkg” file downloaded while the upgrade process began. launching the “.pkg” ran an installer that stopped and told me right away that I must close Safari before it could continue. Let down and lied to, I closed Safari thanked my lucky stars that I am running Lion and all my state is automatically saved these days. I digress
What I really wanted to warn you about was Adobe’s Photoshop Elements Organizer. I made the mistake of importing my iPhotos Library thinking that in this day and age Adobe’s engineers would know enough that it’s not polite to clone the contents of a +50GB photo library. Even if the price of hard disk space is near single digit dollar amounts capacity typically tops off in the .5-1TB range and SSD is becoming popular resetting these limits to their early 2000 ranges. Also, some folks like to split their hard drive in half running two operating systems side by side. Finally, it’s just not a nice thing to do without at least warning your user, “Hey are you sure you want to clone 50GB worth of data just so you can use our software extension which doesn’t do half the work already available in your OS’ pre bundled photo viewer?” “Import…” should at least be properly re-labeled “Copy files in from…” I kind of figured the software was too dumb to use pointers or symbolic links and copy on demand but some part of me just held out hope that things have matured further in 2012.
On a slightly related note, I was looking to move a bunch of videos of my daughter playing Basketball I’d been filming over the last few months to a backup drive to free up drive space (claimed impolitely by Adobe). That’s when I remembered how Apple loves to mutate its popular software titles like iPhoto by constantly tucking familiar options away in new and exciting places. Looking for “Right-click and Reveal in Finder”? Surprise! It’s now in the File menu! Don’t try looking in the more logical info view that we trained you to resort to when you want to find the actual file path. We know you’re too smart for us so now we’ve changed it again! I also learned today that the contents of your photo library are not indexed by spotlight! That means the only way to locate the basketball movie from 3 months ago that is so adequately named “IMG_0081.mov” is to bring up the info view in iPhoto, pencil the name down on a piece of scrap paper, then manually drill into your photo library in Finder diving in and out of each folder until you stumble across something that looks close enough. Copy/paste this file to a backup drive and repeat the process for the seven hundred ninety two remaining files you wish to backup. Finally realize several years later that you copied “IMG_0018.mov” and deleted “IMG_0081.mov”!
I’m just utterly irritated with software in general. There was a time when I used to marvel at computers and programs and programming computers. Now after working in a couple of big name companies and seeing how things are actually cooked up I get depressed. I completely understand how these magical collections of ones and zeroes come into existence and why certain compromises are made leading to issues like what I am facing. I thought I was going somewhere with today’s post but I think I spiraled off somewhere partway in. If you write software for a living then you deserved to be punched in the arm today. If you know someone who writes software for a living, punch them in the arm because… well just because Spotlight can’t find my movie files. I also hold every software engineer personally responsible for Adobe’s everyday upgrade prompts that are now promising not to disturb your work but bringing your systems down anyway. It’s your fault, with your passion for automatic upgrades that magically pull down your corrections from the cloud and constantly disturb end users! If you can understand what’s written in my header f… my banner picture above then I break-wind in your general direction.
Posted in Programming | Tags: rant
How Many Emcees Must Get Dissed…?
So you’re a programmer?
Yes, yes, yes, yes, yes…
I code very deeply…
In about 4 seconds, a teacher will begin to speak
I code very deeply…
Hi, I’m Cliff. You’re here because you wish to know the answer to the age old question, a question that has been asked by many different people over the ages. (Yes some even asked this very question on Yahoo.) This question is generally understood to be it’s own answer. However, in today’s discussion we will revisit the question in code using test driven design as a unique experiment uncover the answer.
Before we begin, some elaboration is in order for those who do not have a background in heavy beats and sentences terminated by rhyming vocabulary. The question we must ask and answer is, “How many emcees must get dissed before somebody says don’t mess with Cliff?” (Astute readers will note that I am paraphrasing slightly from the original.) We ask this question because over the years there have been many emcees who have had their egos reduces to nothing merely because they didn’t understand the exact count or quantitative answer. “Is it 10, or 11? Was my number twelve? Oh, I lost my ticket!”, they would say on their way towards total annihilation. “What is an emcee?”, you ask. It is the phonetic spelling of one MC which (as Queen Latifah explains) is short for “Microphone Commando”. I digress…
So we begin with an iPhone Xcode 4.2 project which will generate an iOS 5.0 static library. Our end result will be a static library which will be able to be linked to any iPhone app that wishes to provide an answer to this very question. Please open you copy of Xcode and follow along. I named my Project “HowManyEmcees” and created it as a static lib project sacked in my “dev” folder. (Feel free to save your project where ever you see fit.) Make sure you have the “Include UnitTests” checkbox marked and also check the “Create a local git repository” option to enable source control. For some it will be difficult but it’s very important that you follow each step exactly. The idea is to recondition yourself from writing code before you know why you’re writing code. Our first test will be as follows.
//
// HowManyEmceesTests.m
// HowManyEmceesTests
//
// Created by Clifton Craig on 12/27/11.
// Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//
#import
#import "EmceeWarehouse.h"
@interface HowManyEmceesTests : SenTestCase
@end
@implementation HowManyEmceesTests
- (void)setUp
{
[super setUp];
// Set-up code here.
}
- (void)tearDown
{
// Tear-down code here.
[super tearDown];
}
- (void)testCanGenerateListOfEmcees
{
}
@end
We start by declaring the need for an “EmceeWarehouse” and beginning a test case that will eventually demonstrate how we get a list of Emcees from the EmceeWarehouse. That said, you can expect a warehouse full of emcees to get dissed in our example. Let’s continue with typical memory management etiquette assigning the warehouse in our setUp and clearing it in our teardown. (I could skip this step if I were to use the new iOS 5.0 ARC features but let’s keep things familiar and not introduce too much at once here.)
@interface HowManyEmceesTests : SenTestCase
@property (nonatomic, retain) EmceeWarehouse *emceeWarehouse;
@end
@implementation HowManyEmceesTests
@synthesize emceeWarehouse;
- (void)setUp
{
[super setUp];
self.emceeWarehouse = [[EmceeWarehouse alloc] init];
}
- (void)tearDown
{
self.emceeWarehouse = nil;
[super tearDown];
}
Now we hit Cmd+U, compile, crash, and understand that we need to actually have an EmceeWarehouse. It is very important that you compile at this point and verify all of the compile errors. If you are not getting compile errors then it is likely that you have not resisted the urge to correct the red flags in your editor as you went ahead and implemented the code before writing your test. If you don’t have errors, go back and delete your premature EmceeWareHouse, compile and crash. After crashing on compile create a plain old Obj-C object named EmceeWarehouse and add it only to the library (not the test) target. Compile, run (Cmd+U) and get your first green bar or passing test suite. (Why doesn’t Xcode unit testing feature green bars?) Back in our test method we express our intentions. This is the fun part because we can be as creative as we wish. I like to think of it as programming with the most dynamic language on the planet because you can change the way methods work as you write them without the penalty of recompiling or bug fixing. You’ll see what I mean in a moment.
- (void)testCanGenerateListOfEmcees
{
id manyEmcees = [self.emceeWarehouse listOfEmcees];
STAssertTrue([[manyEmcees class] isSubclassOfClass:[NSArray class]],
@"Expecting an instance of NSArray but got %@", [[manyEmcees class] description]);
}
Add the logic above to your test and compile, run and crash. If you didn’t crash you jumped ahead again. Delete your listOfEmcees implementation in “EmceeWarehouse.m” and start over. Note that the amount of code you delete and add later is directly proportional to the amount of unnecessary code found in projects that do not use TDD. As we iterate between test and code we are looking for the simplest thing that works which is the barest amount of code that can satisfy the most recent test, anything more will absolutely degrade the quality of your project. This will make more sense after a few iterations. Let’s look back at our test. It doesn’t quite fit what we are after. We are looking to get many different emcees from the warehouse, possibly all with varying skill levels. Lets change the test to make it more indicative of that.
- (void)testCanAskForManyDifferentEmcees
{
id manyDifferentEmcees = [self.emceeWarehouse manyDifferentEmcees];
STAssertTrue([[manyDifferentEmcees class] isSubclassOfClass:[NSArray class]],
@"Expecting an instance of NSArray but got %@", [[manyDifferentEmcees class] description]);
}
This contrived example illustrates an important point. Making changes to your tests should cost little if anything which highlights another valuable concept. Making changes to your product’s requirements should cost very little. In TDD, a test should be the direct result of a discussion of some product requirement and should closely follow or even echo a given requirement. Requirements change frequently because they cannot be completely understood until your product ages a little, so formalizing the requirements in test code is important. Also, if you are being penalized for changing your requirements then you will be less likely to make the necessary changes in your requirements thus suffocating your product. Now lets implement our warehouse just a little.
// EmceeWarehouse.h
#import
@interface EmceeWarehouse : NSObject
-(id) manyDifferentEmcees;
@end
// EmceeWarehouse.m
#import "EmceeWarehouse.h"
@implementation EmceeWarehouse
-(id)manyDifferentEmcees
{
return nil;
}
@end
Cmd+U and crash! It’s like stumbling through a dark room with your hands extended reaching for the wall or nearby objects. We want to carefully approach our optimal solution without stepping passed it. The less code we use to solve a problem or requirement, the more power/flexibility we have to change existing requirements or add new ones. We need to make one minor change in “EmceeWarehouse.m” before we can move on.
-(id)manyDifferentEmcees
{
return [NSArray array];
}
Now that we pass we can commit. Committing after every passing test is a good idea because it leaves a nice audit trail of how you grew your solution. One thing to note now is the return type of our method. Even though our test eventually compared the manyDifferentEmcees to an NSArray we didn’t formalize the return type in the method declaration. That optimization must be done after we go over the test a few times and get our initial pass because it allows us the time to mentally settle on the appropriate types. Once again, the barest amount of code to satisfy the requirement is what’s important. Then you go back and refine the requirements and finally the implementation. Looking back at our test we can ask ourselves, do we really want an NSArray or should it be an NSSet? Should we try to use an NSMutableArray? We’ll stay with NSArray since we probably want to go through emcees in a predictable order and also since each emcee will probably want to listen to the one before him. We’ll forgo the use of NSMutableArray externally because we don’t have a need to change the order or members of the array. That decision is difficult for some people because, as engineers, we like to expound on what we believe the optimal solution to be rather than allowing proper iteration to guide us. That is, we love to make those “experienced educated guesses” at what would most likely solve the problem. Making such assumptions (corruptions) is the actual equivalent of writing bugs into your software or pouring salt into the open wound. Let’s make the NSArray return type formal at this point run our tests to make sure they still pass and commit.
// EmceeWarehouse.h
#import
@interface EmceeWarehouse : NSObject
-(id) manyDifferentEmcees;
@end
// EmceeWarehouse.m
#import "EmceeWarehouse.h"
@implementation EmceeWarehouse
-(id)manyDifferentEmcees
{
return [NSArray array];
}
@end
In our next requirement we explore how many emcees we’re prepared to devour. Recall above that we merely satisfied the requirement of being able to ask for emcees from the warehouse, now we need to count them and make sure we have enough to prove our street credibility. Pay attention to the fact that we are incrementally exploring what our requirements should be and using that to determine what code to write and how it should look. Add the next test.
-(void)testManyDifferentEmceesShouldIncludeMoreThanOne
{
NSInteger howManyEmcees = [[self.emceeWarehouse manyDifferentEmcees] count];
STAssertTrue(howManyEmcees > 1, @"Should have more than 1 emcee to prove street credibility. we count %i", howManyEmcees);
}
Compile, test, fail and fix the implementation to the simplest thing that works.
-(NSArray*)manyDifferentEmcees
{
return [NSArray arrayWithObjects:@"This is not and Emcee",
@"and neither is this",
nil];
}
I like to push the needle towards stoopid sometimes as I add code that is obviously wrong. The point here is to force yourself to write the tests (or the “requirements” as I like to think of them) to expose the obviously wrong or missing code. We now have passing tests and an opportunity to commit. Commit the above changes and let’s move on to one of my favorite parts. Now it’s time to define what it means to be an actual “Emcee”. See the next code example.
-(void)testEachOfManyDifferentEmceesShouldBeAnActualEmcee
{
for (id eachEmcee in [self.emceeWarehouse manyDifferentEmcees]) {
//What do we do here???
}
}
A heavy-handed approach would be to compare eachEmcee class against an actual class named “Emcee”. Since we haven’t thought that far in advance lets try something simple yet not so obvious.
for (id eachEmcee in [self.emceeWarehouse manyDifferentEmcees]) {
STAssertTrue([eachEmcee conformsToProtocol:@protocol(Emcee)],
@"How many emcees wanna be emcees? Never be emcees. Cause they can't emcee!");
}
Protocols are mere abstractions that don’t need an implementation (similar to Java interfaces) and they are simple enough to allow us to specify our intention while allowing us to move on with developing the warehouse. I hit Cmd+U (you should too) after even the most minute source changes. It is a means of giving you instant feedback of what you did as well as how what you just did impacts the overall project. Our compiler (and our editor both) tells us we need to define the Emcee protocol. Now, towards the top of “EmceeWarehouse.h” add:
@protocol Emcee @end
Cmd+U exposes the silly behavior in our warehouse. We need something that represents a real emcee so we’ll add the simplest thing that works. Put thins anywhere in your project (I included it at the bottom of “EmceeWarehouse.m”) to allow our test to pass:
@interface NSString(Emcee) @end @implementation NSString(Emcee) @end
This is a category used only from within EmceeWarehouse.m so it does not need to have separate “.m” and “.h” files. I also like to patch up my implementation to reflect the new change:
-(NSArray*)manyDifferentEmcees
{
return [NSArray arrayWithObjects:@"I wanna be an Emcee!",
@"Now I'm an Emcee!",
nil];
}
As you can see, right now it doesn’t take much to be an emcee. Make sure you commit your changes before moving on. Let’s make our warehouse just a little more interesting by including a capacity and making sure it’s always full to capacity.
HowManyEmceesTests.m
@interface HowManyEmceesTests : SenTestCase
@property (nonatomic, retain) EmceeWarehouse *emceeWarehouse;
@property (nonatomic, assign) NSInteger warehouseCapacity;
@end
@implementation HowManyEmceesTests
@synthesize emceeWarehouse;
@synthesize warehouseCapacity;
- (void)setUp
{
[super setUp];
self.warehouseCapacity = 100;
self.emceeWarehouse = [[EmceeWarehouse alloc] initWithCapacity:self.warehouseCapacity];
}
Cmd+U crash with unrecognized selector “initWithCapacity:” sent to instance.
EmceeWarehouse.h
@interface EmceeWarehouse : NSObject - (id)initWithCapacity:(NSInteger)aCapacity; -(NSArray*) manyDifferentEmcees; @end
EmceeWarehouse.m
- (id)initWithCapacity:(NSInteger)aCapacity /*we don't wanna do anything with the capacity yet!!!*/
{
self = [super init];
if (self) {
//don't touch this part yet!!!
}
return self;
}
Cmd+U, pass, commit! Now we need to make sure we’re always full to capacity.
HowManyEmceesTests.m
-(void)testWarehouseIsFullToCapacity
{
STAssertEquals((NSInteger)[[self.emceeWarehouse manyDifferentEmcees] count], self.warehouseCapacity,
@"EmceeWarehaouse should be full to warehouseCapacity");
}
Cmd+U fail, and fix:
EmceeWarehouse.h
@interface EmceeWarehouse : NSObject - (id)initWithCapacity:(NSInteger)aCapacity; -(NSArray*) manyDifferentEmcees; @property(nonatomic, assign) NSInteger capacity; @end
EmceeWarehouse.m
@implementation EmceeWarehouse
@synthesize capacity;
- (id)initWithCapacity:(NSInteger)aCapacity
{
self = [super init];
if (self) {
self.capacity = aCapacity;
}
return self;
}
-(NSArray*)manyDifferentEmcees
{
NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
for (int countOfEmcees = 0; countOfEmcees < self.capacity; countOfEmcees++) {
[soManyDifferentEmcees addObject:@"I wanna be an emcee!!"];
}
return soManyDifferentEmcees;
}
@end
Now when you have so many different emcees there’s bound to be a sucka in the mix! To be specific, a sucka emcee is the one that will cop out in the midst of a challenge. He’s the one that has no heart and is afraid to battle- the one emcee that’ll say “Don’t mess with Cliff”, thus terminating what eventually become an infinite loop, or never ending round of battles. Many people don’t understand what exactly does it mean to be an emcee. Our next round of tests will explain it very clearly. At the very bottom of “HowmanyEmceesTests.m” we’ll add:
#pragma mark - EmceeTests
@interface EmceeTests : SenTestCase
@property (nonatomic, retain) id theEmcee;
@end
@implementation EmceeTests
@synthesize theEmcee;
-(void)setUp
{
[super setUp];
}
-(void)tearDown
{
self.theEmcee = nil;
[super tearDown];
}
@end
It’s more common to use different test case files but for our purposes we can stuff everything in one file. Hit Cmd+U and verify both test case classes show as being executed. (You can commit here as well.) Add our first definition of a real emcee:
HowManyEmceesTests.m
-(void)testAnEmceeCanBeASucka
{
self.theEmcee.isSucka;
}
Cmd+U (after every little change, remember?) forces us to go add a property that will expose the true heart of each emcee, showing if he’s hardcore or not. (Yeah, yeah, I know! Our emcee could be a “she” as well! and she could also be hardcore.) Let’s define that property.
EmceeWarehouse.h
@protocol Emcee @property (nonatomic, readonly) BOOL isSucka; @end
Adding the following to the NSString category in “EmceeWarehouse.m” will eventually give us a warehouse full of sucka emcees:
EmceeWarehouse.h
@implementation NSString(Emcee)
@dynamic isSucka;
-(BOOL)isSucka
{
return YES;
}
Cmd+U, pass and commit. We’re at a point where we should break out two different classes of emcees. Enter ChampionEmcee and SuckaEmcee, both of these will probably extend the base class of Emcee, right? Before we get ahead of ourselves let’s start from the tests since we have some cleanup to do. First create an empty file named EmceeWarehouse.m and cut/paste the following from “HowManyEmceesTests.m” (copy the imports of course but cut everything else):
HowManyEmceesTests.m
#import
#import "EmceeWarehouse.h"
#pragma mark - EmceeTests
@interface EmceeTests : SenTestCase
@property (nonatomic, retain) id theEmcee;
@end
@implementation EmceeTests
@synthesize theEmcee;
-(void)setUp
{
[super setUp];
}
-(void)tearDown
{
self.theEmcee = nil;
[super tearDown];
}
-(void)testAnEmceeCanBeASucka
{
self.theEmcee.isSucka;
}
@end
Commit after verifying that this new test case is associated with the tests target and its tests are still being executed. (In my case I believe it defatted to the test target since that was the active target.) Change #import "EmceeWarehouse.h" to #import "Emcee.h". Compile (Cmd+U), crash, and know that you now need to create and Emcee Objective-C file. Pay attention to how we always use the Cmd+U sequence to let either the compiler or the runtime let us know when we need to add more code. It is a difficult habit to build, breaking out of the “I know I need to do X” mentality. The more frequently you use Cmd+U the more you get used to seeing what doesn’t work while familiarizing with all the different errors that would otherwise confuse you. Add the new “Emcee” class and Cmd+U again to learn that you now need to move the protocol definition out of “EmceeWharehouse.h”.
EmceeWharehouse.h
#import "Emcee.h"
@protocol Emcee
@property (nonatomic, readonly) BOOL isSucka;
@end
Change the setUp to make sure we are exercising the Emcee class:
-(void)setUp
{
self.theEmcee = [[[Emcee alloc] init] autorelease];
[super setUp];
}
Cmd+U will show failure since we never declared/synthesized the isSucka property. Make the Emcee class follow the Emcee protocol and synthesize the isSucka property.
@interface Emcee : NSObject <Emcee> @end @implementation Emcee @synthesize isSucka; @end
Test (Cmd+U), pass and commit. Change the EmceeWarehouse manyDifferentEmcees method to use our new class and remove the ad-hoc category on NSString.
-(id<Emcee>)anyOldEmcee
{
return [[[Emcee alloc] init] autorelease];
}
-(NSArray*)manyDifferentEmcees
{
NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
for (int countOfEmcees = 0; countOfEmcees < self.capacity; countOfEmcees++) {
[soManyDifferentEmcees addObject:[self anyOldEmcee]];
}
return soManyDifferentEmcees;
}
Cmd+U, pass, commit. Now add the following to the bottom of the EmceeTests file:
@interface SuckaEmceeTests : EmceeTests
@end
@implementation SuckaEmceeTests
-(void)setUp
{
[super setUp];
self.theEmcee = [[[SuckaEmcee alloc] init] autorelease];
}
-(void)testASuckaEmceeWillAlwaysBeASucka
{
STAssertTrue(self.theEmcee.isSucka, @"A sucka emcee will always be a sucka!");
}
@end
Hitting Cmd+U makes our toolchain inform us that we need to define a SuckaEmcee:
Emcee.h
@interface SuckaEmcee : Emcee @end
Emcee.m
@implementation SuckaEmcee @end
Hitting Cmd+U once more reminds us that a sucka emcee will always be a sucka. We must code our new class this way.
Emcee.m
@implementation SuckaEmcee
-(BOOL)isSucka
{
return YES;
}
@end
Cmd+U, pass, and commit. Back in our EmceeTests class. We need to make our Emcees spit a lil’ sumn sumn.
-(void)testAnEmceeCanSpitSomething
{
NSString *aLilSumnSumn = [self.theEmcee spitSomething];
STAssertNotNil(aLilSumnSumn, @"aLilSumnSumn should never be nil because that's just not John Blaze. Y'know?");
}
Cmd+U makes us add the following:
@protocol Emcee <NSObject>
@property (nonatomic, readonly) BOOL isSucka;
-(NSString *)spitSomething;
@end
//And in our base class
@implementation Emcee
@synthesize isSucka;
-(NSString *)spitSomething
{
return nil;
}
@end
Cmd+U shows two errors for the one test. This is important to pay attention to since we’ve added the expectation to the base test case for emcee it will apply to all Emcees, even the suckas. Add the simplest thing that works:
-(NSString *)spitSomething
{
return @"I'll battle any sex or any race. You beating me is like Billy Crystal playing Scarface.";
}
That’s not necessarily the simplest thing but it’s colorful enough to get the point across. Now let’s see what happens when one Emcee spits something at another.
-(void)testAnEmceeCanSpitSomethingAtAnother
{
id<Emcee> anotherEmcee = [[[Emcee alloc] init] autorelease];
NSString *aLilSumnSumn = [self.theEmcee spitSomething:anotherEmcee];
STAssertNotNil(aLilSumnSumn, @"aLilSumnSumn should never be nil because that's just not John Blaze. Y'know?");
}
Editor and compiler errors tell us we need to do something, something simple.
-(NSString *)spitSomething:(id<Emcee>)anotherEmcee
{
return nil;
}
Cmd+U runs and shows us where we’re not so John Blaze. A simple fix would be to make the new spitSomething: work like the other.
-(NSString *)spitSomething:(id<Emcee>)anotherEmcee
{
return [self spitSomething];
}
Now we’re going to see an Emcee just getting dissed.
-(void) testAnEmceeJustGotDissed
{
[[[[Emcee alloc] init] autorelease] spitSomething:self.theEmcee];
self.theEmcee.justGotDissed;
}
Cmd+U compile error tells us to add the missing method.
Emcee.h
@protocol Emcee <NSObject> @property (nonatomic, readonly) BOOL isSucka; @property (nonatomic, assign) BOOL justGotDissed;
Emcee.m
@implementation Emcee @synthesize isSucka; @synthesize justGotDissed;
Now add our expectation to our test case.
-(void) testAnEmceeJustGotDissed
{
[[[[Emcee alloc] init] autorelease] spitSomething:self.theEmcee];
STAssertTrue(self.theEmcee.justGotDissed, @"The Emcee just got dissed. Property check should confirm this.");
}
The simplest solution:
-(BOOL)justGotDissed
{
return YES;
}
Of course it shouldn’t make sense. We want to write another test that explains why tour current solution is less than optimal:
-(void)testAnEmceeDidNotJustGetDissed
{
STAssertFalse(self.theEmcee.justGotDissed, @"Nobody spit anything at the emcee. He did not just get dissed");
}
All along we are adding documentation along side our new software components. This is the best kind of documentation because it is executable and always up to date. When something breaks we have documentation explaining how we expect things to work and where the breakage is. Removing the formal definition from our implementation will cause it to fall back on the synthesized definition which will always return NO when we asked if we just got dissed. That will fix our latest test but break our earlier test. We are forced to change the state of the other emcee as we spit something at another emcee.
-(NSString *)spitSomething:(id<Emcee>)anotherEmcee
{
anotherEmcee.justGotDissed = YES;
return [self spitSomething];
}
//Remove/delete this...
//-(BOOL)justGotDissed
//{
// return NO;
//}
Cmd+U to validate our above changes then feel free to delete the commented code. Cmd+U can be used to confirm our refactoring did not alter behavior prior to commiting. Congratulations! We have demonstrated how an emcee just got dissed. We’re almost there! A couple more changes are in order. First we need to elaborate on the SuckaEmcee. You see, a SuckaEmcee should say “Don’t mess with Cliff!” after he just got dissed because he’s soft. We need to add a test to document and demonstrate the idea. At the bottom of EmceeTests.m inside our SuckEmceeTests add the following:
EmceeTests.m
-(void) testASuckaEmceeJustGotDissed
{
[[[[Emcee alloc] init] autorelease] spitSomething:self.theEmcee];
STAssertEqualObjects([self.theEmcee spitSomething], @"Don't mess with Cliff!",
@"We expect the SuckaEmcee to be soft and tell others 'Don't mess with Cliff'.");
}
Notice how we really don’t need comments to explain what’s happening. Our expectations are inlined as code and our logic echoes our use cases. We can use the simplest thing that works here. At the bottom of Emcee.m in the @implementation for SuckaEmcee, we add this:
-(NSString *)spitSomething
{
return @"Don't mess with Cliff!";
}
The SuckaEmcee feels slightly incomplete. We want our sucka to try to spit lil’ something on occasion, because he is an Emcee after all. The best way to demonstrate this is in our definition of an Emcee in the EmceeTests. We add a new test.
-(void) testAnEmceeWhoHasNotJustGotDissedWillNotShowFear
{
STAssertFalse(self.theEmcee.justGotDissed, @"Given an Emcee that has not yet been dissed...(sanity check.)");
STAssertFalse([[self.theEmcee spitSomething] isEqualToString:@"Don't mess with Cliff!"],
@"Any emcee will try to spit something before being dissed.");
}
Our test is showing us how our SuckaEmcee is not really behaving as an Emcee should. In plain slanglish, our current emcee is always punking out. We have to fix this since our sucka has “Emcee” in it’s class name and in it’s class hierarchy. In our SuckaEmcee @implementation we make it try to spit something before getting dissed:
-(NSString *)spitSomething
{
if (self.justGotDissed) {
return @"Don't mess with Cliff!";
} else {
return [super spitSomething];
}
}
Cmd+U pass, and commit. Now there’s still an issue with the each Emcee in our EmceeWarehouse. Among every group of Emcees you’re bound to find a sucka. Lets add one more test to our HowManyEmceesTests to make sure.
-(void)testThereShouldBeASuckaEmceeInTheWarehouse
{
NSUInteger locationOfSucka = [[self.emceeWarehouse manyDifferentEmcees] indexOfObjectPassingTest:^BOOL(id eachEmcee, NSUInteger eachIndex, BOOL *stop){
return eachEmcee.isSucka;
}];
STAssertFalse(locationOfSucka == NSNotFound,@"Location of our SuckaEmcee should NOT be NotFound.");
}
Cmd+U and we see a new but expected failure from the assert we just coded. We need to change the implementation of our manyDifferentEmcees method using the most simplest approach:
-(NSArray*)manyDifferentEmcees
{
NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
for (int countOfEmcees = 0; countOfEmcees < self.capacity; countOfEmcees++) {
[soManyDifferentEmcees addObject:[self anyOldEmcee]];
}
[soManyDifferentEmcees addObject:[[[SuckaEmcee alloc] init] autorelease]]; //tack on a SuckaEmcee
return soManyDifferentEmcees;
}
Cmd+U and guess what? We fixed our test and broke another. Our TestCases just deposited a few dollars into our development account! Our test, testWarehouseIsFullToCapacity, complains that our warehouse must be flu to capacity. We cannot just add a sucka on the end because he won't fit. For now we just tweak the manyDifferentEmcees method once again to make room.
-(NSArray*)manyDifferentEmcees
{
NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
for (int countOfEmcees = 0; countOfEmcees < self.capacity - 1/* Leave room for desert, the last Emcee is gonna get ate!*/; countOfEmcees++) {
[soManyDifferentEmcees addObject:[self anyOldEmcee]];
}
[soManyDifferentEmcees addObject:[[[SuckaEmcee alloc] init] autorelease]]; //tack on a SuckaEmcee
return soManyDifferentEmcees;
}
At this point we've built enough infrastructure to answer our original question but this solution is a little boring and completely predictable since we always fill our warehouse with a sucka on the end. We have tests to cover our next move, refactor! We want to take a different approach to making sure there's a sucka emcee in the crowd. First restore our manyDifferentEmcees method to it's original form. Revert the EmceeWarehouse.m file so it looks like this:
-(NSArray*)manyDifferentEmcees
{
NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
for (int countOfEmcees = 0; countOfEmcees < self.capacity; countOfEmcees++) {
[soManyDifferentEmcees addObject:[self anyOldEmcee]];
}
return soManyDifferentEmcees;
}
Cmd+U and fail on the original assert failure. Next we change the anyOldEmcee method to return either an Emcee or a sucka based on a random value:
-(id)anyOldEmcee
{
if ((arc4random() % 100) > 95) {
return [[[SuckaEmcee alloc] init] autorelease];
} else {
return [[[Emcee alloc] init] autorelease];
}
}
That should give us a rough distribution of 5% sucka Emcees in our warehouse. We can adjust the percentage to our liking as our needs mature. For now this will do. Our last bit of code is intended to test each emcee. Create the following test case:
-(void)testHowManyEmceesMustGetDissed
{
id cliff = [[[Emcee alloc] init] autorelease];
NSUInteger locationOfEmceeThatJustGotDissed = [[self.emceeWarehouse manyDifferentEmcees] indexOfObjectPassingTest:^BOOL(id eachEmcee, NSUInteger eachIndex, BOOL *stop){
[cliff spitSomething:eachEmcee];
*stop = [[eachEmcee spitSomething] isEqualToString:@"Don't mess with Cliff!"];
return *stop;
}];
STAssertEquals(locationOfEmceeThatJustGotDissed, (NSUInteger)0,@"%i emcees just got dissed", locationOfEmceeThatJustGotDissed + 1);
}
You may want to run this test more than once. It illustrates an important technique I often use when doing TDD. It’s what I call the discovery test. Whenever I have an API call that produces an unknown (or in this case variable) value that I want to discover, I write a failing test which outputs the value of the API call as part of the assert description. In the above example we finally discover how many emcees just got dissed, before somebody says, “don’t mess with Cliff!” I leave you to mull over it for a while. Leave comments if you will. G’night.
Computer Status – Potentially Unprotected
One of the primary reasons you would want to avoid naming your product something like “System Center 2012 Endpoint Protection” is the sheer confusion that would result from any dialog that it spawns.
Hi, I’m Cliff. You’re here because you didn’t know that virus and spyware definitions are files that “System Center Endpoint Protection” uses to identify malicious or potentially unwanted software on your computer. I’m here because I’m just as surprised as you.
Imagine, if you will, that we have an average user attempting to complete a computing task. Let’s just say they need to log into a company internal site where they can post a daily status report. Let’s now pretend that your son, who you chose for no particular reason to name ”System Center Endpoint Protection”, decides to interject his personal knowledge of malware and virus definitions at the precise moment the task was to begin. Our user navigates their pointer to the blue “E” icon, clicks once in an attempt to initiate the all too familiar double click event to begin the internet related task when your son slams the door open. He spontaneously begins to inform our user not only that the virus and spyware definitions are up to date but goes on to detail the exact time and date the definitions were created along with the time/date they were last checked and the versions of each. Because your son suffers from slight autism he refers to himself in the third person when he speaks. Detailed as your son tends to be, he goes on for a period of about 5-10 minutes all the while holding up the internet related task that was about to commence moments earlier. At the conclusion of his speech, he stands there grinning with achievement and a fist anchored to each hip.
Startled and confused, our user is eventually able to post the status report while Mr. Fists-On-Hips continues grinning and beaming, but not before doing one or two double-takes. I imagine such an awkward experience to be somewhat similar to my recent virus/spyware definition update on March 6th.
Posted in Programming | Tags: bad dialog design, how not to design your software
Are you sure you wanna do that?
I’m clearing my dev iPhone from a bunch of apps that accidentally got sync’ed onto it when I see the funniest warning I’ve seen in a while.
“Are you sure you want to remove 116 apps, including ‘Ace Casino’, from the iPhone “My Development iPhone”? This will delete these apps and their data from the iPhone.”
Are you kidding me? Including “Ace Casino”? Absolutely not! I only intended to delete 115 apps… because… I’m sort of a card shark! I walk away thanking my lucky stars that the brilliant minds in Cupertino were wise enough to remind me of my gambling addiction before I made such a disastrous mistake! Hi, I’m Cliff. You’re here because you recently removed Ace Casino from your development iOS device. I’m here to tell you it’s ok. The app is freely available in the app store- a mere few taps away. Now blow your nose, say thank you, and tip your psychologist on the way out.
Posted in Programming
Bing for a week…
It’s amazing how much I really don’t notice the difference after my Bing for a week trial! I actually get better results in some searches. Well better is subjective, but I did get different results which turned out to be things I was actually looking for. I’ll admit, I cheated once or twice! That’s only because I had a couple of site specific searches I needed to do mid week and I was too lazy to figure out if/how you could do a site search on Bing. Hi, I’m Cliff. You’re here because you needed some random explanation as to why you stumbled across such a dumb blog. I’m here because I tend to give random nonsense explanations to people who find my site on accident. I’m also here because I had a thirst for red flavored water diluted with pure cane sugar over a week ago and now I need to report my status.
So after a week of no Google search (or mostly Bing search) I am comfortable admitting that I don’t feel the need to switch back. After their privacy policy change last week I’m not sure I’ll ever switch back. (I’m even considering dropping Gmail in favor of my Windows Live Hotmail. I never thought I’d see the day when I’d prefer Hotmail over GMail but there you go.) The first couple of days I felt a little anxiety not having the name “Google” watermarked in Safari’s search bar but that was merely a psychological issue. After 48 hours passed I didn’t even realize I was using Bing. I went on looking up sites, Lua tutorials, exceptions and error messages like had been doing days before and was never disappointed. It was similar but no where near as disastrous/expensive as my switch to Linux many years ago.
The Bing app on iOS further enhances searches in a way I can’t really explain. You have to try it to fully understand. It’s almost like the original marketing spin, a decision engine rather than a search engine. It takes only a single tap to find daily shopping deals near by, likewise looking for local movie theater showings is a tap away. I love how they combine mapping with all of the local searches and they even provide weather maps. It’s a one stop shop for all things you’d need to make a decision on. (Now if they only included turn by turn voice guided directions…)
Next steps- Switching my email account is definitely more of an effort than any potential gains would be worth. However, I’d love to switch to using other Microsoft apps. Because of my current employment it wouldn’t make sense to adopt Lync or Windows Live messenger but time may tell a different story here. I will move on to One Note next. (I’ve already switched from Mail.app to using Outlook full time.) That will be interesting because I’m not much of a note taker.
Posted in Programming
Drinking the Kool-Aid
Let’s say you were to take a new job on the other side of the country, specifically to work on some cool iPhone/iPad products under a great brand name. Say you’ve also fell in love with everything and anything metallic brushed looking with light up fruit inscribed on the cover. Now let’s say your employer get’s purchased by the one company who’s technology/products you’ve avoided for half of your career. Hi, I’m Cliff! You’re here because you have a thirst for water with red powered flavoring and pure granulated sugar applied. I’m here because I recently discovered a similar urge and have begun quenching myself with the proverbial powdered water delivered by the happy smiling pitcher that crashes through brick walls but never spills a single drop. (You’d think by the second or third wall he would have at least formed a crack or sprung a leak!)
I was just inspired by another Apple Fan swallowing grape flavored drink in a blog post where he describes many of the unknown miracles you get with software from Redmond these days. I have to admit I am intrigued as I was unaware of what’s been cooking in Microsoft until most recently. I’ve switched one of my iPads to Bing a couple of months ago because I really wanted to give it a chance but I never really do much searching on the iPad so it was a really poor way of experimenting. This time around I plan to do something bigger, much like my original jump from Windows XP to Linux trial-by-fire. I plan to force a new Microsoft product on myself and write a short blog post about my experience. I’d like to do this on a weekly basis but since my plate is already so full I don’t know if I can keep up that pace. Today I’m starting with Bing everywhere. The above blog post has me excited enough about the bing app on iPhone so I’ll start there while also switching my defaults in Safari, Firefox and Chrome. I will live the Bing lifestyle and report back here next week.

Posted in Programming | Tags: Bing, Microsoft, Microsoft apps on iOS, Microsoft apps on OS X
Cross Platform Mobile Development
Just when I thought I reached my peak for number of programming languages I could fit in my skull I get bitten by the Lua bug! Not exactly sure what to make of it at first, I rolled up my sleeves and dug deep to see what the big deal was. Why Lua? Was it yet another language, or could there be something I was missing. Hi, I’m Cliff. You’re here because you thought Lua was one of those ornaments you hang on your neck when going on vacation. I’m here for quite the same reason, only I figured out something more.
I found a product called, Gideros Studio, which is based on Lua technology. It facilitates powerful cross platform mobile development for iOS and Android, allowing you to prototype apps in a mobile agnostic emulator while offering instant deployment to device. Development with Gideros is fast! Apps are pushed to device and launched instantly, much quicker than Xcode, IntelliJ, or Eclipse. What’s more, apps are pushed without wires! So now that I found something extremely useful that could be done with the new programming language I am psyched to push the limits. I’ve been mostly quiet on my blog but more active these days on Stackoverflow with questions and answers as I explore.
Side note
If you are getting an error “attempt to call method ‘getContentWidth’” while trying to follow one of the various tutorials or examples out there note that version 2012 of the studio has recently been released and you should upgrade. Some of the examples were built against a beta of the newer SDK and you will no doubt hit the issue unless you’ve upgraded within the last couple of weeks. Also note that you should rebuild and redeploy the player on your device using the newer SDK to avoid the error.
Posted in Programming | Tags: Android, cross platform mobile development, Gideros Studio, ios, lua


What y’all think about me…