A Catalogue of Functional Refactorings Version 1
暂无分享,去创建一个
This document is the first draft of a catalogue of refactorings for functional programs. Most are applicable to a variety of modern functional programming languages – with the example code begin written in Haskell – but some relate specifically to Haskell and are marked as such. What is Refactoring? Refactoring is ‘improving the design of existing code’ and as such, it has been practised as long as programs have been written. It was first identified as an activity in its own right within the object-oriented programming community [3, 4] (http://www.refactoring.com). When does refactoring arise? To take an example, we might first program a system using an algebraic data type, and then decide to change the way that the data are represented. How should we proceed with this? One option is to modify the data type directly, that is to achieve the modification in a single step: this will require us to make substantial modifications to a program’s functionality and structure simultaneously. On the other hand, we might do the same in two stages. First we could transform the algebraic data type into an abstract data type (ADT), and only after this refactoring is done, would we modify the definition of the ADT. This two-stage transformation aims to separate the structural changes (from algebraic to abstract data type) from the changes in functionality. It also makes the program more amenable to further change, as ADT representations can be modified with no cost to the client. We refactor in other situations too. We might program in an exploratory way: first establishing the functionality we seek, and then refactoring into a more elegant form. We suspect that functional languages are particularly suited to this form of programming, because their clean semantic basis makes wholesale transformations more feasible than for a language in the C family, say. Finally, we might refactor someone else’s program to make it more readable; some of the refactorings given in this note were inspired by trying to fully understand some non-trivial student assessments written in Haskell. The Nature of Refactoring One of the simplest refactorings – Refactoring 1 in this catalogue – is to rename a function to reflect its use. We have already discussed the rather more complex Refactoring 9 from an algebraic to an abstract data type. These examples share two important characteristics of refactorings. Di use Their effect is diffuse, in that they require changes throughout a module and indeed throughout a system of modules. A change of function name needs to be effected at each function call; a change from a data type to an ADT will require changes to all functions that directly manipulate the data by pattern matching, for instance. Bidirectional A change from a general name (e.g. f) to a more specific one (e.g. findMaxVolume) might later be followed by a change to a more general name (e.g. findMax). We have discussed the change from an algebraic data type to an ADT, but in other situations it is perfectly reasonable to change an ADT into an algebraic type. One motivation might be to use pattern matching, another to use the deriving facilities over data in Haskell. Supporting Refactoring We have seen that refactorings have a bureaucratic aspect: changes have to be made at all sites that a function is called, for example. With current technology we would use a text editor to assist in making the changes, and rely on a type checker to catch any errors introduced in the refactoring. OO refactorers underline the importance of continual (re)testing of code to ensure correctness [1]. For a functional programming language one could use reasoning to establish the correctness of many classes of refactorings. Moreover, it is entirely feasible to support these refactorings in a variety of tools of increasing levels of sophistication; the experience of the OO community [2] in this respect is broadly positive. A tool could allow users to do and undo refactorings of various sorts; it could also check the applicability of certain transformations, such as renaming or lifting. More detailed considerations of tool design are to be found in [5]. The catalogue The body of this paper is a list of refactorings applicable to functional programs written in the ML/Haskell/Miranda school of strongly-typed functional language.
[1] Kent L. Beck,et al. Extreme programming explained - embrace change , 1990 .
[2] K. Beck,et al. Extreme Programming Explained , 2002 .
[3] Martin Fowler,et al. Refactoring - Improving the Design of Existing Code , 1999, Addison Wesley object technology series.
[4] William F. Opdyke,et al. Refactoring object-oriented frameworks , 1992 .