Refactoring Functional Programs Simon Thompson with Huiqing Li Claus Reinke .

Post on 31-Mar-2015

213 views 1 download

Tags:

transcript

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 sjt@kent.ac.uk

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?