After writing the previous note about the two most important things in object oriented programming, I realized that there's one pitfall I may want to point out. Let's show it based on an example:
A while ago I wrote a UKBorderlessWindow class. It's a subclass of NSWindow that forces the NSBorderlessWindowMask flag. The advantage of this is that I can now create a borderless window in Interface Builder by simply setting this class as an object's "custom class".
I used this in several projects, and suddenly realised bugs I had already fixed were popping up again. What had happened? Well, I had violated the API contract. You see, every class, every method you create is a contract with the code using it: "This class does X." The code expects that contract to be true. Trouble is, sometimes there is implicit behaviour that you don't realize until you use the class in several projects. A borderless window is only borderless. What I did was that in one app I realised that my borderless window was ending up behind menus, but I wanted it on top. So I modified the class to put the window in a higher layer. Trouble was, another app using this window class was expecting the old layering...
What I should have done was create a new UKCoveringBorderlessWindow class that does the different layering. So, be sure your class names match what the class does, and don't add stuff to a class that doesn't fit its name. Either the name has to change, or you need a new class (or subclass).