520 likes | 698 Views
Program Design, Design Patterns, Type Theory, and other buzzwords. Amr Sabry عمرو صبرى Indiana University. Playing Music. Building Structures. Programming. (define fact (lambda (n) (if (zero? n) 1 (* n (fact (sub1 n)))))). Levels of Abstraction.
E N D
Program Design,Design Patterns,Type Theory,and other buzzwords. Amr Sabry عمرو صبرى Indiana University
Playing Music Design Patterns and Type Theory
Building Structures Design Patterns and Type Theory
Programming (define fact (lambda (n) (if (zero? n) 1 (* n (fact (sub1 n)))))) Design Patterns and Type Theory
Levels of Abstraction As programmers we must deal with different levels of abstraction Write little pieces of code, encapsulate them by hiding the irrelevant details, and describing their behavior in concise terms. Use these encapsulations as building blocks for the next layers of abstraction, etc. Design Patterns and Type Theory
Part I Abstraction and Reuse Part II Abstraction and Safety Outline Design Patterns and Type Theory
Part I Abstraction and Reuse
Reuse Do we want to “reuse” code? YES!!! We earlier said: Write little pieces of code, encapsulate them by hiding the irrelevant details, and describing their behavior in concise terms. What is “irrelevant” depends on how the code will be used!!! Design Patterns and Type Theory
Which is an abstraction of a human? Design Patterns and Type Theory
Reuse (unanticipated) If we choose one particular abstraction, then we essentially rule out some future uses of the software. Unfortunately people like to modify software after the fact in unpredictable ways! Design Patterns and Type Theory
Architecture and Design Patterns Christopher Alexander • Design of a building is tied to the anticipated uses and must be flexible to accommodate other emerging uses. • The uses are captured in pattern languages and all buildings are the result of applying sets of rules (or patternlanguages - sets of related patterns) Alexander's Patterns • a pattern is a formalized instruction that says: "if you encounter this problem, then solve it like that" • patterns are the means to an end or rules of thumb • patterns are used in combination, with cross-referencing, enabling decisions to be made in a reasonable order Software Design Patterns • "These patterns solve specific design problems ... make object-oriented designs more flexible, elegant and ultimately reusable ... basing new designs on prior experience ... without having to rediscover them ... “ (Gamma et al. 1995) Design Patterns and Type Theory
Warning! Lots of details to follow! Design Patterns and Type Theory
A Design Problem • McSabry food chain needs a program to keep track of the food items it sells. • Initially, McSabry will focus on: ice cream, hotdogs, and pizza. • For each food item, we will need to keep track of its cost and selling price so that we can compute the profit from sales. Design Patterns and Type Theory
An Initial Java Design FoodItem Cost Price IceCream Hotdog Pizza Design Patterns and Type Theory
abstract class FoodItem { abstract int cost (); abstract int price(); } class HotDog … { … } class Pizza … { … } class IceCream extends FoodItem { int cost () { return 1; } int price () { return 5; } } Java Implementation Design Patterns and Type Theory
Sales and Profit class Profit { int profit (FoodItem[] sales) { int totcost = 0; int totprice = 0; for (int i=0; i<sales.length; i++) { totcost += sales[i].cost(); totprice += sales[i].price(); } return totprice – totcost; } } Design Patterns and Type Theory
McSabry expands… • McSabry decides to add Vegetables to its food items. • We need to modify the design and the program! Design Patterns and Type Theory
Updated Design FoodItem Cost Price Vegetables IceCream Hotdog Pizza Design Patterns and Type Theory
Updated Implementation class Vegetables extends FoodItem { int cost () { return 2; } int price () { return 4; } } Code already written does NOT have to change at all!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Design Patterns and Type Theory
FDA • Unfortunately McSabry discovered recently that the FDA requires that the company reports the number of calories in every food item. • Need to modify the design and program again! Design Patterns and Type Theory
Updated Design FoodItem Cost Price Calories Vegetables IceCream Hotdog Pizza Design Patterns and Type Theory
Updated Implementation • Oops! • Must go back and change EVERY class that we have written. • Scale this to millions of line of code • Let’s revise our original design… Design Patterns and Type Theory
The problem • We did not anticipate reuse in one dimension. • How could we modify the design to accommodate growth not only in new food items but also in new operations on food items. • Solution: the Visitor Pattern. Design Patterns and Type Theory
Visitor Pattern FoodItem accept Vegetables IceCream Hotdog Pizza visitIceCream visitHotDog visitPizza visitVegetables FoodVis CostVis PriceVis CaloriesVis Design Patterns and Type Theory
class IceCream extends FoodItem { int accept (FoodVis fv) { return fv.visitIceCream(); } } class PriceVis extends FoodVis { int visitIceCream () { return 5; } int visitVegetables () { return 4; } … } Implementation Design Patterns and Type Theory
Extensible Reusable Code • Possible to add new operations on food items without changing any existing code. • With another small modification, it is possible to add more food items without changing any existing code. Design Patterns and Type Theory
Summary of Part I Before we can “abstract” we must decide what is “relevant” and what is “irrelevant.” Need design experience, patterns, etc. Most CS courses teach abstraction. Focus on reuse comes in class that focus on programming in the large, software engineering, and OO design. Design Patterns and Type Theory
Part II Abstraction and Safety
Programming with Abstractions Assuming we have already decided what is relevant and what is irrelevant, how do really hide the irrelevant details and be sure they will not somehow leak out? Design Patterns and Type Theory
Types are a syntactic discipline for enforcing levels of abstractions [Reynolds] Not comments Part of the programming language Checked and enforced by the compiler Types Design Patterns and Type Theory
Interfaces (from Java 2) public interface Collection { boolean add (Object o); bollean addAll (Collection c); void clear (); boolean contains (Object o); boolean containsAll (Collection c); boolean equals (Object o); int hashCode (); boolean isEmpty (); Iterator iterator (); boolean remove (Object o); boolean removeAll (Collection c); boolean retainAll (Collection c); int size (); Object[] toArray (); Object[] toArray (Object[] a); } Design Patterns and Type Theory
Informal: If the compiler determines that some expression has type T, then it will have type T at runtime. No unanticipated errors. Bad example: Compiler determines that e has type int Hence ok to write 1+e But e evaluates to an array of booleans. Type Safety Design Patterns and Type Theory
Example in C (I) [From Intensional Equality for Continuations by Andrew Appel] A function in a high-level programming language is just the address of an instruction at the machine level. In C one can mix high-level functions and unsigned numbers!!! Design Patterns and Type Theory
Warning! Lots of details to follow! Design Patterns and Type Theory
Example in C (II) cMain (int ac, char*av[]) { int i,j; (void) srandom (atoi (av[1])); for (i=0; i < 10000000; i++) { j = quickroot (random()); } exit(0); } eMain() {} unsigned mycaller[] = { 0x81c3e008,0x9010001f }; Design Patterns and Type Theory
int quickroot (int i) { static x = 0; if (x) return cbrt (i); x=1; { unsigned *p, *q, caller; union { unsigned *z; unsigned (*f)(); } u; u.z = mycaller; caller = u.f(); if (caller <= (unsigned)main || caller >= (unsigned)main + (unsigned)eMain - (unsigned)cMain) return quickroot(i); } exit(0); } Example in C (III) Design Patterns and Type Theory
Layout: If main == cMain then do nothing If main is anything else then call the real cbrt function What’s going on? quickroot main Design Patterns and Type Theory
Why is this Bad? • The types don’t hide anything! • Unanticipated errors can happen • Evaluation can even proceed with nonsense • No abstraction Design Patterns and Type Theory
Why is it REALLY Bad? From Securing Java, John Wiley & Sons, Inc. The Java language is designed to enforce type safety. This means that programs are prevented from accessing memory in inappropriate ways… Type safety means that a program cannot perform an operation on an object unless that operation is valid for that object. Type safety is the most essential element of Java’s security… In our experience, every type safety violation has created an opportunity for an untrusted applet to break out of Java’s security restrictions. Design Patterns and Type Theory
Safety with a Straightjacket • Pascal was safe (almost!) • Pascal’s type system was very limited (a function that sorts an array of ints cannot sort an array of floats) • Need expressive type system that is safe. Here lies Pascal: A Language Chocked by its Type System Design Patterns and Type Theory
Lookup :: (Eq a) => a -> [(a,b)] -> Maybe b lookup key [] = Nothing lookup key ((x,y):xys) | key == x = Just y | otherwise = lookup key ys There are even more advanced type systems but they are not part of “mainstream” programming languages Hot research topic with new proposals emerging every year An Expressive & Safe Type System: Haskell Design Patterns and Type Theory
Haskell primitive types [Based on tutorial on haskell.org] • 5 :: Integer • ‘a’ :: Char • inc :: Integer -> Integer inc n = n+1 • [1,2,3] :: [Integer] • (‘b’,4) :: (Char, Integer) Design Patterns and Type Theory
Polymorphic Types • length :: forall a. [a] -> Integer length [] = 0 length (x:xs) = 1 + length xs • length [1,2,3] 3 • length [‘a’, ‘b’, ‘c’] 3 • length [[1,5], [2,5], [3,5]] 3 Design Patterns and Type Theory
User-Defined Types • data Bool = False | True • data Color = Red | Green | Blue | Indigo • data Point a = Pt a a • Pt 2.0 3.0 :: Point Float • Pt ‘a’ ‘b’ :: Point Char • Pt True False :: Point Bool • Pt ‘a’ 1 :: TYPE ERROR Design Patterns and Type Theory
Recursive Types • data Tree a = Leaf a | Branch (Tree a) (Tree a) • Branch :: Tree a -> Tree a -> Tree a • Leaf :: a -> Tree a • fringe :: Tree a -> [a] fringe (Leaf x) = [x] fringe (Branch left right) = fringe left ++ fringe right Design Patterns and Type Theory
Type Classes • class Eq a where (==) :: a -> a -> Bool • instance Eq Integer where x == y = x `integerEq` y • instance Eq Float where x == y = x `floatEq` y • instance (Eq a) => Eq (Tree a) where Leaf a == Leaf b = a == b (Branch l1 r1) == (Branch l2 r2) = (l1 == l2) && (r1 == r2) _ == _ = False Design Patterns and Type Theory
module Tree (Tree(Leaf,Branch), fringe) where data Tree a = Leaf a | Branch (Tree a) (Tree a) fringe :: Tree a -> [a] fringe (Leaf x) = [x] fringe (Branch l r) = fringe l ++ fringe r module Main (main) where import Tree( Tree(Leaf,Branch), fringe) main = print (fringe (Branch (Leaf 1) (Leaf 2))) Modules Design Patterns and Type Theory
Existential Types module TreeADT (Tree, leaf, branch, cell, left, right, isLeaf) where -- We know there exists a type Tree but representation is HIDDEN data Tree a = Leaf a | Branch (Tree a) (Tree a) leaf = Leaf branch = Branch cell (Leaf a) = a left (Branch l r) = l right (Branch l r) = r isLeaf (Leaf _) = True isLeaf _ = False Design Patterns and Type Theory
Monads & Memory Encapsulation • new :: forall a. a -> ST s (Ref s a) • read :: forall a. Ref s a -> ST s a • write :: forall a. Ref s a -> a -> ST s () • runST :: forall a. (forall s. ST s a) -> a • If (runST e) typechecks then: • e does not use any memory allocated from the outside • The memory allocated by e is not visible on the outside. • Can evaluate e on a local processor • Can immediately reclaim the memory used by e • etc Design Patterns and Type Theory
And so on … Parametricity Theorem for Haskell (informal) If a program typechecks then it is likely to be correct!!!!!! Intuition: Assume I tell you a term has type forall a. a -> a, what could it be? The only sensible term of this type is the function f defined as: f x = x Design Patterns and Type Theory