1 © AdaCore under the GNU Free Documentation License Franco Gasperoni gasperoni@adacore.com

Preview:

Citation preview

1http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Franco Gasperoni

gasperoni@adacore.com

http://libre.adacore.com

7http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large

– specification & implementation

– privacy

– abstract data types

– hierarchical packages

8http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Separate CompilationSeparate CompilationTHE PROBLEM

Compiler object

CODE

Compiler object

CODE

Compiler object

CODE

Linker

executable

libraries

9http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Problem with this approachProblem with this approach

CODE

CODE

CODE

• No structure

• To write your own code– YOU MUST understand

everybody else’s code

CODE

CODE

10http://libre.adacore.com © AdaCore under the GNU Free Documentation License

IdeaIdea

SPECIFY WHAT EACH

MODULESHOULD DO

11http://libre.adacore.com © AdaCore under the GNU Free Documentation License

SPECIFICATION

Software module

?

BODY

12http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large– specification &

implementation•specification

• implementation

• specification rules in Ada

13http://libre.adacore.com © AdaCore under the GNU Free Documentation License

A Specification is a ...A Specification is a ...

CONTRACTImplementorof themodule

Users/clientsof themodule

• On the SERVICES provided by the module

14http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• SPEC = list of services provided

• BODY = implementation of the services (hidden)

Software module

Service_1Service_2Service_3

Service_1 implementation

Service_2 implementation

Service_3 implementation

15http://libre.adacore.com © AdaCore under the GNU Free Documentation License

SPECIFICATION

?BODY

16http://libre.adacore.com © AdaCore under the GNU Free Documentation License

ExampleExample

• Create a Queue module that can– Add an Integer to the Queue

– See the First integer in the Queue

– Get the first integer in the Queue

– Test whether the Queue is Empty

17http://libre.adacore.com © AdaCore under the GNU Free Documentation License

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

queue.adsqueue.ads

18http://libre.adacore.com © AdaCore under the GNU Free Documentation License

package Queue

?

BODY

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

queue.adsqueue.ads

19http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Using package QueueUsing package Queue

with Queue;procedure Client is Queue_Error : exception; X : Integer;begin Queue.Add (3); Queue.Add (4);

if not Queue.Empty then X := Queue.Get; else raise Queue_Error; end if;end Client;

client.adb

20http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Specifications Reduce ComplexitySpecifications Reduce Complexity

SPECSPEC

SPECSPEC

SPECSPEC

SPECSPEC

• To write your own code– only need to understand

specs for the services you need

21http://libre.adacore.com © AdaCore under the GNU Free Documentation License

package Queue?

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

queue.adsqueue.ads

To write Client only need to look atTo write Client only need to look at

22http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Aside: use clauseAside: use clause

with Queue; use Queue;procedure Client is Queue_Error : exception; X : Integer;begin Queue. Add (3); Queue. Add (4);

if not Queue. Empty then X := Queue. Get; else raise Queue_Error; end if;end Client;

23http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large– specification &

implementation• specification

• implementation

• specification rules in Ada

24http://libre.adacore.com © AdaCore under the GNU Free Documentation License

ONEONE possible possible implementationimplementation

of packageof packageQueueQueue

This implementationThis implementation raises Constraint_Error raises Constraint_Errorif more than Max_Sizeif more than Max_Size

elements are put in the Queue.elements are put in the Queue.

25http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Circular BufferCircular Buffer

Q

0 1Max_Size - 1

Q_Last Q_First

28http://libre.adacore.com © AdaCore under the GNU Free Documentation License

ANOTHERANOTHER possible possible implementationimplementation

of packageof packageQueueQueue

29http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Linked ListLinked List

Q_LastQ_First

Free

34http://libre.adacore.com © AdaCore under the GNU Free Documentation License

A Spec can have several A Spec can have several implementationsimplementations

• Can change implementation

• WITHOUT having to change ANY of the client’s code

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

package Queue is procedure Add (Element : Integer);

function First return Integer; function Get return Integer;

function Empty return Boolean;end Queue;

queue.adsqueue.ads

firstimplement.

firstimplement.

secondimplement.second

implement.

35http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large– specification &

implementation• specification

• implementation

•specification rules in Ada

36http://libre.adacore.com © AdaCore under the GNU Free Documentation License

In AdaIn Ada

• Spec always checked against implementation

• Must with the specs that you are going to

use (not in C)

• Packages provide multiple name spaces

