Last active
December 26, 2015 18:38
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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 |
It's nothing new really. Yet still come across code that violates these basic principles.
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
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.