- COMP.CS.140
- 4. Programming in the Large
- 4.1 The Playing Field of Implementing Software
- 4.1.2 Information Hiding
Information Hiding¶
Defining software components based on their behaviour makes it possible for the user to not be aware of how the component is implemented. The implementation can be encapsulated behind an interface intended for the user. The role of the interface is to tell the user how the component is supposed to work. The same component can have different interfaces depending on the situation. For example, the interface of an object can be different for a constant object, subclasses and other basic use contexts. The interface is the part of the component its user sees and through which the component is used. The implementation of the interface is not visible to the user and is none of the user’s business. The division of responsibilities for an interface and the implementation encapsulated behind it makes both understanding the program structure and implementing it easier. The implementation of the component can be changed without having an effect on the part of the program using it. Because the interface is the only part visible to the user, it should contain everything the user needs as functionality. Additionally it must be clearly indicated to the user how the services provided by the interface should be used, what they promise and how they act when errors occur.
The easiest way to recognize a good interface is seeing one. It is well documented, easy to understand and use. As the interface is the only part of the component visible to the user, proper documentation becomes paramount. Hence the dependencies of the component, possible ownership responsibilities in using the component as well as error situations and their possible visibility to the user must be documented. The plain definition in a programming language is not enough. A written documentation is needed for the user to be able to use the interface correctly.
Information hiding is one of the key principles of implementing large programs. It makes it possible to implement parts of the software separately from each other. It also enables the reuse of code components: a component once well implemented is usable again in other contexts. Hence communication and how different parts of the program connect to each other becomes pivotal. In the design of components using encapsulation this is verbalized in the so called Parnas’s principle (David Parnas 1972):
The developer must provide the intended user with all the information needed to make effective use of the services provided by the component, and no other information.
The implementor of a software component must be provided with all the information necessary to carry out the given responsibilities assigned to the component, and no other information.
The design of interfaces is not the focus in Programming 3. Instead we focus on the user’s viewpoint as well as the implementor view on how to implement an interface that fullfills certain criteria. The basics of interface design is to think:
How the interface can be used?
What the functionality provided by the interface promises to do?
What kind of errors can occur in the functionality?
How the interface should be tested?
On abstractions (duration 8:31 )
The Interface in Programming Languages¶
In programming languages how the interface is seen depends on the language and the component in question.
The most familiar structure is probably the public and private interface of a class.
The methods in the class interface define the public interface of the class through which the components of the class are used.
Additionally the class can have a private interface to help with its implementation as well as a private implementation.
In Java there is specifically a structure interface
that can be used to depict an “empty”
interface: a collection of functionality that belongs together but has no independent implementation.
The implementation of the interface is done in a class. We will explore this more thoroughly
in a few weeks when we have learned enough about classes in Java.
Let’s use a date class implemented in C++ and Java as an example. In Java itself there is a package for handling time and dates. (In C++ the equivalent is std::chrono ). Some of the implementations of the methods have been left out also in the Java class for clarity. Unlike in C++ in Java the implementation of the class cannot be separated from the interface. The implementation of the interface is not interesting to the user on the code level alone. The user gets the information they need from the documentation. The documentation of the class and its public interface can be produced directly from the definition of the class as long as it is correctly commented. We will get back to the documentation once we have enough implementation knowledge.
You have learned to define the public interface first in C++. This is a style choice – a coding convention. In Java it is considered good programming style that the variables of the class are defined first and the services of the interface second. This is sensible from the point of view of the implementor. The user will prefer the documentation. We will get to know the definition of a Java class in more detail next.
class Date
{
public:
// Setting the date (note: no implementation given)
public void setDate(int d, int m, int y){}
void setDate(int d, int m, int y);
void setDay(int d);
void setMonth(int m);
void setYear(int y);
int getDay() const;
int getMonth() const;
int getYear() const;
// Advancing the date the given number of days
void add(int n);
private:
int day;
int month;
int year;
};
public class Date
{
private int day_;
private int month_;
private int year_;
// Setting the date (note: no implementation given)
public void setDate(int d, int m, int y){}
public void setDay(int d){}
public void setMonth(int m){}
public void setYear(int y){}
public int getDay(){ return day_; }
public int getMonth(){ return month_; }
public int getYear(){ return year_; }
// Advancing the date the given number of days
public void add(int n){}
}