génie logiciel software engineering c. petitpierre

267
Génie logiciel Software Engineering C. Petitpierre

Post on 18-Dec-2015

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Génie logiciel Software Engineering C. Petitpierre

Génie logicielSoftware Engineering

C. Petitpierre

Page 2: Génie logiciel Software Engineering C. Petitpierre

Thèmes du cours

• UML (Unified modeling language)• Processus de développement• Design Patterns• Java Server Faces, EJB3• JET, use of templates• Chargement de databases en XML

SAX, FSM, JavaCC• Langage permettant la validation:

CCS et threads

Page 3: Génie logiciel Software Engineering C. Petitpierre

Personnages et sites

• Martin Fowlerhttp://martinfowler.com/

• Scott Amblerhttp://www.ambysoft.com/

Page 4: Génie logiciel Software Engineering C. Petitpierre

Projet de génie logiciel

• Gestion des commandes des clients dans un restaurant:

Prendre une commande

L’afficher au comptoir et à la cuisine

Indiquer quand elle est prête

Faire les factures

• Plan de travail disponible sur le Web:http://ltiwww.epfl.ch/~petitp/GenieLogiciel

Page 5: Génie logiciel Software Engineering C. Petitpierre

UMLUnified Modeling Language

(OMG object management group)

http://www.uml.org/ http://www.omg.org/

Page 6: Génie logiciel Software Engineering C. Petitpierre

UML usage

• UML is particularly useful to sketch IT applications (pencil and eraser or PowerPoint)

• It can be adapterused to document applications (reverse engineering consists of recreating the diagrams from the code, which is a cheap way of making a“cheap” documentation)

• It is used by ArcStyler and OptimalJ (among others) to create applications(it is difficult to enter the application details in these systems)

Page 7: Génie logiciel Software Engineering C. Petitpierre

UML / RUP: history• Rational founded in 1981 around a processor and

development environments for Ada and C++

• In 1990, Grady Booch develops Rose for Rational, a tool to specify models

• In 1995, Rational hires James Rumbaugh, buys Ivar Jacobson’ company, and the three “amigos” define UML (unified modeling language)

• Same year, Philippe Kruchten defines RUP (Rational unified process)

• In 2002, IBM buys the company for ~ $2B (beside UML, they are consultants for many customers)

Page 8: Génie logiciel Software Engineering C. Petitpierre

UML Rules of Thumb(features not bugs !)

• Nearly everything in UML is optional

• UML models are rarely complete

• UML is designed to be open to interpretation

• UML is intended to be extended

UML 2.0 in a nutshell, Dan Pilone, O’Reilly, 2005

Page 9: Génie logiciel Software Engineering C. Petitpierre

UML

• Use cases

• Class diagrams

• Sequence diagrams

• Collaboration diagrams

• State diagrams / Activity diagrams

Page 10: Génie logiciel Software Engineering C. Petitpierre

UML

Use case diagram for an ATM (automate de banque)

Only lists the names of the use case scenarios, which describe the various functions defined by the application

Withdraw Money

Check Balance

TransferMoney

Open Account <<include>>

<<include>>

Page 11: Génie logiciel Software Engineering C. Petitpierre

UML: Use case (scenario)

1. A client inserts a card into the ATM.

2. The system reads and validates the card information.

3. The system prompts for a PIN.

4. The client enters the PIN. (client, system = actors)

5. The system validates the PIN

6. The client selects “Withdraw Money”

7. The client enters the requested amount.

8. The system requests the amount from the client’s account.

9. The system asks the client to remove the card.

10.The system dispenses the requested amount from the banknote buffer(only done if the requested amount has been granted in 8).

Page 12: Génie logiciel Software Engineering C. Petitpierre

UML: Use case (extension)

1. A client inserts a card into the ATM.

2. The system reads and validates the card information.

3. The system prompts for a PIN.

4. The client enters the PIN. (client, system = actors)

5. The system validates the PIN

Extensions

5a. If the PIN is invalid, the system rejects the card

6. The client selects “Withdraw Money”

7. The client enters the requested amount

8. . . .

Page 13: Génie logiciel Software Engineering C. Petitpierre

UML: Dictionary

If you work in a new domain (bank, assurances, production…) you will need to create a small dictionary

Page 14: Génie logiciel Software Engineering C. Petitpierre

Class diagram with visibility

Bill

- numberOfItems : int

+ addItem(item:Item)- getFirstItem() : Item# getNextItem() : Item

+ public visible from everywhere

- private local to the class

# protected visible only from the derived class

~ package visible from the package (Java)

(actually this is too far into the details for a sketch)

Page 15: Génie logiciel Software Engineering C. Petitpierre

Class diagram: inheritance

SomeClass AnotherClass

SuperClass

Page 16: Génie logiciel Software Engineering C. Petitpierre

UML: note(Omondo on Eclipse)

Page 17: Génie logiciel Software Engineering C. Petitpierre

Class diagram: association

SomeClass AnotherClass

Weakest form of relationship

(Can be used, for example, to indicate that a method may call a method in another class)

Page 18: Génie logiciel Software Engineering C. Petitpierre

Class diagram: aggregationBill

- numberOfItems : int

+ addItem(item:Item)- getFirstItem() : Item# getNextItem() : Item

BillItem

+ ProductNumber : int+ NumberOfPieces : int+ UnitPrice : int

Customer

name : String

10..*

Used to show that an object instantiated from that class contains another object (in an attribute) or a collection of objects (collection in an attribute)

Page 19: Génie logiciel Software Engineering C. Petitpierre

Class diagram: composition

Window menu1

1..*

Strong relationship. If the main class is deleted, the subclass has no meaning any more and is destroyed.

Not often used.

Page 20: Génie logiciel Software Engineering C. Petitpierre

Sequence diagram

Main

Object B

run ( )

start ( )

foo ( )

return

Object X

xMeth ( )

new ( )

Page 21: Génie logiciel Software Engineering C. Petitpierre

Collaboration diagram (Omondo)

Page 22: Génie logiciel Software Engineering C. Petitpierre

Collaboration diagram(context of the application)

controller

temporarydataset

GUI

printer_A

remotedatabaseproxy

DBinter-face

printer_B

employee

Non standard use of specific icons

Page 23: Génie logiciel Software Engineering C. Petitpierre

State diagram / state charts

doing

02

1

displayapplication

exit

enter

start

enter

display_francs

next

ignore

ignore

display_euros

previous

timeout

Page 24: Génie logiciel Software Engineering C. Petitpierre

State diagram / state charts

A

action

start

E

timeout

Entry point

Exit

Page 25: Génie logiciel Software Engineering C. Petitpierre

Relation between a state chart and a use case

collaborationdiagram with use case 1

state chartdiagram of

a component

collaborationdiagram withuse case 2

02

1

component

Collaboration diagram: actors and repositories

Use case: what they do and in what sequence

State chart: all actions of a component

Page 26: Génie logiciel Software Engineering C. Petitpierre

Activity diagrams

• Inspired from the Petri nets

• May fork and join threads

• The use of forks and joins is not a very good idea !! It makes it very difficult to follow the state of a program

Page 27: Génie logiciel Software Engineering C. Petitpierre

Activity diagram: an example

close

find

log register

[registration]

[quit]Fork

Two threads

Join

Page 28: Génie logiciel Software Engineering C. Petitpierre

<< Stereotypes >>

<< CMP EJB >>Bill- numberOfItems : int

Customer

name : String

<< hasBills >>

Page 29: Génie logiciel Software Engineering C. Petitpierre

UML: a technique to start a development

Identifying classesBorrowing The library contains books and journals. It may have several copies of a given book. Some of the books are for short term loans only. All other books may be borrowed by any library member for three weeks. Members of the library can normally borrow up to six items at a time, but members of staff may borrow up to twelve items at one time. Only members of staff may borrow journals.

library is out of scope item is vague

short term loan is an event time is out of scope

week is a measure of time system is not part of the domain

We keep:

book – journal – copy (of book) – library member – staff member

Page 30: Génie logiciel Software Engineering C. Petitpierre

Use of a sequence diagram

Main

Object B

Start of the thread(calls method run)

Method executed at the same time asmethod run or method xMeth.

run ( )foo ( )

start ( )

return

Object X

xMeth ( )

new ( )

The example explains how the Java threads work

Page 31: Génie logiciel Software Engineering C. Petitpierre

Corresponding code: 1st solution

