1 / 48

Modularity

Modularity. Shani Bard Based on a lecture by John Mitchell. Reading: Chapter 9. Why Modularity ?. effective design - each module can be designed and tested independently easy to understand – subprograms are smaller and easier to understand then the original big program. Modularity goal.

dirkd
Download Presentation

Modularity

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. Modularity Shani Bard Based on a lecture by John Mitchell Reading: Chapter 9

  2. Why Modularity? • effective design - each module can be designed and tested independently • easy to understand – subprograms are smaller and easier to understand then the original big program

  3. Modularity goal • divide and conquer • allow one module to be written with little knowledge of the code in another module • allow a module to be redesigned and reimplemented without modifying other parts of the system Modern programming languages and software development environments support modularity in different ways

  4. In this chapter • ways that programs can be divided into meaningful parts • the way that programming languages can be designed to support these divisions • In Chapters 10–13 we explore object-oriented languages in detail, in this chapter we are concerned with modularity mechanisms that do not involve objects

  5. Topics • structured programming • support for abstraction • Modules • to describe module systems and generic programming we will use: • standard ML module system • C++ Standard Template Library (STL)

  6. 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 on web (CS242 Reading page) • 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 • Both ACM Classics of the Month

  7. Dijkstra’s Example (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

  8. Program Structure Main Program Sub-program Sub-program Sub-program Sub-program Sub-program

  9. Data Refinement • 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

  10. Example • For level 2, represent account balance by integer variable • For level 3, need to maintain list of past transactions Bank Transactions Deposit Withdraw Print Statement Print transaction history

  11. Modularity: Basic Concepts • Component • Meaningful program unit • 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

  12. 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; }

  13. Example: Data Type - Heap sort using library data structure • Component • Priority queue: data structure that returns elements in order of decreasing priority • Interface Priority queue: structure with three operations • Type pq • Operations empty : pq insert : elt * pq  pq deletemax : pq  elt * pq

  14. Example: Data Type • Specification • Each priority queue has a multiset of elements. There must be an ordering < on the elements that may be placed in a priority queue. (For integer priority queues, we may use the ordinary < ordering on integers) • An empty priority queue has no elements • Insert add to set of stored elements • Deletemax returns max elt and pq of remaining elts • These specifications do not impose any restrictions on the implementation

  15. Implementation - top-down design • Algorithm using priority queue(heap sort) • First step: the problem - sorting an array function sort begin sort an array of integers end • Second step: refine the statement sort an array of integers into subtasks function sort (n : int, A : array [1..n] of int) begin place each element of array A in a priority queue remove elements in decreasing order and place in array A end

  16. Implementation - top-down design • Final step: final refinement function sort(n: int, A : array [1..n] of int) begin priority queue s; s := empty; for i := 1 to n do s := insert(A[i], s); for i := n downto 1 do (A[i],s) := deletemax(s); end This gives us an O(n log n) sorting algorithm

  17. support for abstraction • abstraction mechanism • emphasizes the general properties of some code and hides details • generally separats a program into parts that contain details and parts where these details are hidden • client: the part of a program that uses program component • implementation: the part of a program that defines a program component • The interaction between the client and implementation of an abstraction is usually restricted to a specific interface

  18. support for abstraction • Procedural Abstraction • Client: a program making a function call • Implementation: the encapsulated function body • Advantages: • well-defined interface • local variables has no effect on other parts of the program • enclosing code inside a function makes the code generic and reusable

  19. Data Abstraction • hiding information about the way that data are represented • Goals: • Identifying the interface of the data structure • information hiding by separating implementation decisions from parts of the program that use the data structure • Allowing the data structure to be used in many different ways by many different programs

  20. Abstract Data Types • Prominent language development of 1970’s • Main ideas: • Separate interface from implementation • Example: • Sets have 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

  21. ML - abstract data type • An ML declaration of an abstract data type of complex numbers may be written as follows: abstype cmplx = C of real * real with fun cmplx(x,y: real) = C(x,y) fun x coord(C(x,y)) = x fun y coord(C(x,y)) = y fun add(C(x1, y1), C(x2, y2)) = C(x1+x2, y1+y2) end • ML returns: type cmplx val cmplx = fn : real * real → cmplx val x coord = fn : cmplx → real val y coord = fn : cmplx → real val add = fn : cmplx * cmplx → cmplx

  22. Representation Independence • a type has a property called representation independent when it has built-in operations • In a type-safe programming language with abstract data types we can: • declare variables of an abstract type • define operations on any abstract type • use type-checking rules to guarantee that only these specified operations can be applied to values of the abstract type

  23. Partition Operations • it is possible to partition the operations on the type into three groups: • Constructors: operations that build elements of the type • Operators: operations that map elements of the type that are definable only with constructors to other elements of the type that are definable with only constructors • Observers: operations that return a result of some other type

  24. Partition Operations - Example empty : set insert : int * set → set union : set * set → set isMember: int * set → bool • the operations can be partitioned as follows: • Constructors: empty and insert • Operator: union • Observer: isMember • we may prove properties of all elements of an abstract type by induction on the number of uses of constructors necessary to produce a given element

  25. Modules • General construct for information hiding • Two parts • Interface: A set of names and their types • Implementation: Declaration for every entry in the interface Additional declarations that are hidden • Examples: • Modula modules, Ada packages, ML structures, ...

  26. Modules and Data Abstraction module Set interface type set val empty : set fun insert : elt * set -> set fun union : set * set -> set fun isMember : elt * set -> bool implementation type set = elt list val empty = nil fun insert(x, elts) = ... fun union(…) = ... ... end Set • Can define ADT • Private type • Public operations • More general • Several related types and operations • Some languages • Separate interface and implementation • One interface can have multiple implementations

  27. Modula • developed by Pascal designer Niklaus Wirth in the late 1970s • main innovation of Modula over Pascal is a module system • Interface is called definition module • Implementation is called implementation module

  28. Modula – transparent Module definition module Fractions; type fraction = ARRAY [1 .. 2] OF INTEGER; procedure add (x, y : fraction) : fraction; procedure mul (x, y : fraction) : fraction; end Fractions. implementation module Fractions; procedure Add (x, y : Fraction) : Fraction; VAR temp : Fraction; BEGIN temp [1] := x [1] * y [2] + x [2] * y [1]; temp [2] := x [2] * y [2]; RETURN temp; END Add; procedure Mul (x, y : Fraction) : Fraction; ... END Mul; end Fractions. • In this example, a complete type declaration is included in the interface. As a result, the client code can see that a fraction is an array of integers – not a good use of the Module abilities

  29. Modula – opaque Module definition module Stack module type stack (* an abstract type *) procedure create stack ( ) : stack procedure push( x:integer, var s:stack ) : stack ... end Stack module implementation module Stack module type stack =array [1..100] of integer ... end Stack module

  30. ADA • designed in the late 1970s and early 1980s as the result of an initiative by the U.S. Department of Defense (DoD) • The DoD wanted to standardize its software around a common language that would provide program structuring capabilities and specific features related to real time programming • By some measures, Ada has been a successful language: • Many Ada programs have been written and used • Some Ada design issues led to research studies and improvements in the state of the art of programming language design • adoption of the language outside of suppliers of the U.S. government has been limited • Lack of easily available implementations • companies who produced Ada compilers expected to sell them for high prices to military contractors

  31. ADA packages • Interface is called package specification • Implementation is called package body package FractionPkg is type fraction is array ... of integer; procedure Add ... end FractionPkg; package body FractionPkg is procedure Add ... end FractionPkg;

  32. ML Modules • designed in the mid-1980s as part of a redesign and standardization effort for the ML programming language • three main parts • structures • signatures • functors

  33. ML structure • a module, which is a collection of type, value, and structure declarations structure S = struct type t = int val x: t= 3 end • s.x = 3 • s.t = int

  34. ML signature • module interface • signatures behave as a formof “type” for a structure • a module may have more than one signature • a signature may have more than one associated module • If a structure satisfies the description given in a signature, the structure “matches” the signature

  35. ML signature signature SIG = sig type t val x : t end • Because the structure S previously introduced satisfies these conditions, it is said to match the signature SIG • The structure S also matches the following signature SIG’: signature SIG’ = sig type t val x : int end • SIG AND SIG’ are different, because there are structures that satisfy only one of them and not the other

  36. ML Functor Functors are functions from structures to structures. Functors are used to define generic modules. Because ML does not support higher-order functors (functors taking functors as arguments or yielding functors as results), there is no need for functor signatures. functor F ( S : SIG ) : SIG = struct type t = S.t * S.t valx: t= (S.x,S.x) end

  37. Generic Abstractions • Parameterize modules by types, other modules • Create general implementations • Can be instantiated in many ways • Language examples: • Ada generic packages, C++ templates, ML functors, … • ML geometry modules in book • C++ Standard Template Library (STL) provides extensive examples

  38. C++ Templates • Type parameterization mechanism • template<class T> … indicates type parameter T • C++ has class templates and function templates • Instantiation at link time • Separate copy of template generated for each type • Why code duplication? • Size of local variables in activation record • Link to operations on parameter type

  39. Example (discussed in earlier lecture) • Monomorphic swap function void swap(int& x, int& y){ int tmp = x; x = y; y = tmp; } • Polymorphic function template template<class T> void swap(T& x, T& y){ T tmp = x; x = y; y = tmp; } • Call like ordinary function float a, b; … ; swap(a,b); …

  40. Standard Template Library for C++ • Many generic abstractions • Polymorphic abstract types and operations • Useful for many purposes • Excellent example of generic programming • Efficient running time (but not always space) • Written in C++ • Uses template mechanism and overloading • Does not rely on objects – No virtual functions Architect: Alex Stepanov

  41. Main entities in STL • Container: Collection of typed objects • Examples: array, list, associative dictionary, ... • Iterator: Generalization of pointer or address • Algorithm • Adapter: Convert from one form to another • Example: produce iterator from updatable container • Function object: Form of closure (“by hand”) • Allocator: encapsulation of a memory pool • Example: GC memory, ref count memory, ...

  42. Example of STL approach #include <string> #include <list> int main (void) { list<string> citieslist; } • operations for putting elements on the front or back of a list: citieslist.push back(“Haifa”); citieslist.push back(“Be’er Sheva”); citieslist.push front(“London”); citieslist.push front(“Liverpool”);

  43. Example of STL approach • We now have a list with four strings in our list. We can print the words in our list by using an iterator. declaration of an iterator for lists of strings: list<string>::iterator citieslistIterator; • an STL iterator is like a pointer – an iterator points to an element of a container, and dereferencing a nonnull iterator produces an object from the container for (citieslistIterator =citieslist.begin(); citieslistIterator!= citieslist.end(); ++citieslistIterator) { // dereference the iterator to get the list element cout << * citieslistIterator << endl; }

  44. Example of STL approach • Function to merge two sorted lists • merge : range(s)  range(t)  comparison(u)  range(u) This is conceptually right, but not STL syntax. • Basic concepts used • range(s) - ordered “list” of elements of type s, given by pointers to first and last elements • comparison(u) -boolean-valued function on type u • subtyping -s and t must be subtypes of u

  45. How merge appears in STL • Ranges represented by iterators • iterator is generalization of pointer • supports ++ (move to next element) • Comparison operator is object of class Compare • Polymorphism expressed using template template < class InputIterator1, class InputIterator2, class OutputIterator, class Compare > OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator1 last2, OutputIterator result, Compare comp)

  46. Comparing STL with other libraries • C: qsort( (void*)v, N, sizeof(v[0]), compare_int ); • C++, using raw C arrays: int v[N]; sort( v, v+N ); • C++, using a vector class: vector v(N); sort( v.begin(), v.end() );

  47. Efficiency of STL • Running time for sort N = 50000 N = 500000 C 1.4215 18.166 C++ (raw arrays) 0.2895 3.844 C++ (vector class) 0.2735 3.802 • Main point • Generic abstractions can be convenient and efficient ! • But watch out for code size if using C++ templates…

  48. Chapter Summary • In this chapter, we studied some of the ways that programs can be divided into meaningful parts and the way that programming languages support these divisions • main topics: • structured programming • support for abstraction • Modules • Two examples were used to investigate module systems and generic programming • standard ML module system • C++ Standard Template Library (STL) • Two important concepts in modular program development are interfaces and specifications

More Related