compiler design
play

Compiler Design Spring 2018 4.X Patterns (again) Thomas R. Gross - PowerPoint PPT Presentation

Compiler Design Spring 2018 4.X Patterns (again) Thomas R. Gross Computer Science Department ETH Zurich, Switzerland 1 Why? Remember questionnaire (from the beginning of the semester)? Question 7: Please name three design patterns


  1. Compiler Design Spring 2018 4.X Patterns (again) Thomas R. Gross Computer Science Department ETH Zurich, Switzerland 1

  2. Why? § Remember questionnaire (from the beginning of the semester)? § Question 7: “Please name three design patterns that you encountered in earlier projects/classes.” § Answers § Complete (3+ patterns): 33% § Blank: 55% 2

  3. Patterns § Singleton: 27% § Factory: 27% § Visitor: 22% Not a pattern: § Object-oriented programming § Design by contract § Functional programming § Lazy loading § Inheritance 3

  4. Patterns – some technical reasons § Control flow always difficult to deal with § Patterns like Strategy or Iterator raise the level of programming § Hide details § Easier to read than explicit control flow statements § Simpler to write § Easier to extend/understand/maintain 4

  5. Trivial example § Print date using different formats § Option 1: Test at each place in the program P where the date is to be printed switch(format): { case (INTERNATIONAL): // print YEAR-MONTH-DAY break; case (BANK): // print MONTH-DAY-YEAR break; ... } § Option 2: Invoke function/method F passed to P 5 § F is defined so that the correct format is chosen

  6. Auxiliary classes import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Date; class MyDate { // Won’t work in long-lived programs int day; int month; int year; MyDate() { Calendar cal = new GregorianCalendar(); year = cal.get(cal.YEAR); month = cal.get(cal.MONTH); day = cal.get(cal.DAY_OF_MONTH); } } 6

  7. Select format 1 (international) interface Print { void print(); } class InternationalFormatPrint implements Print { MyDate d_; InternationalFormatPrint(MyDate d) { d_ = d; } public void print() { System.out.println(d_.day + "/" + d_.month + "/" + d_.year ); } 7 }

  8. Select format 2 (bank) class BankFormatPrint implements Print { MyDate d_; BankFormatPrint (MyDate d) { d_ = d; } public void print() { System.out.println(d_.month + "/" + d_.day +"/" + d_.year ); } 8 }

  9. Example public static void main(String args[]) { MyDate d = new MyDate(); Print p = selectPrinter(d); doThePrinting(p); } static Print selectPrinter(Date d) { if (user.input() == ‘b‘) { return new BankFormatPrint(d); } else { return new InternationalFormatPrint(d); } } static void doThePrinting(Print service) { service.print(); 9 }

  10. Output Test6> java Test6 30/1/2018 Test6> java Test6 1/30/2018 § Not a big deal § (This is a simple example after all) § But the idea is powerful § No need to deal with a possibly complicated switch-statement § Only passing the printer instance as parameter is needed 10

  11. Other advantage: Extensibility § Imagine adding support for a new format, e.g., Japanese § With Option 1: Extending switch statement is required switch(format): { case (INTERNATIONAL): // print YEAR-MONTH-DAY break; case (BANK): // print MONTH-DAY-YEAR break; case (JAPANESE): // print YEAR-MONTH-DAY break; } 11

  12. Other advantage: Extensibility § At all places where formatting is needed § Error-prone § High risk of introducing inconsistent behavior 12

  13. Other advantage: Extensibility § Option 2: Requires only adding a new implementation for the Print interface class JapaneseFormatPrint implements Print { MyDate d_; JapaneseFormatPrint(MyDate d) { d_ = d; } public void print() { System.out.println(d_.year + "/" + d_.month +"/" + d_.day ); } } § Where new formatting is needed: Pass a JapaneseFormatPrint instance to existing code 13

  14. public static void main(String args[]) { MyDate d = new MyDate(); Print p = selectPrinter(d); doThePrinting(p); } static Print selectPrinter(Date d) { if (user.input() == ‘b‘) { return new BankFormatPrint(d); } else if (user.input() == ‘j‘){ return new JapaneseFormatPrint(d); } else { return new InternationalFormatPrint(d); } } static void doThePrinting(Print service) { service.print(); } 14

  15. The Strategy pattern § You’ve just seen an example of the Strategy pattern Strategy Context algorithmInterface() contextInterface() ConcreteStrategy1 ConcreteStrategy2 ConcreteStrategy3 algorithmInterface() algorithmInterface() algorithmInterface() 15

  16. The Strategy pattern § You’ve just seen an example of the Strategy pattern Print MyDate print() // direct access to fields BankFormatPrint Int’lFormatPrint JapaneseFormatPrint print() print() print() 16

  17. The Strategy pattern § Idea: Encapsulate a set of related algorithms into a class hierarchy § Benefit: Simplify control-flow (e.g., reduce the need for conditional statements) § Benefit: Algorithm can be changed independently of context § Benefit: Decouple implementation of algorithm from data structure(s) in context 17

  18. Is Strategy really that great? § Should we always use Strategy when our program uses at least two different algorithms on one data structure ? § It depends § A pattern is a solution that works well in some settings § But not always § You have to weight pros/cons 18

  19. Pros/cons § A switch-statement is not that bad after all… § If you have a program with two algorithms and a data structure § A program will not be changed/extended § Don’t forget: Change is rather the norm and not an exception § Implementing Strategy (often) requires interface/virtual calls § (Some) VM engineers: Don’t use virtual calls, they’re expensive § Good for performance, maintenance cost paid later 19

  20. MyDate An alternative print() BankFormatDate Int’lFormatDate JapaneseFormatDate print() print() print() Advantage: Simpler class structure § Disadvantage: Mixes MyDate and algorithms that operate on it § § Can become a problem if algorithms and/or data structure in MyDate 20 complicated

  21. Working with data structures § MyDate: Only three integer fields § Direct access to fields sufficient to print date Print MyDate print() // direct access to fields BankFormatPrint Int’lFormatPrint JapaneseFormatPrint print() print() print() 21

  22. Working with complex data structures § What should we do if the data structure is complex? § We could use an iterator to enumerate all elements 22

  23. Working with complex data structures § Example: list of dates class JapaneseFormatPrint implements Print { List<MyDate> list_; JapaneseFormatPrint(List<MyDate> list) { list_ = list; } public void print() { Iterator iter; while (iter.hasNext()) { MyDate d = iter.next() System.out.println(d_.year + "/" + d_.month +"/" + d_.day ); } } } 23

  24. What about accessing even more complex data structures? § There may not be an iterator § The order of processing/invoking a method may matter § (Just think of trees) § Visitor pattern internalizes the logic of “visiting” the elements 24

  25. Visitor § Coupling of data structure and access method(s) § Powerful in connection with trees § Object must be prepared to “accept” a visitor § Example: arithmetic expressions § Sums § Constants 25

  26. Visitor // Data structure abstract class ArithExpr { abstract int accept(Visitor v); } // Visitor interface Visitor { int forConst(Const c); int forSum(Sum s); } 26

  27. class Const extends ArithExpr { private int value; Const (int v) { value = v; } int getValue() { return value; } int accept(Visitor v) { return v. forConst (this); } } 27

  28. class Sum extends ArithExpr { ArithExpr left, right; Sum (ArithExpr l, ArithExpr r) { left = l; right = r; } ArithExpr getLeft() { return left;} ArithExpr getRight() { return right;} int accept(Visitor v) { return v. forSum (this); } } 28

  29. Visitor examples class EvalVisitor implements Visitor { public int forConst(Const c) { return c.getValue(); } public int forSum(Sum s) { return s.getLeft().accept(this) + s.getRight().accept(this); } } class CountVisitor implements Visitor { public int forConst(Const c) { return 1;} public int forSum(Sum s) { return s.getLeft().accept(this) + s.getRight()).accept(this); } }

  30. Example, continued class ShowArithVisitors { public static void main(String[] args) { ArithExpr c2, c3, s1, s2; c2 = new Const(2); c3 = new Const(3); s1 = new Sum(c2,c3); s2 = new Sum(c2, s1); Visitor v1 = new EvalVisitor(); Visitor v2 = new CountVisitor(); System.out.println(s2.accept(v1)); System.out.println(s2.accept(v2)); }

  31. Visitor {interface} visitConcreteElem(ce: Element) ConcreteVisitor visitConcreteElem(ce: ConcreteElement) ObjectStructure Element {interface} accept(v: Visitor) ConcreteElement accept(v: Visitor) { accept(v: Visitor) v.visitConcreteElem(this) }

  32. Discussion § Who’s responsible for traversing the object structure? § In our case: the visitor class EvalVisitor implements Visitor { … public int forSum(Sum s) { return s.getLeft().accept(this) + s.getRight().accept(this); } } § Could be the object structure as well class Sum extends ArithExpr { … int accept(Visitor v) { return getLeft().accept(v) + getRight().accept(v); } 32 }

  33. Discussion (cont’d) § Should we always use the Visitor pattern for programs operating on tree-like object structures? § It depends. § Visitor beneficial if: § Object structure contains objects with different (unrelated) functionality § E.g., Const represents a value via the field value Sum is an arithmetic expression with fields left and right 33

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend