1 / 39

Chapter 9

Chapter 9. Data Abstraction and Modularity. Outline. Modular program development Step-wise refinement Interface, specification, and implementation Language support for modularity Procedural abstraction Abstract data types Packages and modules Generic abstractions.

taylor
Download Presentation

Chapter 9

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 9 Data Abstraction and Modularity Data Abstraction and Modularity

  2. Outline • Modular program development • Step-wise refinement • Interface, specification, and implementation • Language support for modularity • Procedural abstraction • Abstract data types • Packages and modules • Generic abstractions Data Abstraction and Modularity

  3. Modular Program Development • Computer programmers have long recognized the value of building software that consists of a number of modules. Two important goals in modularity • Allow one module to be written with little knowledge of the code in another module • Allow a module to be redesigned and re-implemented without modifying other modules of the system • Structured programming support modularity through stepwise refinements Data Abstraction and Modularity

  4. Stepwise Refinement • Wirth, 1971 • “… program ... gradually developed in a sequence of refinement steps” • In each step, instructions are decomposed into more detailed instructions. • Historical reading (Classic papers) • N. Wirth, Program development by stepwise refinement, Communications of the ACM, 1971 • D. Parnas, On the criteria to be used in decomposing systems into modules, Comm. ACM, 1972 Data Abstraction and Modularity

  5. Dijkstra’s Example-stepwise refinements (1969) begin print first 1000 primes end begin variable table p fill table p with first 1000 primes print table p end begin int array p[1:1000] make for k from 1 to 1000 p[k] equal to k-th prime print p[k] for k from 1 to 1000 end Data Abstraction and Modularity

  6. Stepwise refinement leads to program with a tree-like conceptual structure Main Program Sub-program Sub-program Sub-program Sub-program Sub-program Data Abstraction and Modularity

  7. Data Refinement • In addition to refining tasks into subtasks, system design may lead to changes in data structures. • Wirth, 1971 again: • As tasks are refined, so the data may have to be refined, decomposed, or structured, and it is natural to refine program and data specifications in parallel. Data Abstraction and Modularity

  8. Data Refinement Example • Consider the problem of designing a simple banking program. It process accounts and print monthly bank statements Bank Transactions Deposit Withdraw Print Statement Print transaction history Data Abstraction and Modularity

  9. Data Refinement Example • Assume the statement only contain the account number and balance. Then a bank account can be represented by integer variable and store all bank accounts in an integer array. • If we later refine the task “Print Statement” to include the subtask “Print list of transactions”. Then we have to maintain a record of bank transactions. • For this refinement, we will have to replace the integer array with some other data structure that records the sequence of transactions that had occurred since the last statement. Data Abstraction and Modularity

  10. Modularity • For a program that is designed modularly, it should be possible to change the internal structure (implementation) of any component, as long as the behavior remains the same. Data Abstraction and Modularity

  11. Modularity • Program development approaches • Top-down approach • Bottom-up approach • Designing basic parts that will be needed in large software systems and then combining them into larger subsystems. • Program development methods • Prototyping • Object-oriented design Data Abstraction and Modularity

  12. Modularity: Basic Concepts • Four concepts in modular program development • Component • Meaningful program unit such as function, data structure, module, … • Interface • Types and operations defined within a component that are visible outside the component • Specification • Intended behavior of component, expressed as property observable through interface • Implementation • Data structures and functions inside component Data Abstraction and Modularity

  13. Example: Function Component • Component • Function to compute square root • Interface • float sqroot (float x) • Specification • If x>1, then sqrt(x)*sqrt(x)  x. • Implementation float sqroot (float x){ float y = x/2; float step=x/4; int i; for (i=0; i<20; i++){if ((y*y)<x) y=y+step; else y=y-step; step = step/2;} return y; } Data Abstraction and Modularity

  14. Component Description • Various languages and methods for describing components (specification writing) • Structured natural languages • Semiformal methods • Formal methods • Basic problem with specification • How to verify that a component or module satisfies its specification? Data Abstraction and Modularity

  15. Example: Data Type • Component • Priority queue: data structure that returns elements in order of decreasing priority • Interface • Type pq • Operations empty : pq insert : elt * pq  pq deletemax : pq  elt * pq • Specification • Insert add to set of stored elements • Deletemax returns max elt and pq of remaining elts Data Abstraction and Modularity

  16. Language Support for Modularity • Abstraction • Emphasize the general properties of a component but hide its details • Implementation: part of a program that defines the component • Abstraction mechanisms: • Procedural abstraction • Procedure or function • Well-defined interface (function name, parameters and return value) • Information hiding (local variables has no effect on other parts of the program. • Generic (function may be called with different type of parameters) • Data abstraction --- Abstract Data Type (ADT) Data Abstraction and Modularity

  17. Abstract Data Types • Prominent in languages development of 1970’s • An abstract data type consists of a type together with a set of operations • Main ideas: • Separate interface from implementation • Example: • Sets have operations like empty, insert, union, is_member?, … • Sets implemented as … linked list … • Use type checking to enforce separation • Client program only has access to operations in interface • Implementation encapsulated inside ADT construct Data Abstraction and Modularity

  18. Abstract Data Types-Example • Assume a stack is implemented with an array. • A user of a stack abstract data type can use only the stack operations: • push • pop • He cannot use array operations such as indexing into the array. Data Abstraction and Modularity

  19. Understanding ADTs • We can understand the significance of abstract type declarations by considering some of the properties of a typical built-in type such as int. • We can declare variables x : int of this type. • There is a specific set of built-in operations on the type +, -, *, etc. • Only these built-in operations can be applied to values of type int; it is not type correct to apply string or other types of operations to integers. Data Abstraction and Modularity

  20. Understanding ADTs • Because ints can be accessed only by means of the built-in operations, they enjoy a property called representation independence. • Representation independence means that different computer representations on integers do not affect program behavior. • One computer could represent ints by using 1’s complement, and another by using 2’s complement, and the same program run on the two machines will produce the same output. Data Abstraction and Modularity

  21. Understanding ADTs • Similar to the built types such int, we can define ADT. • In a programming language with ADTs • We can declare variables of an abstract data type. • We define operations on any abstract data type • Type-checking rules of the language guarantee that only the ADT’s specified operations can be applied to values of the ADT • Similar to built-in types, these properties of ADTs imply representation independence for user-defined type. • Representation independence means that we can change the representaion of our ADTs without affecting the clients of our ADTs. Data Abstraction and Modularity

  22. Abstract Data Types - Principles • One useful principle is data-type induction • Useful for reasoning about abstract data types. • This principle is used informally in program development and maintenance. • It is common to first build a software system with potentially inefficient implementation of data type and then to replace these with more efficient implementation as time permits. Data Abstraction and Modularity

  23. Abstract Data Types – Partition Operations • For many ADTs, it is possible to partition the operations on type into three groups: • Constructors: operations that build elements of the type. • Operators: operations that map element of the type that are definable only with constructors to other elements of the type that are definable only with constructors. • Observers: operations that return a result of some other type. Data Abstraction and Modularity

  24. Abstract Data Types – Example • Consider the integer set ADT with the following operations: • empty : build an empty set. (set) • insert : inserts an int into a set (int*set  set) • union : do union of two sets (set*set  set) • isMember : check membership of int (int*set  bool) • The operations can be partitioned as follows: • Constructors: empty and insert • Operators: union • Observers: isMember Data Abstraction and Modularity

  25. ADTs implementations - Modules • A module is a programming language construct that allows a number of declarations to be grouped together. • Two parts • Interface: • Implementation: • Examples: • Modula modules, Ada packages, ML structures, ... Data Abstraction and Modularity

  26. Modula Modules - Example • In Modula terminology, a module interface is called a definition module and an implementation an implementation module. • A stack module can be defined as follows: definition module Stack_module type stack procedure create_stack() : stack procedure push(x : integer, var s : stack) : stack … end Stack_module implementation module Stack_module type stack = aray[1 .. 100] of integer … end Stack_module Data Abstraction and Modularity

  27. Generic Abstractions • ADTs such as stacks or queues are useful for sorting many kinds of data. • In typed programming languages, however, the code for stack of integers is different from the code for stacks strings. • It is time consuming to write different versions of stacks for different types of elements because the code for the two cases is almost identical. • For that reason, most typed languages that emphasize abstraction and encapsulation have incorporated some form of type parameterization. Data Abstraction and Modularity

  28. Generic Abstractions – C++ • Function templates are special functions that can operate with generic types. • This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. Data Abstraction and Modularity

  29. Generic Abstractions – C++ • In C++ this can be achieved using template parameters. • A template parameter is a special kind of parameter that can be used to pass a type as an argument • Just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function. • These function templates can use these parameters as if they were any other regular type. Data Abstraction and Modularity

  30. Generic Abstractions – C++ • The format for declaring function templates with type parameters is: template <class identifier> function_declaration; template <typename identifier> function_declaration; • The only difference between both prototypes is the use of either the keyword class or the keyword typename. • Its use is indistinct, since both expressions have exactly the same meaning and behave exactly the same way. Data Abstraction and Modularity

  31. Generic Abstractions – C++ • For example, to create a template function that returns the greater one of two objects we could use: template <class myType> myType GetMax(myType a, myType b) { return (a>b?a:b); } • Here we have created a template function with myType as its template parameter. • This template parameter represents a type that has not yet been specified, but that can be used in the template function as if it were a regular type. • As you can see, the function template GetMax returns the greater of two parameters of this still-undefined type. Data Abstraction and Modularity

  32. Generic Abstractions – C++ • To use this function template we use the following format for the function call: function_name <type> (parameters); • For example, to call GetMax to compare two integer values of type int we can write: int x,y; GetMax <int> (x,y); Data Abstraction and Modularity

  33. Generic Abstractions – C++ • When the compiler encounters this call to a template function, it uses the template to automatically generate a function replacing each appearance of myType by the type passed as the actual template parameter (int in this case) and then calls it. • This process is automatically performed by the compiler and is invisible to the programmer. Data Abstraction and Modularity

  34. Generic Abstractions – C++ • Here is the entire example: // function template #include <iostream> using namespace std; template <class T> T GetMax (T a, T b) { T result; result = (a>b)? a : b; return (result); } int main () { int i=5, j=6, k; long l=10, m=5, n; k=GetMax<int>(i,j); n=GetMax<long>(l,m); cout << k << endl; cout << n << endl; return 0; } Data Abstraction and Modularity

  35. Generic Abstractions – C++ • In this specific case where the generic type T is used as a parameter for GetMax the compiler can find out automatically which data type has to instantiate without having to explicitly specify it within angle brackets (like we have done before specifying <int> and <long>). • So we could have written instead: int i,j; GetMax (i,j); • Since both i and j are of type int, and the compiler can automatically find out that the template parameter can only be int. This implicit method produces exactly the same result: Data Abstraction and Modularity

  36. Generic Abstractions – C++ • Here is the same example without <type> // function template #include <iostream> using namespace std; template <class T> T GetMax (T a, T b) { T result; result = (a>b)? a : b; return (result); } int main () { int i=5, j=6, k; long l=10, m=5, n; k=GetMax (i,j); n=GetMax (l,m); cout << k << endl; cout << n << endl; return 0; } Data Abstraction and Modularity

  37. Generic Abstractions – C++ • Because our template function includes only one template parameter (class T) and the function template itself accepts two parameters, both of this T type, we cannot call our function template with two objects of different types as arguments: int i; long l; k = GetMax (i,l); • This would not be correct, since our GetMax function template expects two arguments of the same type, and in this call to it we use objects of two different types. Data Abstraction and Modularity

  38. Generic Abstractions – C++ • We can also define function templates that accept more than one type parameter, simply by specifying more template parameters between the angle brackets. • For example: template <class T, class U> T GetMin (T a, U b) { return (a<b?a:b); } Data Abstraction and Modularity

  39. Generic Abstractions – C++ • In this case, our function template GetMin() accepts two parameters of different types and returns an object of the same type as the first parameter (T) that is passed. • For example, after that declaration we could call GetMin() with: int i,j; long l; i = GetMin<int,long> (j,l); • or simply: i = GetMin (j,l); Data Abstraction and Modularity

More Related