38http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Must with Specs usedMust with Specs used

with Queue;procedure Client is ...begin Queue.Add (3); ...end Client;

Compilationerror

39http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Multiple Name SpacesMultiple Name Spacespackage Queue is procedure Add (E : Integer); ...end Queue;

package Queue is procedure Add (E : Integer); ...end Queue;

package Set is procedure Add (E : Integer); ...end Set;

package Set is procedure Add (E : Integer); ...end Set;

with Queue;with Set;procedure Client isbegin Queue.Add (3);

Set.Add (99);end Client;

40http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Use Clause and AmbiguitiesUse Clause and Ambiguitiespackage Queue is procedure Add (E : Integer); ...end Queue;

package Queue is procedure Add (E : Integer); ...end Queue;

package Set is procedure Add (E : Integer); ...end Set;

package Set is procedure Add (E : Integer); ...end Set;

with Queue; use Queue;with Set; use Set;procedure Client isbegin Add (123);end Client;

Compilationerror

ambiguity

41http://libre.adacore.com © AdaCore under the GNU Free Documentation License

But … Ada has overloadingBut … Ada has overloadingpackage Queue is procedure Add (E : Integer); procedure Add (E : Float); ...end Queue;

package Queue is procedure Add (E : Integer); procedure Add (E : Float); ...end Queue;

with Queue; use Queue;

procedure Client isbegin Add (123);

Add (3.141);end Client;

42http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large

– specification & implementation

– privacy

– abstract data types

– hierarchical packages

43http://libre.adacore.com © AdaCore under the GNU Free Documentation License

package Queues is type Queue is …;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;end Queues;

package Queues is type Queue is …;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;end Queues;

Having Several QueuesHaving Several Queues

45http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Using Several QueuesUsing Several Queues

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

begin Add (Q1, 123);

Add (Q2, 3);

Add (Q2, Get (Q1));end Client;

46http://libre.adacore.com © AdaCore under the GNU Free Documentation License

One possible One possible implementation ...implementation ...

package Queues is type Queue is …;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;end Queues;

type Q_Element;type Element_Ptr is access Queue_Element;

type Queue_Element is record Val : Integer; Next : Element_Ptr;end record;

type Queue is record First : Element_Ptr; Last : Element_Ptr;end record;

type Q_Element;type Element_Ptr is access Queue_Element;

type Queue_Element is record Val : Integer; Next : Element_Ptr;end record;

type Queue is record First : Element_Ptr; Last : Element_Ptr;end record;

47http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Client code allowed to Client code allowed to depend on the depend on the

implementation !implementation !with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

begin Add (Q1, 123); Add (Q2, 3);

Q2.Last := null;

end Client;

OK

48http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Another implementation ...Another implementation ...

package Queues is type Queue is …;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;end Queues;

Max_Size : constant := 100;type Q_array (Natural range <>) of Integer;

type Queue is record Q : Q_Array (0 .. Max_Size); First : Natural; Last : Natural; Size : Natural;end record;

Max_Size : constant := 100;type Q_array (Natural range <>) of Integer;

type Queue is record Q : Q_Array (0 .. Max_Size); First : Natural; Last : Natural; Size : Natural;end record;

49http://libre.adacore.com © AdaCore under the GNU Free Documentation License

… … breaks client code !breaks client code !

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

begin Add (Q1, 123); Add (Q2, 3);

Q2.Last := null;

end Client;

Compilationerror

50http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Even without changing Even without changing the implementationthe implementationthere is a there is a PROBLEMPROBLEM

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

begin Add (Q1, 123); Add (Q2, 3);

Q2.Last := null;

end Client;

Q2 is in aninconsistent

state

33FirstLast

null

Q2:

51http://libre.adacore.com © AdaCore under the GNU Free Documentation License

You need PRIVACYYou need PRIVACY

• Exposing your data structures is risky

– Client code may manipulate the structures directly without using your own services

– Client code is hard to change

52http://libre.adacore.com © AdaCore under the GNU Free Documentation License

ThinkThink BIGBIG

what if what if the the QueuesQueues package package

is is used byused by 1000s1000s of other of other packagespackages

53http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• If there is a bug concerning a Queue, you may have to look at 1000s of packages to find the bug

• If you change the implementation you may have to update 1000s of packages

54http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large

– privacy•private types

• private types & discriminants

• limited private types

55http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Private typesPrivate types

package Queues is type Queue is private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

package Queues is type Queue is private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

