1 / 80

Hands-on Refactoring with Wrangler

Hands-on Refactoring with Wrangler. Simon Thompson Huiqing Li, Xingdong Bian University of Kent. Overview. What is refactoring? Examples The process of refactoring Tool building and infrastructure What is in Wrangler … demo Latest advances: data, processes, erlide.

reegan
Download Presentation

Hands-on Refactoring with Wrangler

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Hands-on Refactoring with Wrangler Simon Thompson Huiqing Li, Xingdong Bian University of Kent

  2. Overview • What is refactoring? • Examples • The process of refactoring • Tool building and infrastructure • What is in Wrangler … demo • Latest advances: data, processes, erlide.

  3. Introducing refactoring

  4. Soft-ware • There’s no single correct design … • … different options for different situations. • Maintain flexibility as the system evolves.

  5. Refactoring • Refactoring means changing the design or structure of a program … without changing its behaviour. Modify Refactor

  6. Examples

  7. -module (test). -export([f/1]). add_one ([H|T]) -> [H+1 | add_one(T)]; add_one ([]) -> []. f(X) -> add_one(X). -module (test). -export([f/1]). add_one (N, [H|T]) -> [H+N | add_one(N,T)]; add_one (N,[]) -> []. f(X) -> add_one(1, X). Generalisation Generalisation and renaming -module (test). -export([f/1]). add_int (N, [H|T]) -> [H+N | add_int(N,T)]; add_int (N,[]) -> []. f(X) -> add_int(1, X).

  8. -export([printList/1]). printList([H|T]) -> io:format("~p\n",[H]), printList(T); printList([]) -> true. printList([1,2,3]) -export([printList/2]). printList(F,[H|T]) -> F(H), printList(F, T); printList(F,[]) -> true. printList( fun(H) -> io:format("~p\n", [H]) end, [1,2,3]). Generalisation

  9. -export([printList/1]). printList([H|T]) -> io:format("~p\n",[H]), printList(T); printList([]) -> true. -export([printList/1]). printList(F,[H|T]) -> F(H), printList(F, T); printList(F,[]) -> true. printList(L) -> printList( fun(H) -> io:format("~p\n", [H]) end, L). Generalisation

  10. pid! {self(),msg} {Parent,msg} -> body pid! {self(),msg}, receive {pid, ok}-> ok {Parent,msg} -> Parent! {self(),ok}, body Asynchronous to synchronous

  11. Refactoring

  12. Transformation Ensure change at all those points needed. Ensure change at only those points needed. Condition Is the refactoring applicable? Will it preserve the semantics of the module? the program? Refactoring = Transformation + Condition

  13. Transformations full stop one

  14. Condition > Transformation • Renaming an identifier • "The existing binding structure should not be affected. No binding for the new name may intervene between the binding of the old name and any of its uses, since the renamed identifier would be captured by the renaming. Conversely, the binding to be renamed must not intervene between bindings and uses of the new name."

  15. Which refactoring exactly? • Generalise f by making 23 a parameter of f: • f(X) -> • Con = 23, • g(X) + Con + 23. • This one occurrence? • All occurrences (in the body)? • Some of the occurrences … to be selected.

  16. -export([oldFun/1, newFun/1]). oldFun(L) -> newFun(L). newFun(L) -> … … . -export([newFun/1]). newFun(L) -> … … . Compensate or crash? or ?

  17. Refactoring tools

  18. Tool support • Bureaucratic and diffuse. • Tedious and error prone. • Semantics: scopes, types, modules, … • Undo/redo • Enhanced creativity

  19. Semantic analysis • Binding structure • Dynamic atom creation, multiple binding occurrences, pattern semantics etc. • Module structure and projects • No explicit projects for Erlang; cf Erlide / Emacs. • Type and effect information • Need effect information for e.g. generalisation.

  20. Erlang refactoring: challenges • Multiple binding occurrences of variables. • Indirect function call or function spawn: apply (lists, rev, [[a,b,c]]) • Multiple arities … multiple functions: rev/1 • Concurrency • Refactoring within a design library: OTP. • Side-effects.

  21. Static vsdynamic • Aim to check conditions statically. • Static analysis tools possible … but some aspects intractable: e.g. dynamically manufactured atoms. • Conservative vsliberal. • Compensation?

  22. Architecture of Wrangler

  23. Wrangler in Emacs

  24. Refactorings in Wrangler Renaming variable, function, module, process Function generalisation Move function between modules. Function extraction Fold against definition Introduce and fold against macros. Tuple function arguments together Register a process From function to process Add a tag to messages All these refactorings work across multiple-module projects and respect macro definitions.

  25. Wrangler demo

  26. Tool building

  27. Lightweight. Better integration with interactive tools (e.g. emacs). Undo/redo external? Ease of implementing conditions. Higher entry cost. Better for a series of refactorings on a large project. Transaction support. Ease of implementing transformations. Wrangler and RefactorErl

  28. Duplicate Code Detection Especially for Erlang/OTP programs. Report syntactically well-formed code fragments that are identical after consistent renaming of variables … … ignoring differences in literals and layout. Integrated with the refactoring environment.

  29. Code Inspection Support • Variable use/binding information. • Caller functions. • Caller/callee modules. • Case/if/receive expressions nested more than a specified level. • Long function/modules. • Non tail-recursive servers. • Non-flushed unknown messages • . . .

  30. Integration … with IDEs • Back to the future? Programmers' preference for emacs and gvim … • … though some IDE interest: Eclipse, NetBeans … • Issue of integration with multiple IDEs: building common interfaces.

  31. Integration … with tools • Test data sets and test generation. • Makefiles, etc. • Working with macros e.g. QuickCheck uses Erlang macros … • … in a particular idiom.

  32. APIs … programmer / user • API in Erlang to support user-programmed refactorings: • declarative, straightforward and complete • but relatively low-level. • Higher-level combining forms? • OK for transformations, but need a separate condition language.

  33. Verification and validation • Possible to write formal proofs of correctness: • check conditions and transformations • different levels of abstraction • possibly-name binding substitution for renaming etc. • more abstract formulation for e.g. data type changes. • Use of Quivq QuickCheck to verify refactorings in Wrangler.

  34. Clone detection

  35. The Wrangler Clone Detector • Uses syntactic and static semantic information. • Syntactically well-formed code fragments • … identical after consistent renaming of variables, • … with variations in literals, layout and comments. • Integrated within the refactoring environment.

  36. The Wrangler Clone Detector • Make use of token stream and annotated AST. • Token–based approaches • Efficient. • Report non-syntactic clones. • AST-based approaches. • Report syntactic clones. • Checking for consistent renaming is easier.

  37. The Wrangler Clone Detector Source Files Tokenisation Token Stream Normalisation Normalised Token Stream Suffix Tree Construction Suffix tree

  38. The Wrangler Clone Detector Source Files Tokenisation Parsing + Static Analysis Token Stream Annotated ASTs Syntactic Clones Normalisation Clone Decomposition Filtered Initial Clones Normalised Token Stream Suffix Tree Construction Clone Filter Suffix tree Initial Clones Clone Collector

  39. The Wrangler Clone Detector Source Files Tokenisation Parsing + Static Analysis Token Stream Annotated ASTs Syntactic Clones Consistent Renaming Checking Normalisation Clone Decomposition Filtered Initial Clones Normalised Token Stream Clones to report Suffix Tree Construction Clone Filter Suffix tree Initial Clones Clone Collector

  40. The Wrangler Clone Detector Source Files Tokenisation Parsing + Static Analysis Token Stream Annotated ASTs Syntactic Clones Consistent Renaming Checking Normalisation Clone Decomposition Filtered Initial Clones Normalised Token Stream Clones to report Suffix Tree Construction Clone Filter Formatting Suffix tree Initial Clones Clone Collector Reported Code Clones

  41. Clone detection demo

  42. Support for clone removal • Refactorings to support clone removal. • Function extraction. • Generalise a function definition. • Fold against a function definition. • Move a function between modules.

  43. Case studies • Applied the clone detector to Wrangler itself with threshold values of 30 and 2. • 36 final clone classes were reported …12 are across modules, and 3 are duplicated function definitions. • Without syntactic checking and consistent variable renaming checking, 191 would have been reported. • Applied to third party code base (32k loc, 89 modules),109 clone classes reported.

  44. Data-oriented refactorings

  45. -module(tup1). -export([gcd/2]). gcd(X,Y) -> if X>Y -> gcd(X-Y,Y); Y>X -> gcd(Y-X,X); true -> X ‏ end. Tupling parameters -module(tup1). -export([gcd/1]). gcd({X,Y}) -> if X>Y -> gcd({X-Y,Y}); Y>X -> gcd({Y-X,X})‏; true -> X end. 2

  46. -module(rec1). g({A, B})-> A + B. h(X, Y)-> g({X, X}), g(Y). Introduce records … -module(rec1). -record(rec,{f1, f2}). g(#rec{f1=A, f2=B})-> A + B. h(X, Y)-> g(#rec{f1=X,f2=X}), g(#rec{ f1=element(1,Y), f2=element(2,Y)}). f1 f2

More Related