public class Main { static ActiveObject a1; static public void main (String [] args) { a1 = new ActiveObject (); // create an active object a1.start(); // start the active object a1.foo();} }

class ActiveObject extends Thread { public void foo() { } public void run () { for (;;) { System.out.println("ActiveObject running"); try { Thread.sleep(3000); } catch (Exception e) {}} } }

Page 32: Génie logiciel Software Engineering C. Petitpierre

Corresponding code: 2nd solution

public class Main { static AnObject a2; static public void main (String [] args) { a2 = new AnObject (); // create an active object new Thread(a2).start(); // start the active object a2.foo() { }} }

class AnObject implements Runnable { public void foo() { } public void run () { for (;;) { System.out.println("AnObject running"); try { Thread.sleep(2000); } catch (Exception e) {}} } }

Page 33: Génie logiciel Software Engineering C. Petitpierre

Use of sequence diagramsThreaded object 2

position of the wait ( ) (blocking)

run ( )

Threaded object 1

run ( )

Semaphore

position of the notify ( ) (non blocking)

stop ( )

kick ( )

Explains how the wait-notify commands work: see code next slide

positions of synch- ronized statements

allows only one thread at a time

stop(), kick() areuser-defined methods

Page 34: Génie logiciel Software Engineering C. Petitpierre

Code corresponding to the sequence diagram

class T1 implements Runnable { Sem tm; public T1 (Sem t) { tm = t; } public void run () { for (;;) { tm.stop(); } }}

class Sem { public void kick () { synchronized (this) { notify(); } } public synchronized void stop () { try { wait(); } catch (InterruptedException ie) {} }}

class T2 implements Runnable { Sem tm; public T2 (Sem t) { tm = t; }

public void run () { for (;;) { tm.kick(); Thread.sleep(1000); } }}

There are two different ways of using synchronized.

Page 35: Génie logiciel Software Engineering C. Petitpierre

Creation of the previous threads

sem = new Sem();

new Thread(new T1(sem)).start();

new Thread(new T2(sem)).start();

Page 36: Génie logiciel Software Engineering C. Petitpierre

Yet another way of using synchronize

class Sem { String s = “” // empty string, or any object public void kick () { synchronized (s) { notify(); } } public void stop () { synchronized (s) { try { wait(); } catch (InterruptedException ie) {} } }}

Every Java object has provision for thread synchronization

Page 37: Génie logiciel Software Engineering C. Petitpierre

Development Process

Page 38: Génie logiciel Software Engineering C. Petitpierre

Well-known development processes

• RUP (Rational Unified Process)

• CMMI (Capability Maturity Model Integration)

• Agile / XP (eXtreme Programming)

Page 39: Génie logiciel Software Engineering C. Petitpierre

Waterfall Development Process

Analysis

Design

Implementation

Testing

Maintenance

Civil engineering:

One first draws plans and only then are they realized !

Why wouldn’t it work with software ?

?

Page 40: Génie logiciel Software Engineering C. Petitpierre

Iterative Process (spiral)

AnalysisDesign

ImplementationTest

Superficial analysis, design, implementation and test of the whole application, then better analysis, design, implementation and test, and improvement at each revolution ?

or ?

Thorough analysis, design, implementation and test of a part, and then analysis, design, implementation and test of a new part at each revolution ?

Development

Maintenance

Page 41: Génie logiciel Software Engineering C. Petitpierre

Agile Development Process

Most important characteristics:

No long term planning. Deliver working

software frequently

(from a couple of weeks to a couple of months,

with a preference to the shorter timescale).

Page 42: Génie logiciel Software Engineering C. Petitpierre

RUP

Page 43: Génie logiciel Software Engineering C. Petitpierre

RUP: Rational Unified Process

• For the project manager

• What is important in a project

• What leads to failures

• Working team composition

• Management tools

• Very little on how to do things !

Page 44: Génie logiciel Software Engineering C. Petitpierre

RUP: Warning

What is Rational's RUP ?

It is a methodology. But to sell it, Rational supplies a bunch of html pages (about 16000 pages). There are some documentation templates also. A warning though, if you are thinking to get into a good methodology in reasonable time, then you need to rethink, RUP will take a looooooooooong time to grasp, implement and finally there is a 50% risk that you will never reap the benefits.

http://www.theserverside.com

Page 45: Génie logiciel Software Engineering C. Petitpierre

RUPAvailable on a CD-Rom that must be customized.Accompanied by : P. Kruchten,“The Rational Unified Process: an Introduction”,

Characteristics and best practices:1. Iterative process

2. Requirement management

3. Architecture and use of components

4. Modeling and the UML

5. Quality of development process and product

6. Change management (tools)

Page 46: Génie logiciel Software Engineering C. Petitpierre

RUP: 1 - Iterations

Page 47: Génie logiciel Software Engineering C. Petitpierre

RUP2 - Requirement management

– Requirements are stakeholders’ needs, goals and wishes. (stakeholders - parties prenantes = contractor, customers, users, employees)

– (FURPS: functionality, usability, reliability, performance and supportability)

– URSP = non functional requirements

Page 48: Génie logiciel Software Engineering C. Petitpierre

RUP3 - Architecture

• Components:– A nontrivial piece of software, a module, a

package, a subsystem, a layer, major classes– CORBA (remote objects), ActiveX, JavaBeans,

a Web page, database table– Mechanisms such as persistency and

communication tool, patterns (MVC, ORB object request broker . . .)

Page 49: Génie logiciel Software Engineering C. Petitpierre

RUP4 - UML and modeling

Use case diagram for an ATM

(automate de banque)

Withdraw Money

Check Balance

TransferMoney

Open Account <<include>>

<<include>>

Page 50: Génie logiciel Software Engineering C. Petitpierre

RUP: 4 - UML and modelingA scenario or use case (the term use case is more general)

1. A client inserts a card into the ATM.

2. The system reads and validates the card information.

3. The system prompts for a PIN.

4. The client enters the PIN. client, system = actors

5. The system validates the PIN

6. The client selects “Withdraw Money”

7. The client enters the requested amount.

8. The system requests the amount from the client’s account.

9. The system asks the client to remove the card.

10.The system dispenses the requested amount from the banknote buffer(only done if the requested amount has been granted in 8).

Page 51: Génie logiciel Software Engineering C. Petitpierre

RUP: 4 - Collaboration diagram

P. Kruchten, The Rational Unified Process – An Introduction, Addison-Wesley

Page 52: Génie logiciel Software Engineering C. Petitpierre

RUP: 5 - Quality• Quality:

– Reliability (no bug)– Functionality (does what it is meant for)– Performance

• Tests:– Unit tests– Integration tests (interactions of units)– System test (complete application)– Acceptance test (same, but performed by the buyer)– Regression tests (repetition of previous tests to

assure that the new features have not introduced bugs in the former part)

Page 53: Génie logiciel Software Engineering C. Petitpierre

RUP: 6 - Change management

• ClearQuest – Tool for change request management

• ClearCase– Tool for configuration management

Page 54: Génie logiciel Software Engineering C. Petitpierre

CMMI

Page 55: Génie logiciel Software Engineering C. Petitpierre

CMM - CMMI

• Capability Maturity Model(developed by the Software Engineering Institute of CMU)

• Capability Maturity Model Integration(upgrade of CMM)

• http://ltiwww.epfl.ch/~petitp/GenieLogiciel/CToMFeb02.pdf

(article by a RUP vendor, excerpts on the next slides)

Page 56: Génie logiciel Software Engineering C. Petitpierre

CMMI

Level 1 (initial)

Represents a process maturity characterized by

unpredictable results.

Ad hoc approaches, methods, notations, tools, and reactive management translate into a process dependent predominantly on the skills of the team to succeed.

Page 57: Génie logiciel Software Engineering C. Petitpierre

CMMILevel 2 (managed)

Represents a process maturity characterized by

repeatable project performance.

The organization uses foundation disciplines for

requirements management; project planning; project

monitoring and control; supplier agreement management;

product and process quality assurance; configuration

management and measurement/analysis.

For Level 2, the key process focus is on project-level

activities and practices.

Page 58: Génie logiciel Software Engineering C. Petitpierre

CMMILevel 3 (defined)

Represents a process maturity characterized by improving project performance within an organization. Consistent, cross-project disciplines for Level 2 kpas (key process areas) are emphasized to establish organization-level activities and practices.

Additional organizational process areas include:

Requirements development, technical solution, product integration, verification, validation, risk management, organizational training, organizational process focus, decision analysis and resolution, organizational process definition, integrated project management

Page 59: Génie logiciel Software Engineering C. Petitpierre

What are risks ?

If your customers need a new system by a specific date the risk is high. If that system is a new challenge for your software group the risk is even greater. If that system is a new challenge to the entire software industry the risk is still greater even.

Unsatisfied employees also participate in the risk.

Page 60: Génie logiciel Software Engineering C. Petitpierre

CMMILevel 4 (quantitatively managed)

Represents a process maturity characterized by improving organizational performance.

Historical results for Level 3 projects can be exploited to make trade offs, with predictable results, among competing dimensions of business performance (cost, quality, timeliness).

Additional Level 4 process areas include:– Organizational process performance: setting norms and

benchmarks for process performance.– Quantitative project management: executing projects

based on statistical quality-control methods.

Page 61: Génie logiciel Software Engineering C. Petitpierre

CMMILevel 5 (optimized)

Represents a process maturity characterized by rapidly reconfigurable organizational performance as well as quantitative, continuous process improvement.

Additional Level 5 process areas include:

– Causal analysis and resolution: proactive fault avoidance and best practice reinforcement.

– Organizational innovation and deployment: establishing a learning organization that organically adapts and improves.

(few companies arrive at that level)

Page 62: Génie logiciel Software Engineering C. Petitpierre

Agile Development Processes

XProgramming

Page 63: Génie logiciel Software Engineering C. Petitpierre

Agile Development Process

Most important characteristics:

No long term planning. Deliver working

software frequently, from a couple of weeks

to a couple of months, with a preference to

the shorter timescale.

http://agilemanifesto.orghttp://martinfowler.com

http://www.ambysoft.com/

Page 64: Génie logiciel Software Engineering C. Petitpierre

XProgramming

Complaint and excuse of the programmer:

“the problem with this project is that the requirements are always changing”

Actually it is always and will always be the case, we must thus do with it !

XProgramming

(http://www.extremeprogramming.org)

Page 65: Génie logiciel Software Engineering C. Petitpierre

XProgramming

PlanningDesigningCodingTesting

2-6 weeksof a slice

Page 66: Génie logiciel Software Engineering C. Petitpierre

XProgramming

• No global up front planning• Slices (meaningful slices) defined with

the customer• Created quickly (2-6 weeks)• Accepted by the customer

Early feedback and impact on the requirements

• Pair programming !!

Page 67: Génie logiciel Software Engineering C. Petitpierre

XProgramming

Planning

– User stories are written.– Release planning creates the schedule.– Make frequent small releases.– The project velocity is measured.– The project is divided into iterations.– Iteration planning starts each iteration.– Move people around.– A stand-up meeting starts each day.– Fix XP when it breaks.

Page 68: Génie logiciel Software Engineering C. Petitpierre

XProgrammingDesigning

– Simplicity– Choose a system metaphor.– Use CRC1 cards for design sessions.– Create spike solutions (for difficult problems)

to reduce risk.– No functionality is added early.– Refactor whenever and wherever possible.

1 Class-Responsibility-Collaboration

Page 69: Génie logiciel Software Engineering C. Petitpierre

XProgramming

Coding

– The customer is always available.– Code must be written to agreed standards.– Code the unit test first.– All production code is pair programmed.– Only one pair integrates code at a time (CVS).– Integrate often.– Use collective code ownership.– Leave optimization till last.– No overtime.

Page 70: Génie logiciel Software Engineering C. Petitpierre

XProgramming

Testing

– All code must have unit tests.– All code must pass all unit tests before

it can be released.– When a bug is found tests are created.– Acceptance tests are run often and the

score is published.

Page 71: Génie logiciel Software Engineering C. Petitpierre

XProgramming

• Documentation is a planned task and the customer pays for it (some documentation must be integrated in the source code)

• Teams are from 2 to 12 persons

• A CVS (concurrent versioning system) is of course mandatory

Page 72: Génie logiciel Software Engineering C. Petitpierre

XProgramming

http://www.extremeprogramming.org

Page 73: Génie logiciel Software Engineering C. Petitpierre

TDD

Page 74: Génie logiciel Software Engineering C. Petitpierre

TDD: Test Driven Development

– Write a test before any real code writing

On Eclipse

– JUnit 1.3.8: Java 1.4

– JUnit 4: Java 5.0 with annotations

Page 75: Génie logiciel Software Engineering C. Petitpierre

TDD: Test Driven Development

Documentation Eclipse:

• Help > Help Contents > Java Development User Guide > Getting Started > Basic Tutorial > Writing and running JUnit tests (1.3.8)

• Help > Help Contents > Java Development User Guide > What’s new > JUnit Toolings (4)

• (http://www.junit.org) JUnit 4.0 in 10 minutes

Page 76: Génie logiciel Software Engineering C. Petitpierre

TDD

• Create a Java project as usual

• Project > Build Path > Add Libraries… > JUnit 4

• Right-click the class that will be under test (possibly with an empty method) > New > JUnit Test Case (creates a case of the version entered into the build path)

• Define a package that is going to contain the tests

Page 77: Génie logiciel Software Engineering C. Petitpierre

TDDEdit the test class:

– Create an instantiation of the Class under test in the @BeforeClass method (once for all methods) or in the @Before method (once for every method)

– Put one test (CTRL-space) per test method. If you put several tests, they will not be identified separately when there is an error.

– The message in an assertion is displayed if there is an error

– It is possible to check the kind of Exception returned by the method under test (see doc)

Page 78: Génie logiciel Software Engineering C. Petitpierre

TDD

package unitTests;

import static org.junit.*;

public class ComputationTest1 {static example.Computation computation = null;

/** * This method is executed only once before all tests * Here, it creates an environment to test the modules */

@BeforeClasspublic static void setUp() throws Exception {

computation = new example.Computation();computation.setResult(0);

}

Page 79: Génie logiciel Software Engineering C. Petitpierre

TDDpackage unitTests;import static org.junit.Assert.*;import org.junit.After;import org.junit.Before;import org.junit.Test;import org.junit.BeforeClass;

public class ComputationTest1 {static example.Computation computation = null;

/** * The following method is repeated before every test */

@Before public void setUpRepeated() throws Exception {

computation = new example.Computation();computation.setResult(0);

} . . .

Page 80: Génie logiciel Software Engineering C. Petitpierre

TDD. . .@Afterpublic void tearDown() throws Exception {}@Testpublic void testComputation() {}@Testpublic void testAdd1() {

computation.add(7);// To show an error in a test, the next check is incorrect !assertTrue("Error 1 of computation", computation.getResult()==6);

}@Testpublic void testAdd2() {

computation.add(-12);assertTrue("Error 2 of computation", computation.getResult()==-5);

}}

Page 81: Génie logiciel Software Engineering C. Petitpierre

TDD: running the tests

• Select some test classes or the test package

• Right click the selection > Run As > JUnit Test

• The result is displayed in the view JUnit (same window as the Package Explorer)

Page 82: Génie logiciel Software Engineering C. Petitpierre

Exercice

/****** This is a test program with 5 lines of code//*****//***/// Slightly pathological comment ending...

public class Hello { public static void main(String [] args) { // comment // Say hello System./*wait*/out./*for*/println/*it*/(“Hello/*”); }}

Develop a class with a method that counts the lines that are not empty nor just contain comments, creating tests for each new code increment.

As soon as you have a idea to start the problem, create a test, implement this first part and test it. For each new increment, do the same.

Don’t think too much beforehand, just try and test, but keep all tests and improve/refactor your code

Use pair programming

Page 83: Génie logiciel Software Engineering C. Petitpierre

Design Patterns

http://en.wikipedia.org/wiki/Design_Patternshttp://en.wikipedia.org/wiki/Design_pattern_(computer_science)

See also anti-patterns in Wikipedia and http://ltiwww.epfl.ch/~petitp/GenieLogiciel/PointCounterPoint.pdf

Page 84: Génie logiciel Software Engineering C. Petitpierre

Design Patterns

Christopher Alexander is an architect noted for his theories about design. He produced and validated a pattern language designed to empower any human being to design and build at any scale.

The concept of design patterns has been reused in IT by E. Gamma, R Helm, R. Johnson and J. Vlissides: also known as the Gang of Four or GoF. They have sold 500.000 copies of their book.

Abstract factory, Adapter, Composite, Decorator, Factory methods, Observer, Strategy, Template method…

E. Gamma is currently heading the Eclipse project

Other authors have written books about patterns

Page 85: Génie logiciel Software Engineering C. Petitpierre

Design Patterns (basic concepts)

class SomeClass extends SuperClass{

private String str;

public String getString() {

return str;}

}

Signature

All signatures = type (or subtype)

The whole = class (subclass or derived class)

The subclass inherits (extends) the superclass

Page 86: Génie logiciel Software Engineering C. Petitpierre

Design Patterns

• An object is an instance of a class

• An abstract class has abstract operations

• A concrete class is one that is not abstract

• A concrete class that inherits an abstract class must override the abstract operations

• A first-class operator or function is one that can be defined during the execution of a program, stored in a variable, passed as arguments to other functions, and returned as the values of other functions.

Page 87: Génie logiciel Software Engineering C. Petitpierre

Inheritance / Composition / Forward

class SuperClass {

private String name;

public String getName() { return name; }

}

class InheritanceClass extends SuperClass{

}

ci = new InheritanceClass ();

ci.getName();

Page 88: Génie logiciel Software Engineering C. Petitpierre

Inheritance / Composition / Forward

class SuperClass {

private String name;

public String getName() { return name; }

}

class CompositionClass {

SuperClass element;

}

cc = new CompositionClass()cc.element.getName()

Page 89: Génie logiciel Software Engineering C. Petitpierre

Inheritance / Composition / Forward

class SuperClass {

private String name;

public String getName() { return name; }

}

class ForwardClass {

SuperClass element;

public String getName() {

return element.getName();

}

} Cd = new ForwardClass();cd.getName();

Page 90: Génie logiciel Software Engineering C. Petitpierre

Delegation = composition + forward + environment

class SuperClass {

private String name;

public String getName(DelegationClass env) {

return env.xxxxx+name;

} }

cd = new DelegationClass()

class DelegationClass { cd.getName()

SuperClass element;

String xxxxx;

public String getName() { return element.getName(this); }

} // see GoF’s state design pattern for an example

Page 91: Génie logiciel Software Engineering C. Petitpierre

Two GoF principles

• Program to an interface, not an implementation

• Favor object composition over class inheritance

Page 92: Génie logiciel Software Engineering C. Petitpierre

Declare interfaces, not classes,

public interface Interface {

public String method();

}

public class SubClass implements Interface{

public String method() {

return null;

}

} BUT…

Page 93: Génie logiciel Software Engineering C. Petitpierre

…debugging and maintenance become difficult !Example:

public class Application {

Interface intf;

public static void main(String[] args) {

Application a = new Application();

a.intf = new SubClass();

a.execute(args);

}

void execute(String[] args) {

intf.method();} } Where do I find the

source of method() ?

Page 94: Génie logiciel Software Engineering C. Petitpierre

Note that you don’t need to implement a new interface to insert new attributes !! If an attribute is added to an object, it does not disturbs the other uses of the object.

Refactoring may also be called to rescue !

Page 95: Génie logiciel Software Engineering C. Petitpierre

The GoF patterns

Design Patterns – Elements of Reusable Object-Oriented Software,E. Gamma…

Page 96: Génie logiciel Software Engineering C. Petitpierre

Inheritance (in GoF’s book)

Aaaa

Operation()

Bbbb

Operation()

Leaf

Operation()

Aaaa

Operation()

Bbbb

Operation()

Leaf

Operation()

identical

Page 97: Génie logiciel Software Engineering C. Petitpierre

SingletonClass1

Class2

Class3

Singleton

Only one singleton is instantiated

One does not know the order in which the Classi are instantiated

All Classi are not always present, they have no references to each other and there may be other such classes later

Who does create the Singleton ?

Page 98: Génie logiciel Software Engineering C. Petitpierre

Singleton

public class ClassicSingleton {

private static ClassicSingleton instance = null;

protected ClassicSingleton() { // Exists only to defeat instantiation }

public static ClassicSingleton getInstance() {

if (instance == null) {

instance = new ClassicSingleton();

}

return instance; used in place of new ClassicSingleton()

} }

// from Javaworld

Page 99: Génie logiciel Software Engineering C. Petitpierre

Singletons

• Global variable !

• Don’t overuse them !

• Only for data that are meaningful in the whole program

• Not more than a few singletons in a program

Page 100: Génie logiciel Software Engineering C. Petitpierre

(Complex) example of use

Threadlocal is a singleton that may be attached to the current thread, the one that executes the code of the current method.

It is managed by the JVM.

Page 101: Génie logiciel Software Engineering C. Petitpierre

TheadLocal singleton

Thread1

Thread2

The class introduced into ThreadLocal can be accessed in the following way:

x = HolderObject.get() x = HolderObject.get() x = HolderObject.get()

y = HolderObject.get() y = HolderObject.get()

Thanks to the JVM, there is one singleton per thread,

x != y, x always the same, y always the same

Page 102: Génie logiciel Software Engineering C. Petitpierre

(Complex) example of useclass HolderObject {

public static ThreadLocal<MyObject> // definition of an attribute

currentObject = new ThreadLocal<MyObject>() {

protected synchronized MyObject initialValue() {

return new MyObject();

}

};

public static MyObject get() { // any object can be kept in ThreadLocal

return currentObject.get();

} }

// At the initialization, the object ThreadLocal calls method initValue(),

// defined by the developer. This method returns an object.

// This object is then stored in ThreadLocal located in currentObject.

// Moreover, the JVM saves and restores this object at each context switch

Page 103: Génie logiciel Software Engineering C. Petitpierre

(Complex) example of useclass HolderObject {

public static ThreadLocal< HolderObject >

currentObject = new ThreadLocal< HolderObject >() {

protected synchronized HolderObject initialValue() {

return new HolderObject ();

}

};

public static HolderObject get() {

return currentObject.get();

}

Type userAttribute = “initval”;

}

// Usually the object that is stored is the HolderObject itself

Page 104: Génie logiciel Software Engineering C. Petitpierre

ThreadLocal

• Process support (task control block, semaphore, identifier)

• Transaction manager (EJB3)

Can be used to replace parameters in a method call, but in very specific situations, such as

Page 105: Génie logiciel Software Engineering C. Petitpierre

Exercice 2

Créer un object dont la méthode run est exécutée sur un thread.

Cette méthode contient une boucle infinie et affiche toutes les secondes un identificateur unique mémorisé dans le singleton ThreadLocal du thread.

Créer deux de ces objets et lancez-les sur deux threads.

Pour générer des identificateurs uniques, utiliser un deuxième singleton (global celui-là).

Attention, sa méthode doit utiliser synchronized !

Page 106: Génie logiciel Software Engineering C. Petitpierre

class Singleton { static Singleton single = null; int i = 10; public static Singleton instantiate() { if (single == null) { single = new Singleton(); } return single; } public int get() { return i++; }}

Quand on a obtenu un ID, il ne faut plus utiliser le singleton depuis le même thread, car les autres objets feront changer le contenu de la variable utilisée pour générer les Ids.

new Thread(new Thr()).start();new Thread(new Thr()).start();

Singleton retournant un ID unique

Page 107: Génie logiciel Software Engineering C. Petitpierre

class HolderObject { public static ThreadLocal<HolderObject> currentObject = new ThreadLocal<HolderObject>() { protected synchronized HolderObject initialValue() { return new HolderObject(); } }; public static String getString() { return currentObject.get().str; } public static void setString(String s) { currentObject.get().str = s; } String str = null;}

Un singleton par thread. On peut faire plusieurs fois getString() dans chaque thread. Chaque thread verra sa propre valeur.

Creation d’un objet ThreadLocal

Page 108: Génie logiciel Software Engineering C. Petitpierre

Class or object adapter

Goal:

The class adapter implements a new interface that provides a new functionality or an existing functionality under a new name.

In the class adapter, the code that implements or support the new functionality is called from an auxiliary object that extends the object with the available functionality.

The object adapter delegates the call to the available object.

Page 109: Génie logiciel Software Engineering C. Petitpierre

Design Pattern: Adapter (Inheritance / Composition / Delegation)+Interface

Existing class

Required interface

Adapter

Just forwards the calls

client

Page 110: Génie logiciel Software Engineering C. Petitpierre

Design Pattern: Adapter

Existing class

Required interface

Adapter

Just forwards the calls

client

Existing object

Two different possibilities

Also possible

Page 111: Génie logiciel Software Engineering C. Petitpierre

Java implementation of a class adapter

/* Adapt DList class to Stack interface */

class DListImpStack extends DList implements Stack {public void push (Object o) {

insertTail (o);} // forwards the calls

} Adapter

interface Stack {void push (Object o);

}

/* Double Linked List */

class DList {public void insertTail (Object o) { ... }

}

Page 112: Génie logiciel Software Engineering C. Petitpierre

Java implementation of a object adapter

/* Adapt DList class to Stack interface */

class DListImpStack implements Stack {DList dl = new DList ();public void push (Object o) {

dl.insertTail (o);}

}

interface Stack {void push (Object o);

}

/* Double Linked List */

class DList {public void insertTail (Object o) { ... }

}

Page 113: Génie logiciel Software Engineering C. Petitpierre

Composite: tree structure(one must be able to walk through and

add/remove groups or leaves in the same way)

supergroup

group square line

circle square

Model of a diagram

for a graphical application

Page 114: Génie logiciel Software Engineering C. Petitpierre

Composite

Component

Operation()Add(Component)Remove(Component)getChild(int)

Composite

Operation()Add(Component)Remove(Component)getChild(int)

Leaf

Operation()

Page 115: Génie logiciel Software Engineering C. Petitpierre

Implementation of the Compositeabstract class GraphicComponent {

abstract public void print();}

class CompositeGraphic extends GraphicComponent {

private ArrayList<Graphic> mChildGraphics = new ArrayList<Graphic>();

public void print() {for (Graphic graphic : mChildGraphics) {graphic.print();

}}

} Groupclass Ellipse extends GraphicComponent {

public void print() {System.out.println("Ellipse");

}} Leaf- All nodes are GraphicComponent

with a print() method

- root.print() prints all leaves

Page 116: Génie logiciel Software Engineering C. Petitpierre

Composite: object diagram

supergroup

group square line

circle square

Each object extends abstract class GraphicComponent to make all objects compatibles

Page 117: Génie logiciel Software Engineering C. Petitpierre

Composite: other implementation details

• Parent references may be handled

• But if parents are multiple reverse path ambiguous Flyweight

Page 118: Génie logiciel Software Engineering C. Petitpierre

Composite: other implementation details

Where to define the children list and the getChild method ?

• Component class (abstract class)–all elements similar (transparency)

–but one may try to retrieve a child from a leaf

• Composite class –one can check that elements are retrieved

only from composite (safety)

–But elements are dissimilar

Page 119: Génie logiciel Software Engineering C. Petitpierre

Decorator

BufferedReader br =

new BufferedReader(

new InputStreamReader(

new ByteArrayInputStream(

“A text to read”.getBytes()

) )

);

Page 120: Génie logiciel Software Engineering C. Petitpierre

Decorator (class diagram)

Page 121: Génie logiciel Software Engineering C. Petitpierre

Decorator

• More flexibility than inheritance• Several identities (addresses) !• Keep interface simple• Decorator’s abstract class optional• For more complex cases Strategy

Page 122: Génie logiciel Software Engineering C. Petitpierre

Decorator (object diagram)

HScrollDecorator

Constructor(x) { super(x) }

VScrollDecorator

Constructor(x) { super(x) }

SimpleWindow

WindowDecorator

Window decorWindow

Constructor(x) { decorWindow = x }

WindowDecorator

Window decorWindow

Constructor(x) { decorWindow = x }

Window (interface)

draw()

Window (interface)

draw()

Window (interface)

draw()

x = new HScrollDecorator (new VScrollDecorator (new SimpleWindow()));

Page 123: Génie logiciel Software Engineering C. Petitpierre

Decorator

HScrollDecorator

Constructor(x) { super(x) }

draw()

VScrollDecorator

Constructor(x) { super(x) }

draw()

SimpleWindow

draw()

public void draw() {

drawVerticalScrollBar();

decoratedWindow.draw();

}

public void draw() {

drawHorizontalScrollBar();

decoratedWindow.draw();

}

Window (interface)

draw()

Page 124: Génie logiciel Software Engineering C. Petitpierre

Decorator

HScrollDecorator

Constructor(x) { super(x) }

getDescription()

VScrollDecorator

Constructor(x) { super(x) }

getDescription()

SimpleWindow

getDescription()

public String getDescription() {

return decoratedWindow.getDescription() + ", including vertical scrollbars";

}

public String getDescription() {

return decoratedWindow.getDescription() + ", including horizontal scrollbars";

}

public String getDescription() {

return "simple window";

}

Page 125: Génie logiciel Software Engineering C. Petitpierre

Decorator (without the intermediary abstract classes)

HScrollDecorator

Window decorWindow

Constructor(x) { super(x) decorWindow = x }

VScrollDecorator

Window decorWindow

Constructor(x) { super(x) decorWindow = x }

SimpleWindow

Window (interface)

draw()

Window (interface)

draw()

Window (interface)

draw()

Page 126: Génie logiciel Software Engineering C. Petitpierre

Façade(simply relays calls to a set of methods

an example is the Session Enterprise Java Beans)

Class

Class

Class

Class

Facade

Page 127: Génie logiciel Software Engineering C. Petitpierre

Bridge

(avoids the following situation)Window

OS independ.

XWindow

OS X

YWindow

OS Y

XWindow

OS X

YWindow

OS Y

NewWindow

OS independ.

One must create two distinct sources, but their sole difference is

“extends Window”

versus “extends NewWindow”

Two hierarchies interleaved

Page 128: Génie logiciel Software Engineering C. Petitpierre

OS Implementation

OS independent hierarchy

abstract class

Bridge (the red-blue lines)

Window

XWindow

OS X

YWindow

OS Y

IconWindowSimpleWindow

FramedIcWindow

Either red or blue is instantiated, at run time

Page 129: Génie logiciel Software Engineering C. Petitpierre

BridgePatternExample.java(as in the CVS, project Patterns)

Shape

drawingAPI

resizeByPercentage()

DrawingAPI1

drawCircle()

DrawingAPI

drawCircle()

CircleShape

draw()

<<exclusifs>>

another variant

drawingAPI

DrawingAPI2

drawCircle()

Page 130: Génie logiciel Software Engineering C. Petitpierre

Factories• Abstract Factory

The client gets a factory corresponding to a specified domain and then generates objects by calling it. All generated objects belong to the specified domain.

• Factory MethodThe client gets objects that are created according to some individual characteristic.The objects of the same application may belong to different domains.

Abstract factories are implemented with the help of factory methods !

Page 131: Génie logiciel Software Engineering C. Petitpierre

Abstract Factory

Factory1

create()<<create object>>

Client

Factory2

create()<<create object>>

ConcreteWindow1 ConcreteWindow1

Of course the factories also inherits a common interface, not shown here

Page 132: Génie logiciel Software Engineering C. Petitpierre

Abstract factory (with interfaces)

AbstractFactory

staticCreateFactory()

CreateProductA()CreateProductB()

ConcreteFactory1

CreateProductA()CreateProductB()

ConcreteFactory2

CreateProductA()CreateProductB()

AbstractProductA

ConcreteProductA1 ConcreteProductA2

AbstractProductB

ConcreteProductB1 ConcreteProductB2

<<create>>

Client

Page 133: Génie logiciel Software Engineering C. Petitpierre

Factory Method

AbstractCreator

factoryMethod(param)

ConcreteCreator

factoryMethod(param) // knows from param // which object to build // “xx.jpg” / “xx.gif”

Product

Client

create object of type x or y

The same factory creates different objects

Page 134: Génie logiciel Software Engineering C. Petitpierre

A Simple Factory Method Pattern

class Complex {public static Complex fromCartesian(double real, double imag) {

return new Complex(real, imag);}

public static Complex fromPolar(double rho, double theta) {return new Complex(rho * java.lang.Math.cos(theta),

rho * java.lang.Math.sin(theta));}

private Complex(double a, double b) {// ...

} }

One method for each kind of object because it is not possible to differentiate them by their parameters.

Page 135: Génie logiciel Software Engineering C. Petitpierre

Créer une factory qui génère les composants suivants:

1. Factory de fenêtres GUI2. Factory d'objets qui utilisent la console d'Eclipse

● La factory à créer est spécifiée dans une propriété● Les méthodes read du GUI et de la console sont

bloquantes

Exercice 3

Page 136: Génie logiciel Software Engineering C. Petitpierre

// From the user properties:

Properties myProperties = new Properties();FileInputStream

in = new FileInputStream("myProp.properties");myProperties.load(in);in.close();String dType = myProperties.getProperty("displayType");

// From the system properties:

dtype = System.getProperty("terminalType");

Properties

Page 137: Génie logiciel Software Engineering C. Petitpierre

Object semaphore = new Object();

synchronized (semaphore) { semaphore.wait();

}

synchronized (semaphore) {semaphore.notify();

};

Thread 1 Thread 2

1

3

2

Synchronisations of threads

If the call to notify() is done before the call to wait() the wait() will wait the next call to notify(). One should thus memorize the signal in an attribute

suspended

Page 138: Génie logiciel Software Engineering C. Petitpierre

Instanciation

String dType = "pack.Classname";

Class dFactoryClass = Class.forName(dType);

dFactoryClass.newInstance();

Appel d'une classe statique

Class dFactoryClass = Class.forName(dType);

Method meth = dFactoryClass.getMethod("getDisplayFactory", new Class[0]);

DisplayFactory dFactory = (DisplayFactory)meth.invoke(null, new Object[0]);

Objet sur lequel la méthode est appelée (pas d'objet ici, donc appel statique)

Paramètres (type, puis valeurs)

Java Reflection

Page 139: Génie logiciel Software Engineering C. Petitpierre

Drawback of Reflection

• The availability of the class called in by reflection is only checked at runtime.

• In order to clean an application, an IT team in a bank had eliminated all programs that had not been used for 6 months. At the December, 31 closure, the programs had been destroyed …..

Page 140: Génie logiciel Software Engineering C. Petitpierre

Flyweight(poids mouche, poids plume)

• the program must handle lists containing many pieces

• many of them are similar

• using an object for each one would use up much memory space

• a typical example is a text, in which each letter has specific parameters (font, face, size…)

Page 141: Génie logiciel Software Engineering C. Petitpierre

HashMap<SpecialChar>

Flyweight

GraphicCharFactory

pool

get (char, font): SpecialCharH

ArialL

TimesE

TimesO

Arial

ArrayList <SpecialChar> text (only pointers)get returns the pointer to the SpecialChar, and creates it if it does not exist already.

(flyweight pool)

Page 142: Génie logiciel Software Engineering C. Petitpierre

Flyweight

The GoF book describes the flyweight within a hierarchy, but the hierarchy is independent from the flyweight pattern.

The Flyweight is used only at the line level.

page

paragraph paragraph paragraph

line line line line

Page 143: Génie logiciel Software Engineering C. Petitpierre

GraphicCharFactory

pool

get(character, fontFace)

FlyweightExample

text

main()

<<HashMap>>

<<ArrayList>>

FlyweightExample.java(as in CVS, project Patterns)

GraphicChar

String fontFace

printAtPosition(c, x)

Page 144: Génie logiciel Software Engineering C. Petitpierre

Observer

Subject

Observer

Observer

callcall

callEach time the subject is called, it calls a method in all the observers.

Thus at the end of each method called in the subject, there is a call to the list of observers.

The observer are registered, sometimes by themselves

The observers must of course have a common interface.

They are also called listeners!

Page 145: Génie logiciel Software Engineering C. Petitpierre

Observer

Subject

void notify() { for (observer o: pool) { o.update() }}

pool

Observer1

update()

Observer2

update()

Observer3

update()

Event

Page 146: Génie logiciel Software Engineering C. Petitpierre

Observer

Observer– update()– it often register itself in the subject

Subject– notify()– addObserver()– removeObserver()

Page 147: Génie logiciel Software Engineering C. Petitpierre

Template (simple use of inheritance)

Algorithm expressed as a sequence of operations.

These operations must be replaced easily in the source

operation 1 operation 2 …

Page 148: Génie logiciel Software Engineering C. Petitpierre

Template Method (trivial)

AbstractClass

templateMethodprimitiveOperation1primitiveOperation2

ConcreteClass

primitiveOperation1primitiveOperation2

void templateMethod() {

primitiveOperation1();

for (i=0; i<5;i++)

primitiveOperation2();

}

Different concrete classes implement different algorithms with the same sequence of operations

Page 149: Génie logiciel Software Engineering C. Petitpierre

Strategy

• A user class requires one algorithm chosen among a set of algorithms for its execution

• The algorithm is performed within some context, which contains the data.

• At initialization time, the current algorithm is set and then called by delegation

• Template with delegation• Similar to bridge

(Bridge structure; Strategy behavior)

Page 150: Génie logiciel Software Engineering C. Petitpierre

Strategy

Context

currentAlgorithm

contextInterface()

<< interface >>Strategy

algorithm()

ConcreteStrategyB

algorithm()

ConcreteStrategyA

algorithm()

ConcreteStrategyC

algorithm()

Client

1. Set the algorithm reference in the context

2. The algorithm is called from the context

3. The algorithm may have access to the context

Page 151: Génie logiciel Software Engineering C. Petitpierre

Strategy (usage)

// Three contexts following different strategies

context = new Context(new ConcreteStrategyA());

context.execute();

context = new Context(new ConcreteStrategyB());

context.execute();

context = new Context(new ConcreteStrategyC());

context.execute();

Page 152: Génie logiciel Software Engineering C. Petitpierre

Builder

Builder (similar to the strategy)

RTFReader

builder

ParseRTF()

<< interface >>TextConverter

ConvertChar(char)ConvertFontChange()ConvertParagraph()

TeXConverter

ConvertChar(char)ConvertFontChange()ConvertParagraph()getTeXText()

ASCIIConverter

ConvertChar(char)

getASCIIText()

TextWidgetConverter

ConvertChar(char)ConvertFontChange()ConvertParagraph()getTextWidget()

while (getNextToken) { switch (token) { case CHAR: builder.convertChar(token) break; case FONT: builder.convertFontChange(token) break; case PARA: . . .

Page 153: Génie logiciel Software Engineering C. Petitpierre

Builder

Director

builder

Construct()

<< interface >>Builder

buildPart()

ConcreteBuilder

buildPart()getResult()

for all objects in structure {

builder.buildPart()

}

Page 154: Génie logiciel Software Engineering C. Petitpierre

Chain of responsibility

This pattern allows a request to pass

along a chain of objects until one of

them handles it, thus giving multiple

objects a chance to handle the request.

Page 155: Génie logiciel Software Engineering C. Petitpierre

Chain of responsibility

aClientaHandler aConcreteHandler

successor anotherConcreteHandlersuccessor

Page 156: Génie logiciel Software Engineering C. Petitpierre

Chain of responsibility

Client

<< interface >>Handler

handleRequest()

ConcreteHandler1

handleRequest()

ConcreteHandler2

handleRequest()

successor

Page 157: Génie logiciel Software Engineering C. Petitpierre

Command

1. First class operation

2. The command is provided with the object that must be processed

3. The command may be stored and performed later

Page 158: Génie logiciel Software Engineering C. Petitpierre

Command Pattern

ConcreteCommand_2documentexecute()

Document

action()

ConcreteCommand_1documentexecute()

ConcreteCommand_3documentexecute()

The command is defined within an object. It can thus be passed over to other objects, it can be stored in a list, called at any time later and so on.

It is thus a mean to create a command as a first class operation.

The command also binds a command to a receiver (document)

Page 159: Génie logiciel Software Engineering C. Petitpierre

Command Pattern: undo

Useful to create undoable commands:

– The command receives the state of the document before the command is executed

– It defines an undo function that restores the previous state

– The commands are kept in a list, in the order of their execution

– Can be combined with the memento pattern

Page 160: Génie logiciel Software Engineering C. Petitpierre

Command Pattern

Invoker Command

execute()

ConcreteCommand

execute()

Receiver

action()

<<create and add command>>

<<create>>

Initializer

2

3

1

The commands can be stored in invokers, as in the observer pattern,

but here, the command contains a reference to a document.:

new ConcreteCommand(receiver)

Page 161: Génie logiciel Software Engineering C. Petitpierre

Command: when to use it

• A document is read and then operations triggered by menu items are performed when a user clicks them (~callback, listener)

• One must prepare a context and have operations performed at a later time

• Support undo (stack the commands)

• Support transactions (which may have to be undone)

Page 162: Génie logiciel Software Engineering C. Petitpierre

Memento

• Object used to save and later restore a state

OriginatorstatesetTo(Memento m)createMemento()

MementostategetState()setState()

CaretakerstatesetTo(Memento m)createMemento()

return new Memento(state) state = m.getState()

• The caretaker should no see the state, it must only store and retrieve it.

• Can be used by a Command object to maintain the state of the undo.

Page 163: Génie logiciel Software Engineering C. Petitpierre

Prototype

• Several objects with few variations must be created

• Their attribute values are only known at run time

• One instantiates a prototype and then clones it

Page 164: Génie logiciel Software Engineering C. Petitpierre

Cloning objects in Java

public class ToBeCloned implements Cloneable {

String s = “xxx";

int[] i = new int[] { 0,4,2 };

public ToBeCloned clone() {

try { // copies the simple attributes

ToBeCloned temp = (ToBeCloned ) super.clone();

temp.i = i.clone(); // an array must be cloned explicitly

return temp; // - Java defines clone() in arrays

} catch (CloneNotSupportedException cnse) {

return null;

}

}

} // for special constructs, the program must copy the contents explicitly

(not a pattern, butused in prototype)

Page 165: Génie logiciel Software Engineering C. Petitpierre

PrototypeClient

operation()

<< interface >>Prototype

clone()

ConcretePrototypeA

clone()

ConcretePrototypeB

ConcreteSubPrototypeC

clone()

ConcreteSubPrototypeD

clone()

operation () {

prototype = new ConcretePrototypeC();

p = prototype.clone();

}

Page 166: Génie logiciel Software Engineering C. Petitpierre

Proxies• Remote proxy

(proxy that forwards the calls to an object located in a remote site)

• Virtual proxy(e.g. an object that represents a figure that is loaded only when the figure appears on the current page. Used for optimization purpose)

• Protection proxy(an object that intercepts all calls to an object and checks if the caller has the right to call it)

• Handle(e.g. to maintain the number of links to the object to destroy it when the last link has been freed, referencing a persistent object to load it when it is first referenced or to map it on a key, to lock it, and so on)

Page 167: Génie logiciel Software Engineering C. Petitpierre

Proxy

aClientsubject aProxy

realSubject aRealSubject

Client

request()

<< interface >>Subject

request()

Proxy

request()

RealSubject

request()

Page 168: Génie logiciel Software Engineering C. Petitpierre

Iterator

Iterator

Item Item Item Item ItemHead

<<create>>

Page 169: Génie logiciel Software Engineering C. Petitpierre

• Provides a way to traverse an aggregation according to different policies, without introducing the policy into the list object

• Filtering can be introduced

• The iterator references the list and vice-versa: a creator method in the list must connect the two ( can be implemented as a factory)

Iterator

Page 170: Génie logiciel Software Engineering C. Petitpierre

Iterator: object diagramClient

Iterator

first()next()isDone()currentItem()removeItem()

ListIterator

Skip

AbstractList

createIterator()count()append(Object)removeItem(Object) . . .

SkipList

List

It is important to have a remove operation within the iterator, otherwise one cannot remove an element during the scan, because if the current element is removed without the iterator knowing it, it would not skip the missing element.

Page 171: Génie logiciel Software Engineering C. Petitpierre

Iterator: class diagramClient

Iterator

first()next()isDone()currentItem()

ConcreteIterator

Aggregate

createIterator()

ConcreteAggregate

createIterator()

return new ConcreteIterator(this)

Page 172: Génie logiciel Software Engineering C. Petitpierre

Mediator

• Many objects (called the colleagues) have connections between them

• The connections between the objects are managed by a central object: the mediator

Page 173: Génie logiciel Software Engineering C. Petitpierre

Mediator: implementation

• The accesses to the colleagues may be implemented according to the observer pattern or simply by delegation

• The colleagues may pass a reference to themselves (this) within the call to the mediator, to identify the callers

Page 174: Génie logiciel Software Engineering C. Petitpierre

Mediator: an object diagram

Colleague

ConcreteColleague1

ConcreteColleague2

Mediator

ConcreteMediator

Page 175: Génie logiciel Software Engineering C. Petitpierre

State, Interpreter and Visitor Patterns

• These patterns will be used in relation with the analysis of languages (XML or other)

• We will thus study SAX, DOM and Javacc (Java compiler’s compiler) in relation with these patterns.

• (See http://www.epflpress.org/Book_Pages/petitpierre.html)

Page 176: Génie logiciel Software Engineering C. Petitpierre

State Pattern

02

1

enter

display_francs

next

ignore

display_euros

previous

Page 177: Génie logiciel Software Engineering C. Petitpierre

State Pattern (one method to handle all actions)

Context

staterequest()

<< interface >>State

handle()

ConcreteStateA

handle()

ConcreteStateB

handle()

state.handle()

The handle() method determines the nature of the event that has occurred.

If it is not foreseen in some state, the method takes some corrective action.

Page 178: Génie logiciel Software Engineering C. Petitpierre

State Pattern (one method per action)

Context

stateaction1( )action2( )action3( )

State

action1( )action2( )action3( )

ConcreteStateA

action1( )

ConcreteStateB

action1( )

action3( )

EventGenerator

The action is determined by the event generator. If it is not foreseen in some state, the default action is called. The later ignores the action or handles the error.

Page 179: Génie logiciel Software Engineering C. Petitpierre

State Pattern (State interface)

abstract class State {

public void action1(Context context) {}

public void action2(Context context) {}

public void action3(Context context) {}

}

Page 180: Génie logiciel Software Engineering C. Petitpierre

State Pattern (context)

class Context {

State state = First.getState();

public void changeState(State s) { state = s; } public void action1() { state.action1(this); } public void action2() { state.action2(this); } public void action3() { state.action3(this); }}

Page 181: Génie logiciel Software Engineering C. Petitpierre

State Pattern (State object)

class Second extends State { static State state = null; public static State getState() { if (state == null) { state = new Second(); } return state; } public void action2(Context context) { System.out.println("action 2");

// go to First State context.changeState(First.getState()); } public void action3(Context context) { System.out.println("action 3"); context.changeState(Third.getState()); }}

Page 182: Génie logiciel Software Engineering C. Petitpierre

State Pattern (based on a switch)

Not official, but more efficient: use a switch (in theory, a state is a position in a program and the set of all the values of its variables)

class Context3 { enum State {a, b, c}; State state = State.a; public int number; public void handle(char inp) { switch (state) { case a: if (inp == '1') { System.out.println("action 1"); state = State.b; } break; case b: if (inp == '2') { System.out.println("action 2"); state = State.a; } else if (inp == '3') { System.out.println("action 3"); number = 0; state = State.c; } break; . . .

Page 183: Génie logiciel Software Engineering C. Petitpierre

A SAX Parser with the State Pattern can be used to read

XML files.

Page 184: Génie logiciel Software Engineering C. Petitpierre

XML: EXtensible Markup Language

<!-- A comment -->

<person>

<firstName>Robert</firstName>

<name/> <!-- empty -->

<address category="private" duration="permanent">

<street>Carrigton allee</street>

<town>Philadelphia</town>

</address>

</person>

&amp; &apos; &lt; &gt; &quot;

Page 185: Génie logiciel Software Engineering C. Petitpierre

DTD: Data Type Definition(defined in the XML standard)

<!ELEMENT person (firstName, name, address)> <!ELEMENT firstName (#PCDATA)><!ELEMENT name (#PCDATA)><!ELEMENT address (street, town)><!ELEMENT street (#PCDATA)><!ELEMENT town (#PCDATA)><!ATTLIST address category CDATA IMPLIED duration (permanent|temporary) "temporary“>

PCDATA = parsed character data (the &gt; are translated)

Page 186: Génie logiciel Software Engineering C. Petitpierre

Commande ATTLIST

<!ATTLIST symbolOfTheElement

symbolOfTheAttribute1 attributeType1 characteristic1

symbolOfTheAttribute2 attributeType2 characteristic2

>

Page 187: Génie logiciel Software Engineering C. Petitpierre

attributeTypes possibles dans une DTD

CDATA "xxx yyy &quot;”

NMTOKEN "v1.2“ without space

NMTOKENS "v1.2 xxx www“ a list of tokens

ID "aUniqueId“ this ID should appear only once in

the whole XML file

IDREF "anExistingID“ there should be the same ID

somewhere in the XML file

IDREFS "anID anotherOne“ a list of IDREF

Enumeration (Monday | Tuesday | Wednesday)

NOTATION see the standard

ENTITY see the standard

Page 188: Génie logiciel Software Engineering C. Petitpierre

characteristics possibles dans une DTD

"defaultValue“ used after an enumeration, itrepresents the default value, used if the attribute is not defined

#IMPLIED the attribute is optional

#REQUIRED the attribute is mandatory

Page 189: Génie logiciel Software Engineering C. Petitpierre

Example of XML file

In order to dump a table of MySQL in XML

C:\>mysqldump – –xml databaseName tableName

Page 190: Génie logiciel Software Engineering C. Petitpierre

SAX: Simple API for XML

SAXParserstartDocument()

startElement ()

endElement()

characters()

XML data

refers to

DTD

MyHandler

DefaultHandler

Page 191: Génie logiciel Software Engineering C. Petitpierre

SAX Handler (available in J2SE)

Page 192: Génie logiciel Software Engineering C. Petitpierre

Exercise 5.1

Create a program to read the following file:

<?xml version="1.0" encoding="iso-8859-1"?>

<!DOCTYPE a SYSTEM "test6.dtd">

<a> <b> <c>xxx xx</c> <c>yyyy y</c> <c>zz zzz</c> </b> <d/> <b> <c>u u u </c> </b></a>

Page 193: Génie logiciel Software Engineering C. Petitpierre

Exercise 5.1 (continuation)The preceding file correspond to this DTD:

<!ELEMENT a ( (b | d)* )><!ELEMENT b (c)*><!ELEMENT c (#PCDATA)><!ELEMENT d EMPTY>

/a </a>23

4

5

10a

b

chars

c

/dd

/c

/b

end/a

Page 194: Génie logiciel Software Engineering C. Petitpierre

Using SAX

public static void main(String args[]) throws Exception {

MySAXHandler handler = new MySAXHandler();

SAXParserFactory factory = SAXParserFactory.newInstance();

factory.setValidating(true);

SAXParser saxParser = factory.newSAXParser();

File readFile = new File(args[i]);

try {

saxParser.parse(readFile, handler);

} catch (Exception e) {

System.out.println("Error caught: " + e.getMessage());

}

}

Page 195: Génie logiciel Software Engineering C. Petitpierre

SAX + State Pattern: My handler

/**

* SAX Handler methods

*/

State state = state0;public void startElement( String uri, String name, String qName, Attributes atts ) {

state = state.handle(0, qName);

}

. . .

Page 196: Génie logiciel Software Engineering C. Petitpierre

SAX + State Pattern: a state

class State0 extends State {

State handle(int no, String s) {

if ((s.equals("a")) && (no == 0))

return state1;

else

error(s, no);

return null;

}

}

Page 197: Génie logiciel Software Engineering C. Petitpierre

SAX + State Pattern

In the previous case, a switch statement to implement the states would be more efficient !

Page 198: Génie logiciel Software Engineering C. Petitpierre

Exercise 5.2

• Use the state pattern to create a tokenizer that decode the following tokens:“x” “abc” unknown (all other characters)

• It should be capable of returning the following tokens “a” “x” “a” “abc”from this sequence “axaabc”

Page 199: Génie logiciel Software Engineering C. Petitpierre

Exercise 5.2

A test sequence and an object that contains part of the solution is available (see list of exercises).

// read the token located at the beginning of the buffer, // from 0 to the current position

public void extractImage()

// Same thing when the first character is not a token

public void extractFirstChar() {

// Called by the client to get the next token

public int getNext() throws IOException {

// Sets the next state

public void setState(State _state) {

Page 200: Génie logiciel Software Engineering C. Petitpierre

Exercise 5.2

For example, for the tokens “abc” “xyz”, the state machine tries the following paths:

State0 ‘a’ (continuation in State1), ‘x’ (continuation in State2), other (extract the first character as the next token and return unknown)

State1 ‘b’ (continuation in State3), other (idem)

State3 ‘c’ (extractImage and return the token number)

State2 ‘y’ (continuation in State4), other (idem)

State4 ‘z’ (extractImage and return the token number)

Page 201: Génie logiciel Software Engineering C. Petitpierre

Exercise 5.2: (JUnit Test)

@Test

public final void test4() throws IOException {

assertTrue("a, x, a, abc not found",

readTokens(

new int[] {0,1,0,2},

new String[]{"a","x","a","abc"},

new ByteArrayInputStream(

"axaabc".getBytes()) ) );}

Page 202: Génie logiciel Software Engineering C. Petitpierre

DOM: document object model (tree)

<address category="private" duration="permanent">

Attributes

Node

attributes

childrenNode

attributes

childrenNode

attributes

children

Node

attributes

children

Page 203: Génie logiciel Software Engineering C. Petitpierre

DOM: initializationtry {

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

factory.setValidating(true);

DocumentBuilder builder = factory.newDocumentBuilder();

builder.setErrorHandler(new ErrorHandler() {

public void error(SAXParseException exception) {…}

public void fatalError(SAXParseException exception) {…}

public void warning(SAXParseException exception) {…}

});

document = builder.parse(new File(argv[0]));

PrintTree.print(document, "");

} catch (Exception ioe) {

ioe.printStackTrace();

} }

Page 204: Génie logiciel Software Engineering C. Petitpierre

DOM: walking through the tree

public static void print(Node node, String indentation) {

System.out.print(indentation + node.getNodeValue());

if (node.hasAttributes()) {

NamedNodeMap map = node.getAttributes();

for (int j = 0; j < map.getLength(); j++)

System.out.println(indentation + map.item(j).getNodeName());

}

NodeList nl = node.getChildNodes();

if (nl != null)

for (int i = 0; i < nl.getLength(); i++) {

print(nl.item(i), (indentation + " |"));

} }

Page 205: Génie logiciel Software Engineering C. Petitpierre

Interpreter

42 2 1 - + // expression in Reverse Polish notation

push(42) push(2) push(1) push(-pop+pop) push(pop+pop)

1

2 2 1

42 42 42 42 43

Page 206: Génie logiciel Software Engineering C. Petitpierre

Interpreter for the previous notation (object diagram)

ParseTreeArrayList<Expression>

TerminalExpression_Numbervalue

constructor(int)interpret(Stack)

TerminalExpression_Plusvalue

interpret(Stack)

Expression

interpret(Stack)

Expression

interpret(Stack)

StackArrayList<Integer>

Parser

parse(String)evaluate()

Page 207: Génie logiciel Software Engineering C. Petitpierre

Interpreter: class diagram

Client

AbstractExpression

interpret(Context)

TerminalExpression

interpret(Context)

NonTerminalExpression

interpret(Context)

Context

Page 208: Génie logiciel Software Engineering C. Petitpierre

JavaCC: Java compiler’s compiler

Site Web: https://javacc.dev.java.net

(go to : Documentation > ... the JavaCC grammar file ... )

Download the version 4.0

(See http://www.epflpress.org/Book_Pages/petitpierre.html)

Page 209: Génie logiciel Software Engineering C. Petitpierre

JavaCC: compilation of a .jj file(the sources are contained in .jj files)

In external tools:

Page 210: Génie logiciel Software Engineering C. Petitpierre

JavaCC: parts

1. Options

2. Program header

3. Tokens

4. Productions

Page 211: Génie logiciel Software Engineering C. Petitpierre

JavaCC: (1) options

options { STATIC = true; DEBUG_PARSER = true;}

The first block of the source contains the options. Here are the two main ones.

Page 212: Génie logiciel Software Engineering C. Petitpierre

JavaCC: (2) the program header

PARSER_BEGIN(XMLParserSKIP)package parser;import java.io.FileReader;

public class XMLParserSKIP { public static void main(String args[]) throws Exception { FileReader in = new FileReader(args[0]); XMLParserSKIP parser = new XMLParserSKIP(in); parser.rootProduction(); } // possibility to define attributes and methods}PARSER_END(XMLParserSKIP)

Page 213: Génie logiciel Software Engineering C. Petitpierre

JavaCC: (3) ignored tokens

SKIP :{ " "| "\r"| "\t"| "\n"}

Specifies that the spaces, carriage returns, tabulations, new lines are ignored (skipped).

These tokens separate the other ones, of course, but they are not transmitted to the analyzer.

Page 214: Génie logiciel Software Engineering C. Petitpierre

JavaCC: simple tokens

TOKEN :

{ < LT: "<" >

| < GT: ">" >

| <UNDERLINE: "_">

| <COLON: ":">

| <DOT: ".">

| <MINUS: "-">

| <ENDTAG: "</">

}

This source defines a few tokens

Page 215: Génie logiciel Software Engineering C. Petitpierre

JavaCC: composed tokens

TOKEN :

{ <ID: ( <LETTER> | "_" | ":" )

( <DIGIT> | <LETTER> | "_" | ":" | "." | "-" )* >

| <#LETTER: ["a"-"z", "A"-"Z"] >

| <#DIGIT: ["0" - "9"] >

}

#LETTER defines a token known only locally

Page 216: Génie logiciel Software Engineering C. Petitpierre

JavaCC: attention!

TOKEN :

{ < COLON: ":" >

| < ID: ":" (["a"-"z])* >

}

Input text:

:234 <COLON> 2 3 4

:aaa <ID>

The token is the longest possible path, but if two

tokens have the same length, the first one is returned

Page 217: Génie logiciel Software Engineering C. Petitpierre

JavaCC: definition of spaces

TOKEN : // not correct (a single space is SPACE != S )

{

<SPACE: " ">

| <CR: "\r">

| <TAB: "\t">

| <NL: "\n">

| <S: (<SPACE> | <CR> | <TAB> | <NL>)+ >

}

Page 218: Génie logiciel Software Engineering C. Petitpierre

JavaCC: correct definition

TOKEN : // correct

{

<S: (<SPACE> | <CR> |<TAB> | <NL>)+ >

| <#SPACE: " "> // local definition

| <#CR: "\r">

| <#TAB: "\t">

| <#NL: "\n">

}

Page 219: Génie logiciel Software Engineering C. Petitpierre

JavaCC: special token definition

SPECIAL_TOKEN :

{

<S: (<SPACE> | <CR> |<TAB> | <NL>)+ >

| <#SPACE: " "> // local definition

| <#CR: "\r">

| <#TAB: "\t">

| <#NL: "\n">

}

Page 220: Génie logiciel Software Engineering C. Petitpierre

JavaCC: queue of tokens and special tokens

Token

next

specialToken

Token

next

specialTokenToken

next

specialTokenToken

next

specialToken

Token

next

specialToken

Special tokens

in reverse order

Page 221: Génie logiciel Software Engineering C. Petitpierre

JavaCC: special token and token class

package tree;

public class Token {

public int kind;

public int beginLine, beginColumn, endLine, endColumn;

public String image;

public Token next;

public Token specialToken;

public String toString() { return image; }

public static final Token newToken(int ofKind) {

switch(ofKind) { // to create specific tokens

default : return new Token();

} } }

Page 222: Génie logiciel Software Engineering C. Petitpierre

JavaCC: token in contexts

<![CDATA[ x x x x x x ]]>

<DEFAULT> MORE : { "<![CDATA[" : IN_CDATA }

<IN_CDATA> MORE : { < ~[] > }

<IN_CDATA> TOKEN : { <CDATA : "]]>"> : DEFAULT }

In the default mode (start of the program), introduce token "<!

[CDATA[" in the current token and jump to context <IN_DATA>. In this context, add any character to the same token, add the token "]]>", return to the default mode and return a single token made of all pieces appearing in the MORE lines. The final token is named CDATA. (not in the book!)

Page 223: Génie logiciel Software Engineering C. Petitpierre

JavaCC: (4) production

void tag() :{ }{ "<“ <ID> ">"}

String tag() :{ String s; Token t; // extra token}{ "<" t =<ID> ">" { return t.image; }}

String tag() :{ }{ "<" <ID> ">" { return token.image; }}

token exists by default

Page 224: Génie logiciel Software Engineering C. Petitpierre

JavaCC: repetitions

void product() :

{ }

{

tag()

( <ID> )*

endTag()

}

void tag() : { }

{ "<" <ID> ">" }

void endTag() : { }{ "</" <ID> ">" }

( x )* 0 – n times

( x )+ 1 – n times

( x )? optional

[ x ] same as above

Page 225: Génie logiciel Software Engineering C. Petitpierre

JavaCC: choices

void product() :

{ }

{

"("

(

<ID>

|

tag()

)

endTag()

}

Either

"(" <ID> endTag()

or

"(" tag() endTag()

Page 226: Génie logiciel Software Engineering C. Petitpierre

void command() throws Exception :

{ String s, t; }

{

s = tag()

( (<ID>)+

| (command())+ <a> ID ID </a>

| <CDATA> <a> <c>x</c> </a>

) <a> <![CDATA[ x x x ]]>

</a>

t = endTag()

{ if (!s.image.equals(t.image)) // Java code

throw new Exception("end tag != from start tag");

}

}

JavaCC: another production

Page 227: Génie logiciel Software Engineering C. Petitpierre

JavaCC: token versus production

TOKEN:

{

<TAG: "<" <ID> ">" >

}

String tag () :

{ String s; }

{

"<" <ID>{s=token.image;} ">"

{ return s; }

}

Page 228: Génie logiciel Software Engineering C. Petitpierre

JavaCC: lookahead

void product() :

{ }

{ ( tag() | endTag() (

}

void tag() : { }

{ "<" <ID> ">" }

void endTag() : { }{ "<" "/" <ID> ">" }

both continue with "<"

void product() :

{ }

{ ( LOOKAHEAD (2) tag() | endTag() (

}

void tag() : { }

{ "<" <ID> ">" }

void endTag() : { }{ "<" "/" <ID> ">" }

Page 229: Génie logiciel Software Engineering C. Petitpierre

JavaCC: LOOKAHEAD

The LOOKAHEAD command is placed at the beginning of the alternative

Three possibilities:

LOOKAHEAD (2)

LOOKAHEAD ( "<" id() ">" )

LOOKAHEAD ( { methodReturningABoolean() } ) . . .

JAVACODEboolean methodReturningBoolean() { if (…) return true; else return false;}

Page 230: Génie logiciel Software Engineering C. Petitpierre

JavaCC: JAVACODE command

TOKEN:{ <UNDEFINED: ~[]>}void command() { }{ tag() <CDATA_START> {getCDATA();} endTag()}

JAVACODE

void getCDATA() {

while ( getNextToken().kind != CDATA_END)

System.out.print("-"+getToken(0).image+"-");

if (getToken(1).kind==S)

getNextToken();

} // getToken(1) == lookahead

Page 231: Génie logiciel Software Engineering C. Petitpierre

JavaCC: an example ( CVS project Patterns,

package tree, compile Parser.jjt with javacc for now )

SKIP :

{

" "

| "\r"

| "\t"

| "\n"

}

TOKEN :

{ compiler for expressions like this one

< LPAR: "(" > 4*(8+7-9)+(6*(7-2))

| < RPAR: ")" >

| < PLUS: "+" >

| < MINUS: "-" >

| < INTEGER: (["0" - "9"])+ >

}

Page 232: Génie logiciel Software Engineering C. Petitpierre

JavaCC: productions of the example

void expression() throws Exception :{ }{ multExpression() ( "+“ multExpression() | "-" multExpression() 4*(8+7-9)+(6*(7-2)) )*}void multExpression() throws Exception :{ }{ primaryExpression() ( "*" primaryExpression() )* }void primaryExpression() throws Exception :{ }{ ( <INTEGER> | "(" expression() ")" )}

Page 233: Génie logiciel Software Engineering C. Petitpierre

JavaCC: creation of an interpreter tree

AbstractExpression expression() throws Exception :{ AbstractExpression ae, m;}{ m = multExpression() ( "+" ae = multExpression() {m=new PlusExpression(m,ae);} | "-" ae = multExpression() {m=new MinusExpression(m,ae);} )* {return m;}}

PlusExpression

multExpression()multExpression()

MinusExpression

multExpression()

Page 234: Génie logiciel Software Engineering C. Petitpierre

JavaCC: creation of an interpreter tree

AbstractExpression multExpression() throws Exception :{ AbstractExpression ae, m;}{ m = primaryExpression() ( "*" ae = primaryExpression() {m=new MultExpression(m, ae);} )* { return m; }}

MultExpression

primaryExpression()

primaryExpression()

Page 235: Génie logiciel Software Engineering C. Petitpierre

JavaCC: creation of an interpreter tree

AbstractExpression primaryExpression() throws Exception :{ AbstractExpression m;}{ ( <INTEGER> {m = new Terminal(Integer.parseInt(token.image));} | "(" m=expression() ")" ) {return m;}}

Terminal expression()

Page 236: Génie logiciel Software Engineering C. Petitpierre

JavaCC: class for loading the constant

public class Terminal extends AbstractExpression{

public Terminal( AbstractExpression left, AbstractExpression right) { super(left, right); }

int value;

public Terminal(int value) {

super(null,null);

this.value = value;

}

public void interpret(Stack stack) {

stack.push(value);

} }

Page 237: Génie logiciel Software Engineering C. Petitpierre

JavaCC: class for adding the values returned by 2 subtrees

public class PlusExpression extends AbstractExpression {

public PlusExpression(AbstractExpression left, AbstractExpression right) { super(left, right); }

public void interpret(Stack stack) {

left.interpret(stack);

right.interpret(stack);

stack.push(stack.pop()+stack.pop());

} }

// Available in project Patterns, package tree, ParserDump.jjt

Page 238: Génie logiciel Software Engineering C. Petitpierre

The following slides show how to print a file after it has been treated by the compiler

Tokennext

Tokennext

Tokennext

Tokennext

Tokennext

Tokennext

Tokennext

The tokens are stored in a list

(See also the special tokens in a previous slide)

Page 239: Génie logiciel Software Engineering C. Petitpierre

Returning the first token of the list(first solution)

Token rootProduction() throws Exception :{Token first;}{ {first = getToken(1);} command() {return first;}}void command() throws Exception :{}{ tag() (command())* endTag()}// can also be retrieved from the first node, // as shown on one of the following pages

Page 240: Génie logiciel Software Engineering C. Petitpierre

Printing all the tokens(not the special ones): in main()

. . .

Token first = parser.rootProduction();

while (first != null) {

System.out.println(first.image);

first = first.next;

}

. . .

Page 241: Génie logiciel Software Engineering C. Petitpierre

Printing the special tokens

// To be called before every true token

// It inverts the order of the special tokens

static void followSpecialTokens (Token t){

if (t == null) return;

followSpecialTokens(t.specialToken);

System.out.print(t.image);

}

Page 242: Génie logiciel Software Engineering C. Petitpierre

jjtree: creating a tree automatically (AST-abstract syntax tree)

Take the same file as before, but change extension to .jjt and call

jjtree Xxxx.jjt

You obtain Xxxx.jj and a list of classes. Call

javacc Xxxx.jj

Compile with javacc and execute as usual, the tree is created, but of course the program does not use it yet.

// Source available in project Patterns, package tree, ParserDump.jjt

Page 243: Génie logiciel Software Engineering C. Petitpierre

Tree: a node for each production(which node is generated can be controlled)

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

dump() is recursive, it calls the dump() of the children rootNode.dump()walks through all the nodes

Page 244: Génie logiciel Software Engineering C. Petitpierre

How to link the tokens to the nodes

With the options:

NODE_SCOPE_HOOK=true;

The compiler jjtree enters the following commands at the beginning and the end of the every productions:

jjtree.openNodeScope(jjtn000);

. . .

jjtreeCloseNodeScope(jjtn000);

Page 245: Génie logiciel Software Engineering C. Petitpierre

Add this in file .jjt

static void jjtreeOpenNodeScope(Node node) {

((SimpleNode)node).setBeginToken(getToken(1));

}

static void jjtreeCloseNodeScope(Node node) {

((SimpleNode)node).setEndToken(getToken(0));

}

Page 246: Génie logiciel Software Engineering C. Petitpierre

… and this in SimpleNode.java

private Token beginToken;

private Token endToken;

public Token getBeginToken() { return beginToken; }

public void setBeginToken(Token beginToken) {

this.beginToken = beginToken;

}

public Token getEndToken() { return endToken; }

public void setEndToken(Token endToken) {

this.endToken = endToken;

}

Page 247: Génie logiciel Software Engineering C. Petitpierre

… then you obtain the following structure (Design Pattern!)

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

SimpleNodechildrendump()

Token Token Token Token Token Token Token Token Token

beginTokenendToken

beginToken endToken

Page 248: Génie logiciel Software Engineering C. Petitpierre

JavaCC: Controlling which node is generated

options { Node_DEFAULT_VOID=true; MULTI=true; NODE_PREFIX=“EPFL_”}expression() #Xxxx: // creates a node with { } // name EPFL_Xxxx{ multExpression() ( "+“ multExpression() | "-" multExpression() )*}

Page 249: Génie logiciel Software Engineering C. Petitpierre

Getting the first token of the list(second solution)

The first token can also be retrieved from the first node:

node = parser.rootProduction()

where

SimpleNode rootProduction() : { } { . . .

{return jjtn000;}

}

Page 250: Génie logiciel Software Engineering C. Petitpierre

Printing the tokens covered by each node

public void dump(String prefix) {

Token t = getBeginToken();

Token te = getEndToken();

System.out.print(toString(prefix) + " !");

while (t != null) {

System.out.print(t.image);

if (t == te)

break;

t = t.next;

}

System.out.println("!");

// writes marks that represent the tree

. . .

Page 251: Génie logiciel Software Engineering C. Petitpierre

Printing the tokens covered by each node

public void dump(String prefix) {

. . .

System.out.println("!"); // create lines that

if (children != null) { // highlight the tree

for (int i = 0; i < children.length; ++i) {

SimpleNode n = (SimpleNode) children[i];

if (n != null) {

if (i != (children.length - 1))

n.dump(prefix + "!"); // recursion

else

n.dump(prefix + " ");

} } } }

Page 252: Génie logiciel Software Engineering C. Petitpierre

Visitor Design Pattern (GoF)handled by javacc

Used to perform work on the AST (abstract syntax tree).

The tree is walked through and the code of a visitor object

is executed within each node.

Different visitors can perform different tasks (type checking,

code generation) over the same tree, one after the other.

In the following, the example of the expressions interpreter

will be handled with the help of the visitor pattern

Page 253: Génie logiciel Software Engineering C. Petitpierre

The nodes in the tree of the previous example

void expression() throws Exception :{ }{ multExpression() ( "+“ multExpression() | "-" multExpression() )*}void multExpression() throws Exception :{ }{ primaryExpression() ( "*" primaryExpression() )* }void primaryExpression() throws Exception :{ }{ ( <INTEGER> | "(" expression() ")" )}

Nodes created :

ASTexpression ASTmultExpression ASTprimaryExpression

Page 254: Génie logiciel Software Engineering C. Petitpierre

The nodes of the tree of the previous example

ASTexpression

ASTmultExpressionASTmultExpressionASTmultExpression

ASTprimaryExpressionASTprimaryExpression

ASTexpression <INTEGER>

SimpleNode

SimpleNode

SimpleNode

Page 255: Génie logiciel Software Engineering C. Petitpierre

Visitor Pattern: each node accepts a visitor(located in SimpleNode, see previous slide))

/** Accept the visitor. * */

public Object jjtAccept(MyExpressionsVisitor visitor,

Object data) {

return visitor.visit(this, data);

}

The call is forwarded to the visitor, which contains one method per node. The method is identified by its argument. It receives this to allow the visitor to create the task determined by the node. Thus, different visitors can be executed with the same structure.

Page 256: Génie logiciel Software Engineering C. Petitpierre

Visitor Pattern: the visitor contains a method for each kind of node

public class MyVisitor implements MyExpressionsVisitor {

public Object visit (ASTexpression node, Object data)

{ your code }

public Object visit (ASTmultExpression node, Object data)

{ your code }

public Object visit (ASTprimaryExpression node, Object data)

{ your code }

}

// MyExpressionsVisitor is generated automatically

// each task requires only a class like this one (no changes in the parser)

Page 257: Génie logiciel Software Engineering C. Petitpierre

Visitor Pattern: in the main

// visit the nodes

node.childrenAccept(new MyVisitor(), null);

Page 258: Génie logiciel Software Engineering C. Petitpierre

Visitor Pattern: recursive walk through the nodes (located in SimpleNode)

/** Accept the visitor. * */

public Object childrenAccept ( MyExpressionsVisitor visitor, Object data) {

if (children != null) {

for (int i = 0; i < children.length; ++i) {

((SimpleNode)children[i]).childrenAccept(visitor, data);

}

}

jjtAccept(visitor, data);

return data;

} These 2 lines had to be modified

Page 259: Génie logiciel Software Engineering C. Petitpierre

Example of visitor

public Object visit(ASTprimaryExpression node, Object data) {

if ( ((SimpleNode) node).jjtGetNumChildren() == 0 ) {

node.ae = new Terminal(Integer.parseInt(node.getBeginToken().image));

} else {

node.ae = ((SimpleNode) node.jjtGetChild(0)).ae;

}

return null;

}

Either create a Terminal node { found <Integer>, namely no child }

or pass the expression found in the subtree { found "(" expression() ")" }

A field AbstractExpression has been defined in SimpleNode

Page 260: Génie logiciel Software Engineering C. Petitpierre

Example of visitor (2)(how to check if it is a “+” or a “-”)

expression: multExpression() ( "+“ multExpression() | "-" multExpression() )*

expressionchildrendump()

multExpressionchildrendump()

multExpressionchildrendump()

multExpressionchildrendump()

Token Token Token

+

Token Token Token

-

beginToken endToken

Token Token Token

Page 261: Génie logiciel Software Engineering C. Petitpierre

Another example of visitor (2)public Object visit (ASTexpression node, Object data) {

if ( ((SimpleNode) node).jjtGetNumChildren() > 0 ) {

SimpleNode nodeX = ((SimpleNode) node.jjtGetChild(0));

node.ae = nodeX.ae; // pass the subexpression

int operation = nodeX.getEndToken().next.kind; // previous operation

for (int i = 1; i < ((SimpleNode) node).jjtGetNumChildren(); i++) {

nodeX = (SimpleNode) node.jjtGetChild(i);

if (operation == MyExpressionsConstants.PLUS) {

node.ae = new PlusExpression(node.ae, nodeX.ae);

} else {

node.ae = new MinusExpression(node.ae, nodeX.ae);

}

operation = nodeX.getEndToken().next.kind;

} }

return null;

} gets the token to see if it is a “+” or < “-”

(next slide)

Page 262: Génie logiciel Software Engineering C. Petitpierre

In summary

ParserVisitor.jjt previous .jj file complemented with the definition of jjtreeOpenNodeScope

SimpleNode.java generated node complemented with the handling of beginNode and endNode, as well as an attribute for an AbstractExpression

MyVisitor.java one method per node to generate the interpretertree; generated entirely by the developer

AbstractExpression.java classes for the Interpreter Pattern used

MinusExpression.java in previous slides; the visitor creates them and

MultExpression.java embed them within an interpreter tree

PlusExpression.java

Terminal.java

Stack.java

Source available in project Patterns, package visitor

Page 263: Génie logiciel Software Engineering C. Petitpierre

Example of the use of JavaCC:Synchronous Javascript

http://ltiwww.epfl.ch/sJavascript/

http://ltiwww.epfl.ch/~petitp/GenieLogiciel/test_s.html

Page 264: Génie logiciel Software Engineering C. Petitpierre

Example of sJavascript

process Consumer(name) { var count this.put = function(counter) { // a method count = counter } this.run = function () { // the thread method for (;;) { accept put document.getElementById("consDisplay").innerHTML = count} } }

Page 265: Génie logiciel Software Engineering C. Petitpierre

Example of sJavascriptprocess Producer(name) { var ON = true var counter = 0 this.run = function() { for (;;) { select { case startStop.clicked() // synchronizing call ON = !ON document.getElementById("startStop") .style.backgroundColor = ON?"green":"red" case when (ON) waituntil(now()+1000) // synchronizing call counter++ consumer.put(counter)} } } }

Page 266: Génie logiciel Software Engineering C. Petitpierre

// sJavascriptprocess Consumer(name) { var count this.put = function(counter) { count = counter } this.run = function () { for (;;) { accept put document.getElementById ("consDisplay") .innerHTML = count} } }

// standard Javascriptextending(Consumer, TaskControlBlock)function Consumer(name) { Consumer.baseConstructor.call(this, name) var count this.$JM_put = 1 this.put = function(counter) { count = counter } this.$J_state = 10000 this.run = function () { for (;;) { switch(this.$J_state) { case 10000: this.$J_init() this.$J_accept(10002, this.$JM_put) this.$J_syncWait(29) return case 10002: document.getElementById ("consDisplay").innerHTML = count this.$J_state = 10000;} } } }

scheduler

Compilation

Page 267: Génie logiciel Software Engineering C. Petitpierre

sJavascript

The transformation on the last page has been performed with the Visitor Design Pattern