Think of a definition statement
In order to ensure good Cohesion, think of what purpose the class serves. If you are able to come up with a single, short, clear statement of what the class should be, it means the candidate class likely has good cohesion. If not, then you may need to merge the class into another, or split it into multiple classes. Once you have a definition statement, choose the shortest noun phrase which captures the essence of it; this is your class's name. The benefit of this approach is not only to come up with a good name; it also provides excellent documentation for the class. In addition, as you and others work with the class in the future, you can refer to the definition to decide whether some new functionality belongs in that class or in another.
As an example, consider the definitional statement for the
java.io.LineNumberReaderclass in the Java Standard Library: "A buffered character-input stream that keeps track of line numbers." This definition draws a very clear boundary around the function of this class, and very neatly boils down to the name of the class itself.
Keeping in mind the principle of Unit Economy, reuse vocabulary to reduce the number of concepts in the system. When choosing class names, consider what other classes in the system are related, serve a similar function, or fit into the application's architecture in the same way. Subclasses of the same parent class often should repeat the parent class's name with a new adjective to differentiate them from other subclasses (consider the whole
java.iopackage). Classes which play a part in a standard design pattern often should include the name of the part they play (Apple's Cocoa API uses Model, View, Controller frequently in class names). Classes responsible for validating user input may all contain the word, "Validator", to explicitly spell out its role. Reusing this common vocabulary conveys a wealth of information to the future reader by explicitly telling him how the class fits into the system as a whole.
Stick with the end user's language
Nearly all programming is done with some end user in mind, and that end user invariably has a whole set of vocabulary around the problem your program is trying to solve. Take advantage of that built-in set of concepts for naming your classes. If you're writing a program to deal with a user's digital image, name the class "Photo". If you need a collection of them with some meta-data, name the class "Album". Take advantage of the real-world metaphors which already exist to reduce the effort required to understand your code.
Sticking to the user's own language becomes especially important when dealing with more technical areas where the end user's vocabulary may be somewhat foreign to you as a programmer (e.g. finance, mechanical engineering, or medicine). In this case, the existing terminology generally has an exact definition in the user's own problem space, and by sticking with that language, you carry all that meaning over into the program itself. This makes the mental job of translating between what the user says to what the program does much easier in everything from initial requirements, to bug reports, to enhancement requests. By understanding the user's problem domain, one can gain a lot of information about how the program works.
Naturally, there are a ton more suggestions, guidelines, and principles to apply when naming classes. What are some of your favorites that I haven't included?