Refactoring Functional Programs Simon Thompson with Huiqing Li Claus Reinke .
-
Upload
allan-coveny -
Category
Documents
-
view
216 -
download
1
Transcript of Refactoring Functional Programs Simon Thompson with Huiqing Li Claus Reinke .
Refactoring Functional Programs
Simon Thompson
with
Huiqing Li
Claus Reinke
www.cs.kent.ac.uk/projects/refactor-fp
AFP04 2
Session 1
AFP04 3
Refactoring
Refactoring means changing the design or structure of a program … without changing its behaviour.
RefactorModify
AFP04 4
Splitting a function in two
AFP04 5
Splitting a function in two
AFP04 6
Splitting a function in two
AFP04 7
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = foldr (++) [] [ y++"\n" | y <- ys ]
AFP04 8
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = foldr (++) [] [ y++"\n" | y <- ys ]
AFP04 9
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join [y ++ "\n" | y <- ys] where join = foldr (++) []
AFP04 10
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join [y ++ "\n" | y <- ys] where join = foldr (++) []
AFP04 11
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join addNL where join zs = foldr (++) [] zs addNL = [y ++ "\n" | y <- ys]
AFP04 12
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join addNL where join zs = foldr (++) [] zs addNL = [y ++ "\n" | y <- ys]
AFP04 13
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join (addNL ys) where join zs = foldr (++) [] zs addNL ys = [y ++ "\n" | y <- ys]
AFP04 14
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join (addNL ys) where join zs = foldr (++) [] zs addNL ys = [y ++ "\n" | y <- ys]
AFP04 15
Splitting a functionmodule Split where
f :: [String] -> [String] -> String
f ys = join (addNL ys) join zs = foldr (++) [] zs
addNL ys = [y ++ "\n" | y <- ys]
AFP04 16
Generalisation
ff 9 + 37
h x = … f 9 + 37 …
e = h 37 + 12
AFP04 17
Generalisation
f 9 + 37
h y x = … y …
e = h (f 9 + 37) 37 + 12
AFP04 18
Session 1
Potted history of refactoring.
Refactoring and design.
Example refactorings … what do we learn?
Demonstration of the HaRe tool for Haskell.
A practical exercise.
AFP04 19
A little bit of history …
Floyd, 1978 Turing Award Lecture: encourages reflective revision.
Griswold: Automated assistance for (LISP) program restructuring.
Opdyke: Refactoring OO Frameworks.
Fowler et al: Refactoring: Improving the Design of Existing Code.
AFP04 20
Refactoring in OO
Smalltalk refactoring browser … relies heavily on reflection.
Built into a number of IDEs: Eclipse, …
Refactor and test … major way of ensuring correctness of refactorings …
… others require heavyweight static analysis.
Link with design …
AFP04 21
Design
Structure of the program?• Modules, types, interfaces …
Artefact?• UML diagrams of various kinds …• … with accompanying constraints.• Model Driven Architecture
Design patterns?
The problem of consistency: design vs code.
AFP04 22
Designing functional programs
No evidence of an appetite for separate modelling languages …
No established terminology of patterns …
… it’s all in the code.
AFP04 23
Development
Development of functional programs
is spiral …
… from a working base, extend, refactor and elaborate.
Design emerges.
AFP04 24
Soft Ware
There’s no single correct design …
… different options for different situations.
Maintain flexibility as the system evolves.
AFP04 25
Modify and refactor
AFP04 26
Refactoring functional programs
Semantics: can articulate preconditions and verify transformations.
Absence of side effects makes big changes predictable and verifiable … unlike OO.
Language support: expressive type system; abstraction mechanisms: higher order functions, classes, …
AFP04 27
Rename f x y = …
Name may be too specific, if the function is a candidate for reuse.
findMaxVolume x y = …
Make the specific purpose of the function clearer.
Scope: just change occurrences of this f.
Modules: change f (and M.f) everywhere.
AFP04 28
Lift / demotef x y = … h … where h = …
Hide a function which is clearly subsidiary to f; clear up the namespace.
f x y = … (h y) … h y = …
Makes h accessible to the other functions in the module and beyond.
Free variables: which parameters of f are used in h?
Need h not to be defined at the top level, … ,
Type of h will generally change … DMR.
AFP04 29
Lessons from these examples
Ensuring correctness requires knowledge of:
Lexical structure of programs Abstract syntax Binding structure Type system Module system
AFP04 30
Lessons from these examples
Changes are not limited to a single point or even a single module: diffuse and bureaucratic …
Most refactorings bidirectional …
… unlike traditional program transformation.
AFP04 31
Visualising the effect
Estimating the effect of a refactoring.
Work by
Chris Ryder
AFP04 32
Program transformations
Operational semantics reduction to normal form
Program optimisation source-to-source transformations to get more efficient code
Program derivation calculating efficient code from obviously correct specifications
Refactoring transforming code structure
Related themes, with substantial overlap, and common theory, but with different intentions.
AFP04 33
Conditions: renaming f to g
“No change to the binding structure”
1. No two definitions of g at the same level.
2. No capture of g.
3. No capture by g.
AFP04 34
Capture of renamed identifier h x = … h … f … g … where g y = …
f x = …
h x = … h … g … g … where g y = …
g x = …
AFP04 35
Capture by renamed identifier h x = … h … f … g … where f y = … f … g …
g x = …
h x = … h … g … g … where g y = … g … g …
g x = …
AFP04 36
Refactoring by hand?
By hand = in a text editor
Tedious
Error-prone• Implementing the transformation …• … and the conditions.
Depends on compiler for type checking, …
… plus extensive testing.
AFP04 37
Machine support invaluable
Reliable
Low cost of do / undo, even for large refactorings.
Increased effectiveness … and creativity.
AFP04 38
Demonstration of HaRe, hosted in vim.
AFP04 39
The refactorings in HaRe
Rename
Delete
Lift / Demote
Introduce definition
Remove definition
Unfold
Generalise
Add/remove parameters
Move def between modules
Delete/add to exports
Clean imports
Make imports explicit
data type to ADT
Short-cut, warm fusion
All module aware
AFP04 40
Practical exercise
A practical exercise in reflective programming and design.
Work together in groups, preferably pairs.
AFP04 41
Two roles
The writer writes design or types the program.
The logger keeps a log of the process:• Rationale for design decisions.• Refactorings in the design or the coding• Purpose, effect, extent.
Regularly swap roles.
Better understand refactoring in practice.
AFP04 42
Context
ASCII log files plus program(s) … conclusions to go on the web.
Mail to [email protected]
To reach a consensus on which refactorings are most useful and commonly used.
• Document.• Implement.• Evaluate API.
AFP04 43
What?
Any project of your own choice, perhaps building on other courses at AFP04.
Alternatively, a minesweeper program.
AFP04 44
Minesweeper
AFP04 45
Minesweeper
Mines distributed in a grid: find and mark all the mines.
On revealing a square, lose if it’s occupied, if not see # adjacent.
If # is zero, clear connected region.
Can also unmark.
AFP04 46
Minesweeper extensions
Add deduction: play all the guaranteed moves …
… or probability: reveal the square which is least likely to explode.
Show the deductions: how large support set for each deduction?
AFP04 47
Minesweeper extensions
Add a GUI …
… or animation.
Allow backtracking?