56http://libre.adacore.com © AdaCore under the GNU Free Documentation License

In any implementation ...In any implementation ...package Queues is type Queue is private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue_Element; type Element_Ptr is access Queue_Element; type Queue_Element is record Val : Integer; Next : Element_Ptr; end record;

type Queue is record First : Element_Ptr; Last : Element_Ptr; end record;end Queues;

57http://libre.adacore.com © AdaCore under the GNU Free Documentation License

… … private types are PRIVATEprivate types are PRIVATE

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

begin Add (Q1, 123); Add (Q2, 3);

Q2.Last := null;

end Client;

Compilationerror

58http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Advantages of Advantages of privateprivate types types

• Enforces the contract of a specification

• No client code can corrupt your data structures

• Can change implementation without changing client code

66http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large

– privacy• private types

• private types & discriminants

• limited private types

67http://libre.adacore.com © AdaCore under the GNU Free Documentation License

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

X : Integer;

begin Add (Q1, 123); Add (Q1, 3);

Q2 := Q1;

X := Get (Q2);end Client;

Does this affect Q1 ?

68http://libre.adacore.com © AdaCore under the GNU Free Documentation License

it depends on … the it depends on … the implementation !implementation !

• If a Queue is implemented with

– a pointer then Get (Q2) MODIFIES Q1

– a record containing an array then Get (Q2) does NOT modify Q1

69http://libre.adacore.com © AdaCore under the GNU Free Documentation License

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue; X : Integer;begin Add (Q1, 123);

Add (Q1, 3);

Q2 := Q1;

X := Get (Q2);X := Get (Q2);end Client;

123123Q1: 33

Q2:

123123Q1:

123123Q1: 33

Q2:

Pointer Pointer implementationimplementation

Pointer Pointer implementationimplementation

70http://libre.adacore.com © AdaCore under the GNU Free Documentation License

limited private typeslimited private types

• NO assignment :=

• NO equality comparison =

71http://libre.adacore.com © AdaCore under the GNU Free Documentation License

package Queues is type Queue is limited private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

package Queues is type Queue is limited private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

72http://libre.adacore.com © AdaCore under the GNU Free Documentation License

with Queues; use Queues;procedure Client is Q1 : Queue; Q2 : Queue;

X : Integer;

begin Add (Q1, 123); Add (Q1, 3);

Q2 := Q1;

end Client;

COMPILATIONERROR

:= forbidden

83http://libre.adacore.com © AdaCore under the GNU Free Documentation License

• Programming in the Large

– specification & implementation

– privacy

– abstract data types

– hierarchical packages

84http://libre.adacore.com © AdaCore under the GNU Free Documentation License

To add functionality ...To add functionality ...

package Queues is type Queue is private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

function Last (Q : Queue) return Integer;

function Last (Q : Queue) return Integer;

Must add it to

QueuesQueue is a private type

85http://libre.adacore.com © AdaCore under the GNU Free Documentation License

But ...But ...

• Every time you change a spec you must recompile all its clients

• Every time you change a module you must RETEST the whole module

86http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Solution: use child unitsSolution: use child units

package Queues is type Queue is private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

queues.ads

function Queues . Last (Q : Queue) return Integer;queues-last.ads

Child subprogram

87http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Child Units RulesChild Units Rules

• The body or private part of a child unit can see the private part of all of its parents

• The spec of a child unit does NOT

88http://libre.adacore.com © AdaCore under the GNU Free Documentation License

Using a child unitUsing a child unit

with Queues; use Queues;with Queues.Last;procedure Client is Q : Queue; X : Integer;

begin Add (Q, 123); Add (Q, 3);

X := Queues.Last (Q);end Client;

89http://libre.adacore.com © AdaCore under the GNU Free Documentation License

package Queues is type Queue is private;

procedure Add (Q : Queue; Element : Integer); function First (Q : Queue) return Integer; function Get (Q : Queue) return Integer; function Empty (Q : Queue) return Boolean;

private type Queue is …;end Queues;

queues.ads

package Queues . New_Functionality is function Last (Q : Queue) return Integer;end Queues . New_Functionality

queues-new_functionality.ads

Child package

90http://libre.adacore.com © AdaCore under the GNU Free Documentation License

with Queues; use Queues;with Queues.New_Functionality;procedure Client is Q : Queue; X : Integer;

begin Add (Q, 123); Add (Q, 3);

X := Queues.New_Functionality.Last (Q);end Client;

Recommended