570 likes | 694 Views
Building “Real World” Software in Academia. Matthias Felleisen PLT, Rice University. What is the “Real World”? … the Problem?. The TeachScheme! Project Problems with Scheme Building DrScheme Technical Problems Today: Extensibility or Single Point of Control. The TeachScheme! Project .
E N D
Building “Real World” Software in Academia MatthiasFelleisen PLT, Rice University
What is the “Real World”? … the Problem? • The TeachScheme! Project • Problems with Scheme • Building DrScheme • Technical Problems • Today: Extensibility or Single Point of Control
The TeachScheme! Project • Everyone should learn to program • … should do so early • … and it should be in Scheme • Scheme programming teaches critical skills: algebraic problem solving • Every student benefits …. • … not just the few who continue to program
Example #1 Arithmetic Algebra Scheme Pascal 4 + 5 = 9 (+ 4 5) 9 Program Add (Output); Begin Writeln (4 + 5) End. <compile> <run> 9
Example #2 A Simple Function Algebra Pascal f(x) = 4 + x Program f (Input, Output) ; Var x : Integer ; Begin Readln ( x ) ; Writeln ( 4 + x ) End . Scheme ( define ( f x ) ( + 4 x ))
The Problems We Are Facing • psychology of teachers, students and parents • sociology of AP, principals, and administrators • a technical problem: Scheme’s syntax isn’t all that simple
Scheme’s Syntax is Bad #1 (define (length alist) (cond ((empty? alist) 0) (else 1 + (length (rest alist)))))
Scheme’s Syntax is Bad #2 (define (length alist) (cond (null? (alist) 0) (else (+ 1 (length (rest alist))))))
Our Solution: DrScheme • a hierarchy of languages • each level matches a student’s skill level • each level provides matching error messages • … plus a few tools: • a syntax checker & alpha renamer • a symbolic stepper • a type-flow analysis • currently used at around 80 universities/schools by around 8000 to 10000 students
The Language Hierarchy (Excerpts) d = (define (f v …) e) e = v | (f e …) | (primitive e …) | (cond (e e) …) f = name v = name d = (define-struct v (v …)) e = (local (d …) e) d = (define v e) | (set! v e) | (cond (e …) …) each level extends the level below
Building Extensible Software MatthiasFelleisen PLT, Rice University
The Technical Problem: • We need extensible software components: • extensible parser • extensible evaluator • … • By developing each language level once and reusing it for all extensions, we save a huge amount of work (and maintenance work) • Principle: Single Point of Control
The Technical Solutions: • What does “extensible component” mean? • The programmer’s programmer’s perspective • composing patterns • composing patterns, again • The programming language perspective
Extensible Software Components cut, paste, edit add / link Matthias Felleisen: Base Extensible Base Modified Component Extension
Extensible Components are Good • No access to source code needed: critical for a Web-based model of software production & sales • Even if source code is accessible: programming for extensibility forces programmers to create a single point of control for many “functions” • Finally, it increases the reuse potential.
Extensibility is Not Guaranteed • Rumor 1: OOPLs guarantee extensibility. • Rumor 2: OO Design patterns do. • Rumor 3: Scheme does it :-) Krishnamurthi and Felleisen [FSE98]
The “Big” Problem for Extensibility | (let (var E) E) | (if E E E) E = var | (lambda (var) E) | (E E) void f(E some_e) { … } atyp g(E some_e) { … } E h(String s) { … } variant extension btyp m(E some_e) { … } E o(E an_e) { … } functional extension
Previous Attempts to Solve “It” • Reynolds (76): “It” is a problem … • Guy Steele (93): quasi-monads for interpreters • Cartwright and Felleisen (94): extensible interpreters • Hudak, Jones, and Liang (92-97): extensible “geometry server” for Navy
Solution 1: The Magic of Composing Patterns
A Closer Look at Objects and Classes • Classes make variant extensions straightforward. • The visitor pattern makes functional extensions straightforward. • Let’s combine these two virtues!
Datatypes as Class Hierarchies e = c | v | (lambda (x ...) e) | (e e) | ...
Datatype Visitors forConstants forVariables forProcedures forApplications forConstants forVariables forProcedures forApplications forConstants forVariables forProcedures forApplications
A Concrete Visitor class PrintVisitor implements VisitorIF { void forConstants(… aConstant) { … } void forVariables( …aVariable) { … } void forProcedures(… aProcedure){ … } void forApplication(… anApplication){ … } class Constant extends Expression { void toVisitor(VisitorIF aVisitor) { aVisitor.forConstants(this) ; } } Expression k; … k.toVisitor(new PrintVisitor()); ...
A Variant Extension forConstants forVariables forProcedures forApplications Expression Conditional (if e e e) forConditionals
So What’s the Problem? forConstants forVariables forProcedures forApplications new PrintVisitor(…) Expression Conditional (if e e e) forConditionals The Fix: Use Virtual Constructor Pattern
The Solution Imposes • Composing patterns: • Interpreter Pattern (natural) • Visitor Pattern • Virtual Constructor Pattern • Complex interactions between patterns • Numerous run-time type checks
Solution 2: More Magic with Patterns
Another Closer Look at Objects and Classes • Classes make variant extensions straightforward. • Inheritance can add functionality. • Let’s combine these two virtues!
Datatypes and Clients Parser for Expression Expression
So What’s the Problem Now? Method1 Method1 Method1 Method1 Ouch -- It’s the wrong kind of expression! Parser for Expression Expression
Linking the Parser via a Factory Expression Factory Expression Factory Parser for Expression Expression Method1 Method1 Method1 Method1
The Second OO Solution Imposes • Composing patterns: • interpreter pattern • abstract factory • virtual constructor (or two AF) • Complex interactions between patterns • Numerous run-time type checks
Summary of OO Solutions • Programming for extensibility and for single point of control is feasible in existing OOPLs • But, the code is difficult to produce and maintain. • It suggests a new challenge to language designers.
Solution 3: The Language Designer at Work
How a Language Designer Can Help: A programming language should support both • classes and • hierarchical modules with external connectors.
Modules imports A module definitions C B exports
Linking and Nesting Modules A C E B D
Classes in Modules exports:classes, abstract classes, and interfaces imports: classes, abstract classes, and interfaces Conditionals (cond (e e) …)
Clients of Datatypes new Constants(…) ; … new Procedure(…)
Adding Variants, Again Conditionals (cond (e e) …) link to old clients, link to new clients now
Adding Functionality, Again Conditionals (cond (e e) …) new_method new_method new_method new_method new_method link to old clients, link to new clients now