The role of abstraction
Scientific descriptions of the world are based on abstractions. A living animal is
a system constructed of organs, bones and so on. These organs are composed of
cells, which in turn are composed of molecules, which in turn are composed of
atoms, which in turn are composed of elementary particles. Scientists find it
convenient (and in fact necessary) to limit their investigations to one level, or maybe
two levels, and to abstract away
from lower levels. Thus your physician will
listen to your heart or look into your eyes, but he will not generally think about the
molecules from which they are composed. There are other specialists, pharmacologists
and biochemists, who study that level of abstraction, in turn abstracting away
from the quantum theory that describes the structure and behavior of the molecules.
In computer science, abstractions are just as important. Software engineers gener- ally deal with at most three levels of abstraction:
Systems and libraries Operating systems and libraries—often called Application Program Interfaces (API)—define computational resources that are available to the programmer. You can open a file or send a message by invoking the proper procedure or function call, without knowing how the resource is im- plemented.
Programming languages A programming language enables you to employ the computational power of a computer, while abstracting away from the details of specific architectures.
Instruction sets Most computer manufacturers design and build families of CPUs which execute the same instruction set as seen by the assembly language programmer or compiler writer. The members of a family may be implemented in totally different ways—emulating some instructions in software or using memory for registers—but a programmer can write a compiler for that instruction set without knowing the details of the implementation.
Of course, the list of abstractions can be continued to include logic gates and their implementation by semiconductors, but software engineers rarely, if ever, need to work at those levels. Certainly, you would never describe the semantics of an assignment statement like \(x\leftarrow y+z\) in terms of the behavior of the electrons within the chip implementing the instruction set into which the statement was compiled.
Two of the most important tools for software abstraction are encapsulation and concurrency.
Encapsulation achieves abstraction by dividing a software module into a public specification and a hidden implementation. The specification describes the available operations on a data structure or real-world model. The detailed implementation of the structure or model is written within a separate module that is not accessible from the outside. Thus changes in the internal data representation and algorithm can be made without affecting the programming of the rest of the system. Modern programming languages directly support encapsulation.
Concurrency is an abstraction that is designed to make it possible to reason about the dynamic behavior of programs. This abstraction will be carefully explained in the rest of this chapter. First we will define the abstraction and then show how to relate it to various computer architectures. For readers who are familiar with machine-language programming, Sections 2.8—2.9 relate the abstraction to machine instructions; the conclusion is that there are no important concepts of concurrency that cannot be explained at the higher level of abstraction, so these sections can be skipped if desired. The chapter concludes with an introduction to concurrent programming in various languages and a supplemental section on a puzzle that may help you understand the concept of state and state diagram.