In this next section we will look at C++ interfaces. With any programming problem we must first understand the use cases and the problem. Once we have a handle on what we are trying to accomplish we need to define a design and that usually starts by designing the interfaces for the modules and components that implement the design. This step is the foundation on which all of the work going forward will be built. Time spent at this step is often not budgeted by project managers and does not yield a quantifiable short term return. It will however make or break the project.
18: Make interfaces easy to use correctly and hard to use incorrectly: This means that the designer has to think about all the ways that another person might misuse their code. A good example pf this is an object that encapsulates a date. If we consider the interface:
Date(int month, int date, int year);
There is nothing really wrong with this interface and if it is used in the USA, it will almost always produce the expected result. If however the month and day are reversed (Canada) then an unexpected and perhaps undetectable error occurs. Even if we use range checking, 2/1/2007 and 1/2/2007 would not be detected and an error. If we were to redesign this interface and use objects or types for each field however, the error can be prevented.
Date(Month month, Day date, Year year);
There are allot of examples in the book that refer back to previous rules but the summary captures the essentials of rule 18.
- Good interfaces are ones that are easy to use correctly and difficult to use incorrectly.
- Ways to facilitate correct use include consistency in interfaces and behavioral compatibility with built-in types
- Ways to prevent error include creating new types, restricting operators, constraining values and eliminating resource management issues.
- tr1:shared_ptr supports deleters which can be used to prevent a number of problems.
19: Treat Class design as Type design: In C++ and many other object oriented languages, creating a new Class, creates a new Type. Good types have a natural syntax, intuitive semantics and one or more efficient implementations. So what questions should you ask yourself when designing classes?
- How should objects of your new type be created and destroyed?
- How should object initialization differ from object assignment?
- What does it mean for objects of your new type to be passed by value?
- What are the restrictions on legal values for your new type?
- Does your new type fit into an inheritance graph?
- What kind of type conversions are allows for your new type?
- What operators and functions make sense for your new type?
- What standard functions should be disallowed?
- Who should have access to the members of your new type?
- What is the undeclared interface of your new type?
- How general is your new type?
- Is a new type really what you need?
That’s all the time I have to look at C++ for today. The twelve questions presented in rule #19 however, can be applied to any language when defining classes. If object oriented designers were to approach their designs with the same intensity of language designers, we would have much tighter and reusable designs.