Skip to content

Instantly share code, notes, and snippets.

@qnoid
Last active December 26, 2015 18:38
Show Gist options
  • Save qnoid/7195397 to your computer and use it in GitHub Desktop.
Save qnoid/7195397 to your computer and use it in GitHub Desktop.
An example that shows the do's and don't's on a method contract. Summary, DON'T code defensively DO add precondition checks DO add runtime checks DON'T be paranoid
@implementation QNDUnit
- (id)initWithCalculator:(QNDCalculator*) calculator
{
self = [super init];
if (self) {
_calculator = calculator;
}
return self;
}
/**
Divides two positive numbers
@precondition x, y must be positive
@precondition y must be non-zero
@returns a positive number
*/
-(NSNumber*)divide:(NSNumber*)x over:(NSNumber*)y;
{
// 1. Defensive, adds noise. (assuming *there is no way* for x and y to be nil)
// 2. Against the contract
// 3. Propagates issue down the stack
if(x == nil || y == nil){
return nil;
}
//Runtime exception, should never happen. If it does, there is something wrong with how you've wired up your code.
//i.e. called [[QNDUnit alloc] init]
[NSException isNonNil:self.calculator raise:@"calculator cannot be nil" format:nil];
//Preconditions
[NSException isNonZero:y raise:@"x must be positive, got: %d" format:y];
[NSException isPositive:x raise:@"x must be positive, got: %d" format:x];
[NSException isPositive:x raise:@"y must be positive, got: %d" format:x];
NSNumber *result = [self.calculator divide:[x unsignedIntegerValue] over:[y unsignedIntegerValue]];
//Paranoid
[NSException isNegative:result raise:@"http://www.youtube.com/watch?v=NZyVZFJGX5g" format:nil];
return result;
}
@end
@MariusCiocanel
Copy link

This reminds me about what Graham Lee wrote in his book about Design by Contract.
He mentions using NSAssert to make sure the preconditions/postconditions are being met.

@qnoid
Copy link
Author

qnoid commented Oct 28, 2013

It's nothing new really. Yet still come across code that violates these basic principles.

@MariusCiocanel
Copy link

I admit that I don't use this approach very often but I can see the benefit.
At the moment I'm working on proof of concept apps and time to delivery is more important than having elegant code.
Sometimes the proof of concept apps are scheduled to go into production but there is another team that reworks the solution (adding tests, handling all the edge cases etc).

My side projects will have tests and asserts from now on though :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment