Coding Tip: Don’t Mix Abstraction Levels

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:

“addObject” and “removeObject” should be named “addEmployee” and “removeEmployee”

Why? Because EmployeeList is at a higher level of abstraction than a generic list class.

addObject and removeObject are at the correct level of abstraction for a generic list. However, EmployeeList is not a generic list. The bad method naming in the code above is a trivial example, and won’t cause much damage other than being slightly confusing. However, consider this interface:

@interface Preferences
-(id)preferenceForKey:(NSString*)key;
-(void)setPreference:(id)prefObject forKey:(NSString*)key;
-(void)flushDiskCache;
@end

flushDiskCache has smashed through the pretty Preferences abstraction like a sledge hammer. Without it, the preferences class is dead simple to use. But including it raises questions like:

  • In what situation do I need to flush the disk cache?
  • What will go wrong if I don’t flush the disk cache?

But the real question is this:

Why am I wasting my time understanding disk cache flushing when I just want to get or set a preference?

Answer: You shouldn’t have to deal with it. Flushing the disk cache is something that should have been handled at a lower level. Saving the preferences to the disk is an implementation detail that should not be visible from the interface. Anyone should be able to use the Preferences class without having to know how it is implemented.

Did that last sentence sound familiar? It should, because it’s a textbook case of information hiding; one of the cornerstones of object oriented programming. The benefits of information hiding are well documented.

Comments are closed.

blog comments powered by Disqus