HEDGEHOG: Automatic Verification of Design Patterns in Java
Total Page:16
File Type:pdf, Size:1020Kb
HEDGEHOG: Automatic Verification of Design Patterns in Java Alex Blewitt I V N E R U S E I T H Y T O H F G E R D I N B U Doctor of Philosophy School of Informatics University of Edinburgh 2006 Abstract Design patterns are widely used by designers and developers for building complex systems in object-oriented programming languages such as Java. However, systems evolve over time, increasing the chance that the pattern in its original form will be broken. To verify that a design pattern has not been broken involves specifying the original intent of the design pattern. Whilst informal descriptions of patterns exist, no formal specifications are available due to differences in implementations between programming languages. This thesis shows that many patterns (implemented in Java) can be verified automatically. Patterns are defined in terms of variants, mini-patterns, and artefacts in a pattern description language called SPINE. These specifications are then processed by HEDGEHOG, an automated proof tool that attempts to prove that Java source code meets these specifications. iii Acknowledgements I am indebted to Alan Bundy who has given me the freedom to work on this thesis whilst at the same time guiding me towards the final production and presentation of these results. I not would have been able to achieve this without Alan’s support through a sometimes difficult, but always busy part of my life. This project, and especially the production of this thesis, would not have been possible without the care and attention that Alan provided. Ian Stark has provided invaluable feedback on all aspects of this thesis, from the low-level technical intricacies of Java’s design patterns through to the high-level structure of the thesis as a whole. Without doubt, he has caught many of the technical errors and inconsistencies of this thesis; the fact that this work stands as it is can be attributed to his detailed attention to proof reading. Any remaining errors are my own fault in transcribing his feedback of the work. I would also like to thank my previous supervisors, Richard Boulton and Helen Lowe, who helped me during the early stages of this research project before other commitments took them aside. In addition, Andrew Ireland helped with some very early aspects, and in conjunction with Alan Bundy allowed me to realise that my ideas were worth investigating, and convinced me to start down the long path of a PhD. Jon Whittle gave me support and a path to follow as I started out on this thesis. I would not have been able to do this thesis without the support of Adrian Jackson and others from International Object Solutions Limited, whose support allowed me to work in conjunction with EPSRC to create HEDGEHOG. My thanks are also due to the proof readers who gave me pages of feedback on this thesis, in alphabetical order: Derek Blewitt, Robert Blewitt, Tony Brookes, Adrian Jackson and Gareth Webber. I would also like to thank some of the particularly influential people for encouraging me to achieve my full potential; Ian Nussey of IBM UK and ‘Doc’ Misell of Epsom College. My thanks also go to Koos van Tubergen of IBM NL for supporting me through the early stages of my PhD. Lastly, I would especially like to thank my loving wife Amy, for putting up with me over the past few years with all the late nights (and sometimes early mornings) in working on this project. iv Declaration I declare that this thesis was composed by myself, that the work contained herein is my own except where explicitly stated otherwise in the text, and that this work has not been submitted for any other degree or professional qualification except as specified. (Alex Blewitt) v This thesis is dedicated to the memory of our son Max, who was born and died during the production of this thesis. vi Table of Contents 1 Introduction 1 1.1 Structure of the thesis . 2 1.2 Hypothesis and contributions . 3 2 Literature survey 5 2.1 Java........................................ 7 2.1.1 Byte-code . 7 2.1.2 Java language semantics . 9 2.1.3 Java modelling and constraints . 13 2.2 Design patterns . 17 2.2.1 Specification . 17 2.2.2 Detection . 21 2.2.3 Refactoring . 23 2.3 Summary . 25 3 System architecture 27 3.1 HEDGEHOG .................................... 27 3.2 Parsing Java source files . 29 3.3 Parsing and processing SPINE files . 31 3.4 Interacting with the user . 31 3.5 Summary . 32 4 Design patterns 33 4.1 The history of patterns . 33 4.1.1 Software design patterns . 34 4.2 Terminology . 36 4.2.1 Realises . 36 vii 4.2.2 Variant . 36 4.2.3 Artefact . 39 4.2.4 Super-pattern . 39 4.2.5 Mini-pattern . 41 4.3 Formally defining patterns . 42 4.3.1 Run-time semantic definition . 43 4.3.2 Metaprogramming definition . 45 4.3.3 Declarative constraint definition . 47 4.4 Elements of patterns . 49 4.4.1 Reviewing existing patterns . 49 4.4.2 Intent . 51 4.5 Summary . 52 5 The SPINE language 53 5.1 Overview . 53 5.2 Syntax . 55 5.3 Semantics . 56 5.3.1 Basic propositions . 56 5.3.2 Evaluable propositions . 57 5.3.3 Evaluable sets . 58 5.4 Rules . 59 5.5 Java constraints . 60 5.5.1 Structural constraints . 60 5.5.2 Semantic constraints . 61 5.5.3 Weak semantic constraints . 61 5.6 Patterns . 62 5.6.1 Immutable . 62 5.6.2 Singleton . 63 5.7 Summary . 65 6 The HEDGEHOG proof engine 67 6.1 Representing Java . 69 6.1.1 Java source files . 69 6.1.2 Java class files . 70 6.1.3 Inner classes . 74 viii 6.1.4 Native methods . 74 6.2 Proof engine . 75 6.2.1 Overview of proof process . 75 6.2.2 Proof tree . 76 6.2.3 Rules . 77 6.2.4 Backtracking . 80 6.2.5 Proof strategy . 80 6.2.6 Soundness . 81 6.2.7 Termination . 81 6.2.8 Complexity . 88 6.3 Built-in functions and predicates . 90 6.4 Summary . 92 7 Generating error messages 93 7.1 Tree filtering . 94 7.2 Converting trees to error messages . 94 7.2.1 Displaying a complete reason . 95 7.2.2 Compressing the message . 95 7.3 Interesting errors . 95 7.3.1 Chains with uninteresting beginnings or ends . 96 7.3.2 Tree nodes with interesting children . 97 7.4 Pattern annotation . 97 7.5 From nodes to explanations . 98 7.6 Example . 99 7.7 Summary . 102 8 Worked examples 103 8.1 Startup . 103 8.2 Simple proofs . 105 8.3 Proving a class realises a pattern . 108 8.3.1 Parsing the Java source . 110 8.3.2 Applying quantifiers . 111 8.4 Multi-class patterns . 114 8.5 Dealing with failure . 116 8.6 Summary . 117 ix 9 Results 119 9.1 Critique of patterns as constraints . 119 9.1.1 Unrepresentable patterns . 120 9.1.2 Abstract Factory . 121 9.1.3 Factory Method . ..