SOLID Class Design: The Single Responsibility Principle

November 12th, 2009

This is part one of a five part series about SOLID class design principles by Robert C. Martin. The SOLID principles focus on achieving code that is maintainable, robust, and reusable. In this post, I will discuss the Single Responsibility Principle.

The Single Responsibility Principle (SRP): A class should have one, and only one, reason to change.

Read the rest of this entry »

Why Inline Comments Are Generally a Bad Idea

October 8th, 2009

Bellow is a single function commented in two different ways. Which one is better?

NSString* MD5StringOfString(NSString* inputStr)
{
	//UTF8 encoding is used so the hash can be compared with hashes of ASCII strings
	NSData* inputData = [inputStr dataUsingEncoding:NSUTF8StringEncoding];
 
	unsigned char outputData[CC_MD5_DIGEST_LENGTH];
	CC_MD5([inputData bytes], [inputData length], outputData);
 
	NSMutableString* hashStr = [NSMutableString string];
	int i = 0;
	for (i = 0; i < CC_MD5_DIGEST_LENGTH; ++i)
		[hashStr appendFormat:@"%02x", outputData[i]];
 
	return hashStr;
}
NSString* MD5StringOfString(NSString* inputStr)
{
	//convert the string to UTF8 encoded byte data
	NSData* inputData = [inputStr dataUsingEncoding:NSUTF8StringEncoding];
 
	//calculate the hash
	unsigned char outputData[CC_MD5_DIGEST_LENGTH];
	CC_MD5([inputData bytes], [inputData length], outputData);
 
	//convert hash to a hexadecimal string
	NSMutableString* hashStr = [NSMutableString string];
	int i = 0;
	for (i = 0; i < CC_MD5_DIGEST_LENGTH; ++i)
		[hashStr appendFormat:@"%02x", outputData[i]];
 
	//return the hexadecimal string
	return hashStr;
}

Read the rest of this entry »

Coding Tip: Replace Complicated Conditions With Boolean Variables

October 3rd, 2009

Consider the following if statement:

if(dragOperation != NSDragOperationCopy && NSPointInRect(currentMouseLocation, self.bounds)){
    //do something
}

Even though you may have worked out what the condition represents, it probably took you a little longer than it should. It’s complicated, making it time consuming to read, and prone to bugs upon modification. Thankfully, there is an easy remedy:
Read the rest of this entry »

MD5 Hashes in Cocoa

September 24th, 2009

Let’s jump straight into the code:

#import <commoncrypto /CommonDigest.h>
 
NSString* MD5StringOfString(NSString* inputStr)
{
	NSData* inputData = [inputStr dataUsingEncoding:NSUTF8StringEncoding];
	unsigned char outputData[CC_MD5_DIGEST_LENGTH];
	CC_MD5([inputData bytes], [inputData length], outputData);
 
	NSMutableString* hashStr = [NSMutableString string];
	int i = 0;
	for (i = 0; i < CC_MD5_DIGEST_LENGTH; ++i)
		[hashStr appendFormat:@"%02x", outputData[i]];
 
	return hashStr;
}

Now for the explanation.
Read the rest of this entry »

Coding Tip: Use The Ternary Conditional Operator

September 9th, 2009

The ternary conditional operator (?:) can be used as a short-hand version of an if statement. It is a feature of many languages.

For example, this code:

int height;
if(isTall)
    height = 50;
else
    height = 10;

can be better written as:

int height = isTall ? 50 : 10;

The ?: operator is good for replacing very simple if statements, but is bad for complicated if statements as it can harm readability.

Crack an MD5 hash in less than a second

September 1st, 2009

Here is a common misconception when it comes to password security:

“It’s unsafe store user passwords as plain text in the database, so I’ll MD5 the passwords. MD5 is safe because it is one-way encryption, and takes too long to brute force.”

WRONG!

An unsalted MD5 hash can be cracked in less than a second, because it is vulnerable to a precomputation attack. Don’t believe me? Try it for yourself. There are dozens of websites that will take a hash, and return the original password almost instantly. This is true of all hashing algorithms, not just MD5.

How do you defend against a precomputation attack? You use a salt when computing the hash. Using a large salt makes it infeasible to precompute. Also, it helps if you have a strong password that contains numbers, uppercase letters, lowercase letters, and especially symbols. You get bonus points if your password contains strange characters (unicode characters, ascii characters above 128, etc) because nobody can be bothered precomputing rainbow tables for those.

Implementing Your Own Cocoa Bindings

July 31st, 2009

This post is the result of investigation into a stackoverflow.com question of mine.

So, you’ve created a spiffy NSView of your own, and have decided to make it compatible with bindings. Great! So you go and read the documentation, and you look at mmalc’s GraphicsBindings example. You override bind:toObject:withKeyPath:options: and everything works. But wait! Why isn’t the NSWindowController ever being deallocated anymore?

Now you’ve got a nasty retain cycle on your hands. You do a little research and discover that not only do other people have the same problem, but even Apple’s bindings used to have it a few years ago. How did Apple fix the problem? With the magic, undocumented class NSAutounbinder, which nobody seems to know much about.

Other people will tell you that you don’t need to override bind:toObject:withKeyPath:options: and that bindings work automatically. This is only a half truth. NSObject does provide an implementation of bind:toObject:withKeyPath:options:, but it only half works. Using the default NSObject implementation, changes in the model will update the view, but the reverse is not true. When the bound property of the view changes, nothing happens to the model.

So, what is a Cocoa developer to do? I’ll explain how to implement your own bindings that work exactly like Apple’s, with no retain cycles. I haven’t found this solution anywhere else, so as far as I know, I’m the discoverer. I feel so special. It has been mentioned before at least once. The solution is hard to find, though.

Read the rest of this entry »

Coding Tip: Don’t Mix Abstraction Levels

July 5th, 2009

Can you tell what is wrong with the abstraction in this class interface?

@interface EmployeeList
-(void) addObject:(Employee*)anEmployee;
-(void) removeObject:(Employee*)anEmployee;
-(NSUInteger) numberOfEmployees;
@end

Here is the answer:
Read the rest of this entry »

Coding Tip: Have A Single Exit Point

June 30th, 2009

Having one exit point (return) from a function is a good thing. Here is an example of a single exit point:

int MyArray::indexOfElement(int elementToFind){
	int foundIndex = ELEMENT_NOT_FOUND;
 
	for(int i = 0; i < m_numberOfElements; ++i){
		if(this->elementAtIndex(i) == elementToFind){
			foundIndex = i;
			break;
		}
	}
 
	return foundIndex;
}

Having multiple exit points can be bad. Here is an example of multiple exit points:

int MyArray::indexOfElement(int elementToFind){
	for(int i = 0; i < m_numberOfElements; ++i){
		if(this->elementAtIndex(i) == elementToFind){
			return i;
		}
	}
 
	return ELEMENT_NOT_FOUND;
}

Why are multiple exit points bad? Because I say so. They are also bad for these two reasons:

Read the rest of this entry »

Model View Controller Mechanisms

June 7th, 2009

The previous article, Model View Controller Explained, explained what MVC is and why it’s such a good design pattern. The model view controller design pattern has a flow. Actions flow from the view to the model via certain pathways. Conversely, changes to the model flow through to the view. This article will dive into finer detail about these pathways, and discuss some of the specific mechanisms and design patterns used to implement the flows.
Read the rest of this entry »