thesis budianto 20299965

114
Refactoring AutoSim for Program Comprehension By Budianto Student Number: 20299965 DISSERTATION Submitted in partial fulfillment of the requirement for the degree of Master of Engineering in Information Communication Technology in School of Electrical, Electronic and Computer Engineering of University of Western Australia Perth, Western Australia Supervisor: Associate Professor Thomas Bräunl Submitted on: 29 May 2009

Upload: budianto07

Post on 16-Nov-2014

177 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Thesis Budianto 20299965

Refactoring AutoSim for Program Comprehension

By

Budianto

Student Number: 20299965

DISSERTATION

Submitted in partial fulfillment of the requirement

for the degree of Master of Engineering in Information Communication Technology

in School of Electrical, Electronic and Computer Engineering of

University of Western Australia

Perth, Western Australia

Supervisor: Associate Professor Thomas Bräunl

Submitted on: 29 May 2009

Page 2: Thesis Budianto 20299965

ii

Letter of Transmittal

Budianto

15B Garvey St

Waterford, 6152

Western Australia

29 May 2009

The Dean

Faculty of Engineering Computing and Mathematics

The University of Western Australia

35 Stirling Highway

CRAWLEY WA 6009

Dear Sir

I submit to you this dissertation entitled “Refactoring AutoSim for Program Comprehension” in

partial fulfillment of the requirement of the award of Master of Engineering in Information and

Communication Technology.

Yours faithfully

Budianto

Page 3: Thesis Budianto 20299965

iii

Abstract

This dissertation provides Automotive Simulator program restructuring activities that improve

software design, software understandability, and software reusability.

Firstly, it introduces some low level refactoring that is the fundamental aspect of program

restructuring especially to improve code readabilities and program comprehension. These

refactoring is also the preliminary strategies to assist the high level refactoring that can be used

to improve the software design and software reusability.

This dissertation identifies the code readability issues in Automotive Simulator, presents some

low level refactoring operations to improve code readability, explores some multithreading

implementation, performs program restructuring on the multithreading management, mitigates

singleton pattern overuse, implements state transition modeling using state pattern, and

introduces the creational pattern for data creation.

Page 4: Thesis Budianto 20299965

iv

Acknowledgement

First of all, I would like to thank my supervisor, Thomas Bräunl, for His guidance and also

advices given are the most appreciated. I am grateful for his valuable time for reading the first

draft of this dissertation and giving lots of insights in every weekly Monday meeting as well. I

am amazed by his stamina towards several research projects that encourage me to do this project.

I hope that our collaboration will continue in the coming days.

I wish to thank to Terry Woodings, for being an inspiring lecturer and his tremendous views on

software engineering. His insightful assignments also keep me busy and give invaluable ideas to

this project as well.

Thanks to AusAID for supporting my study in the University of Western Australia. I also thank

to Christine Kerin, the AusAID liaison, who provides support during my study.

I would like to thank Steven Bradley for sharing the ideas and also discussing about each

project‟s progress and difficulties that both faced. I am also thankful to Hilman Pardede and

Shaun my classmates.

I wish to thank to my beloved parents for their supports, and especially their guidance and also

the encouragements given. For their love and understanding that are the most precious things for

me.

I would like to thank to Eveline for her supports, encouragements and her prayer for me until this

project is being accomplished.

I wish to thank to all my friends both in Indonesia and Perth, for all their encouragements and

pray for me. I feel really grateful also for the great fellowship that I have found in MRII Perth

and Phillia Philharmonic Choir that giving me such a huge supports and motivations.

Finally, I thank God for granting me talents and opportunities that made this possible and for my

salvation. Fundamentally, everything is vanity without Him.

Page 5: Thesis Budianto 20299965

v

Table of Contents

Letter of Transmittal .................................................................................................................... ii

Abstract ......................................................................................................................................... iii

Acknowledgement ........................................................................................................................ iv

Table of Contents .......................................................................................................................... v

List of Tables ................................................................................................................................ ix

List of Figures ................................................................................................................................ x

Chapter 1 Introduction ................................................................................................................ 1

1.1 Simulation Overview ........................................................................................................ 1

1.2 Driving Simulator History ................................................................................................ 2

1.3 Autonomous Driving ........................................................................................................ 5

1.4 AutoSim Overview ........................................................................................................... 6

1.5 The Problem ..................................................................................................................... 7

1.6 Proposed Solutions ........................................................................................................... 7

1.7 Challenges ........................................................................................................................ 8

1.8 Major Contributions ......................................................................................................... 9

Chapter 2 Motivation and Related Works ............................................................................... 10

2.1 Motivation Examples ...................................................................................................... 10

2.2 Design Pattern ................................................................................................................ 12

2.3 Works on Refactoring ..................................................................................................... 13

2.3.1 Early Works on Refactoring .................................................................................... 13

2.3.2 Formalizing Refactoring ......................................................................................... 15

2.3.3 Refactoring Research .............................................................................................. 15

2.3.4 Refactoring Tools .................................................................................................... 16

Page 6: Thesis Budianto 20299965

vi

2.3.5 Refactoring in Practices .......................................................................................... 16

2.4 Automotive Simulation .................................................................................................. 17

Chapter 3 AutoSim Functionalities and Support .................................................................... 19

3.1 AutoSim Graphical User Interfaces ................................................................................ 19

3.1.1 Loading Process on AutoSim Server and Client ..................................................... 19

3.1.2 AutoSim Client Interface ........................................................................................ 20

3.1.3 AutoSim Client Networking Interface .................................................................... 20

3.2 AutoSim Structure Overview ......................................................................................... 22

3.2.1 AutoSim Client Design Overview .......................................................................... 22

3.2.2 AutoSim Server Design Overview .......................................................................... 23

3.3 AutoSim Libraries .......................................................................................................... 24

3.4 Automation Tools ........................................................................................................... 25

Chapter 4 Refactoring on Code Readability ........................................................................... 27

4.1 C++ ................................................................................................................................. 27

4.2 The Aspect of Coding ..................................................................................................... 28

4.2.1 Coding and Design .................................................................................................. 28

4.2.2 Program Comprehension ......................................................................................... 29

4.3 Coding Quality in AutoSim ............................................................................................ 29

4.3.1 Code Clone .............................................................................................................. 29

4.3.2 Unstructured Statement Organization ..................................................................... 30

4.3.3 Long Statement ....................................................................................................... 31

4.3.4 Semantic Meaning of Program ................................................................................ 32

4.4 Refactoring for Code Readability ................................................................................... 32

4.5 Discussion ....................................................................................................................... 37

Page 7: Thesis Budianto 20299965

vii

Chapter 5 Refactoring Multithreading Application ............................................................... 38

5.1 Multithreading Overview ............................................................................................... 38

5.2 AutoSim‟s MultiThreading Management ....................................................................... 39

5.3 Restructuring Multithreading ......................................................................................... 41

5.4 AutoSim‟s Structure ....................................................................................................... 44

5.5 Impact after Multithreading Resructuring ...................................................................... 45

5.6 Exception Handler Features ........................................................................................... 45

5.7 Summary ......................................................................................................................... 47

Chapter 6 Refactoring Singleton Pattern Overuse ................................................................. 48

6.1 Singleton Overview ........................................................................................................ 48

6.2 Example of Singleton in AutoSim .................................................................................. 50

6.3 Singleton Overuse .......................................................................................................... 50

6.3.1 Motivation of singleton usage ................................................................................. 50

6.3.2 An Example: Debugging Experience in Singleton Overuse Design ....................... 51

6.3.3 Consequences of Singleton Overuse ....................................................................... 52

6.4 Singleton Mitigation ....................................................................................................... 53

6.4.1 Example ................................................................................................................... 54

6.5 Other Strategies for Singleton Overuse Mitigation ........................................................ 57

6.6 Conclusion ...................................................................................................................... 58

Chapter 7 Refactoring for State Pattern .................................................................................. 59

7.1 Modeling Simulation System ......................................................................................... 59

7.1.1 Statecharts Overview .............................................................................................. 60

7.2 State Diagram Implementation Example ........................................................................ 61

7.2.1 Nested Switch Statement and Variable status ......................................................... 62

7.2.2 State table ................................................................................................................ 63

Page 8: Thesis Budianto 20299965

viii

7.2.3 State Pattern ............................................................................................................ 65

7.3 AutoSim: State Transition Design and Problems ........................................................... 66

7.3.1 Problem of AutoSim‟s state transition .................................................................... 68

7.4 Refactoring to State Pattern ............................................................................................ 68

7.4.1 Example ................................................................................................................... 69

7.5 AutoSim‟s StateCharts ................................................................................................... 76

7.5.1 State Pattern on AutoSim‟s Server ......................................................................... 76

7.5.2 State Pattern on AutoSim Client ............................................................................. 78

7.6 Conclusion and Future Works ........................................................................................ 79

Chapter 8 Refactoring for Creational Pattern ........................................................................ 81

8.1 Overview ........................................................................................................................ 81

8.2 AutoSim Objects ............................................................................................................ 81

8.2.1 BuildData Class ....................................................................................................... 82

8.3 Refactoring to BuildDataCreator .................................................................................... 84

8.3.1 Extract Method ........................................................................................................ 85

8.3.2 Replace Hard-Coded with Enumeration ................................................................. 89

8.3.3 Extract Class ............................................................................................................ 92

8.3.4 Introduce BuildDataCreator .................................................................................... 94

8.4 Discussion ....................................................................................................................... 95

8.4.1 Possible extension to creational pattern .................................................................. 95

Chapter 9 Conclusion ................................................................................................................ 96

9.1 Summary of Contribution ............................................................................................... 96

9.2 Lesson Learned ............................................................................................................... 97

9.3 Future Works .................................................................................................................. 97

References .................................................................................................................................... 99

Page 9: Thesis Budianto 20299965

ix

List of Tables

Table 6-1.Refactoring Steps for Singleton Pattern Overuse Mitigation ....................................... 53

Table 7-1 Refactoring Steps for State Pattern ............................................................................... 69

Table 8-1 Refactoring Steps for Builder Pattern ........................................................................... 85

Page 10: Thesis Budianto 20299965

x

List of Figures

Figure 1-1 BMW Simulator [1] ....................................................................................................... 2

Figure 1-2 Daimler-Benz Simulator[2] ........................................................................................... 3

Figure 1-3 DS 6000 Training Simulator [3] .................................................................................... 3

Figure 1-4 The Iowa Driving Simulator [7] .................................................................................... 4

Figure 1-5 Vitrtex (2001) [1] .......................................................................................................... 4

Figure 1-6 Mars Path Finder [11] .................................................................................................... 5

Figure 1-7 Mörri, Autonomous Robot in Military-ELROB 2006 and 2008 [15] ........................... 6

Figure 2-1 A Motivation Examples .............................................................................................. 11

Figure 2-2. List of Opdyke's Refactoring [30] .............................................................................. 14

Figure 2-3. TORCS Screenshot [43] ............................................................................................. 17

Figure 2-4. RARS Screenshot [45] ............................................................................................... 18

Figure 3-1 Graphical User Interface of AutoSim Server with Loading Dialog ............................ 19

Figure 3-2. Graphical User Interface of AutoSim Client .............................................................. 20

Figure 3-3. AutoSim Client's Connection Progress ...................................................................... 21

Figure 3-4. Connection Failed Dialog ........................................................................................... 21

Figure 3-5The Client Server Architecture of AutoSim [10] ......................................................... 22

Figure 3-6 The AutoSim Client Basic Block Diagram ................................................................. 23

Figure 3-7 The AutoSim Server Basic Block Diagram................................................................. 24

Figure 3-8. Dialog for Documents generator using KingsTools[59] ............................................ 25

Figure 3-9. Example of AutoSim Server Documentation ............................................................. 25

Figure 3-10. Piece of Code from StartParameter Testcase ........................................................... 26

Figure 3-11. Example of Testing Result ....................................................................................... 26

Figure 4-1. An Example of Strict Ordering Statement ................................................................. 30

Figure 4-2. An Example of Arbitrary Ordering Statement ........................................................... 30

Figure 4-3. Looping Statement of Parameter Extraction .............................................................. 31

Figure 4-4. Long Statement examples .......................................................................................... 31

Figure 4-5. Semantic Meaning in Program ................................................................................... 32

Figure 4-6. Two Functions that naturally can go together ............................................................ 33

Page 11: Thesis Budianto 20299965

xi

Figure 4-7. if statement restructuring to Normal Case Ordering .................................................. 34

Figure 4-8. Simplifying if statement using simple comparison .................................................... 34

Figure 4-9. Simplifying if statement using boolean function ....................................................... 34

Figure 4-10. An Example Replace Temp with Query Refactoring ............................................... 35

Figure 4-11. An Example of Extract Method Refactoring ............................................................ 35

Figure 4-12. An Example Rename Method Refactoring .............................................................. 36

Figure 4-13. Simplifying Long Methods using Extract Method Refactoring ............................... 36

Figure 5-1. Original UML Diagram of Threads in AutoSim ........................................................ 39

Figure 5-2. Original UML Diagram of AutoSim Client Threads ................................................. 39

Figure 5-3. Busy Waiting Loops in Main.cpp ............................................................................... 40

Figure 5-4. Sleep Methods to delay between Thread Calling ....................................................... 41

Figure 5-5. Sequence Diagram of GUIThread implementation in AutoSim Client...................... 42

Figure 5-6. MoveMethod Refactoring on the show methods ....................................................... 43

Figure 5-7. MoveMethod on main.cpp ......................................................................................... 43

Figure 5-8. AutoSim Server's Class Diagram ............................................................................... 44

Figure 5-9. AutoSim Server's Simulation Package ....................................................................... 44

Figure 5-10. Exception Handler's Message Sending from RakNetClient to QApplication .......... 46

Figure 5-11. Exception Handler of AutoSim Client ..................................................................... 46

Figure 6-1. Singleton Pattern ........................................................................................................ 48

Figure 6-2. ClientController class. .................................................................................... 49

Figure 6-3. The Fault location in the MessageList class ............................................................... 51

Figure 6-4. The Actual Fault Location .......................................................................................... 51

Figure 7-1 Simple Finite State Machine (FSM) Diagram. ............................................................ 61

Figure 7-2 FSM Implementation using Nested State Switch. ....................................................... 62

Figure 7-3 State Table of statechart on Figure 7-1 ....................................................................... 63

Figure 7-4 State Table Implementation ......................................................................................... 64

Figure 7-5. UML Diagram of State pattern ................................................................................... 65

Figure 7-6 A Piece of code that represents AutoSim Implementation .......................................... 67

Figure 7-7 Client Class .................................................................................................................. 69

Figure 7-8 A Piece of Original AutoSim Code ............................................................................. 70

Figure 7-9 Move Field Refactoring ............................................................................................... 71

Page 12: Thesis Budianto 20299965

xii

Figure 7-10 UML Diagram of SubClasses after Extract Sub Class Refactoring .......................... 72

Figure 7-11 Extract Sub Class Refactoring ................................................................................... 72

Figure 7-12 Class diagram after Replace Data Value with Object Refactoring ........................... 73

Figure 7-13 Replace Data Value with Object Refactoring ........................................................... 73

Figure 7-14 Class Diagram after Add Method Refactoring .......................................................... 74

Figure 7-15 Add Method Refactoring ........................................................................................... 74

Figure 7-16 Class Diagram after Move Method Refactoring ....................................................... 75

Figure 7-17 Move Method Refactoring ........................................................................................ 75

Figure 7-18 AutoSim State Transition Diagram ........................................................................... 76

Figure 7-19 State Pattern of AutoSim's Server Application ......................................................... 77

Figure 7-20 FSM of Simulation States .......................................................................................... 77

Figure 7-21 State Pattern of Simulation's State............................................................................. 78

Figure 7-22 AutoSim Client's State Transition Diagram ............................................................. 78

Figure 7-23 State Pattern of AutoSim's Client State Diagram ...................................................... 79

Figure 8-1. BuildData Class Diagram ........................................................................................... 82

Figure 8-2 The MAP Collection of Graphic tag ........................................................................... 84

Figure 8-3 The First Extract Method Refactoring on fromXML function .................................... 86

Figure 8-4 The Second Extract Method Refactoring on fromXML function ............................... 87

Figure 8-5 Inline Method in fromXML function .......................................................................... 87

Figure 8-6 The Extract Method Refactoring on XMLExtractArrayData function ....................... 88

Figure 8-7 BuildData Class Diagram after ExtractMethod Refactoring ....................................... 89

Figure 8-8 Class Diagram after Extract Class Refactoring .......................................................... 93

Figure 8-9 BuildData class before and after Extract Class Refactoring .................................. 93

Figure 8-10 BuildDataCreator class .................................................................................... 94

Page 13: Thesis Budianto 20299965

1

Chapter 1

Introduction

1.1 Simulation Overview

Simulation is an imitation of the real life: its process, its states, and its transition. Currently

simulation is used in various aspects ranging from science to engineering. By simulating the real

world, we try to learn about its behavior by adjusting its parameters that has influence to the

simulation objects. The ultimate goal is to represent the model that can give us a prediction about

the real world application.

In automotive industries, simulation is applied in various range of application for different

purposes. For instance, a driving simulator can be applied to driving schools, psychological

research centers, amusement games, car manufacture, etc [1].

Furthermore the simulator in automotive bring several benefits as follows:

Economic benefit. Simulation is cost effective compare with the real world experiment

Support the system prediction. In the real life, we cannot stretch the timing to see the

future time. However modeling the environment using simulation allows us to predict the

future as the timing can be speed up.

Provides a Framework. Simulation can be used to resemble different types of

environments that provide an abstraction about the various possibilities. Thus simulation

can provides a framework.

Provides a model for Analysis. The real world problem is difficult to understand since

there are many factors that work together. Analyzing a particular problem need a model

that can give information about a particular issues without any other factors that influence

Page 14: Thesis Budianto 20299965

2

our perception about the system. The users are allowed to adjust parameters to see the

simulation behavior and the result can be used to model the real world environment.

Support safely. Simulation will provides a virtual world that support safety issues in the

real world. For instance, simulation can be employed to test the safely of product.

However automotive simulation also provides undesirable disadvantages particularly its fidelity

to the real world. This is an essential task of simulation to ensure its accuracy to imitate the real

world that is being studied.

1.2 Driving Simulator History

The proliferation of driving simulator is started by flight simulator in the beginning of 1900.

According to Slob, flight simulator firstly was introduced by flight training school “Antoinette”

and later, in 1962, the parallel six degree of freedom system comprises two platforms and six

actuators in developed by D. Stewert [1].

Figure 1-1 BMW Simulator [1]

Page 15: Thesis Budianto 20299965

3

Figure 1-2 Daimler-Benz Simulator[2]

In Europe the first driving simulator is developed by Volkswagen in the beginning of 70s and

later, iDOF simulator was produced in 1984. Additionally, the Swedish Road and Traffic

Research Institute started building VTI in 1984. What is more the driving simulators was built

some car companies and aerospace institution such as Daimler-Benz in 1985 [2], BMW, and

Katech and German Aerospace Institute (DLR) [1].

Figure 1-3 DS 6000 Training Simulator [3]

In Japan, research on driving simulator begun in 1960 by National Research Institute of Police

Science, Prince Motor Company and National Research Institute of Mechanical Engineering

Laboratory using analog computer and electronic circuits [4]. It was continued by Toyota using

Page 16: Thesis Budianto 20299965

4

Drum-type driving simulator. The more advance driving simulator later was introduced by

several car companies. These simulator includes Mazda driving simulator[5], Honda riding

simulator, and Mitsubishi Motor Flat-Belt driving simulator [4]. Currently, Mitsubishi Motor

has produced several driving simulators for driving training, rider training, helicopter, and train

[6].

Figure 1-4 The Iowa Driving Simulator [7]

In the United State, the Center for Computer-Aided Design (CCAD) at the University of Iowa

started developing the Iowa Driving Simulator (IDS) which is primarily funding by the state of

Iowa and the advanced Research Projects Agency (ARPA) [7]. Additionally, Ford introduced the

Vitrtex in 1994 and was renewed in 2001 [1].

Figure 1-5 Vitrtex (2001) [1]

Page 17: Thesis Budianto 20299965

5

1.3 Autonomous Driving

The outer space exploration brings human being to explore the universe using robots that can

works in the hostile environment. The exploration mission has been begun since 1960 in United

of Soviet Socialist Republic (USSR) by launching Korabl 4. After that, there are many efforts to

performs the similar exploration programs during the cold war era [8]. There are several

successful missions. For instance, in 1996, NASA launched the Mars Path finder named

Sojourner, the first semi-autonomous vehicle that rolls on Mars planet [9, 10]. It is controlled by

earth-based center. However, the successful of the mission has low rate. Between 1980-2000,

among ten mission programs, both countries have launched only two robot successfully[8].

Figure 1-6 Mars Path Finder [11]

In addition to that, the research on autonomous vehicle is also studied by Ernst Dickmanns et all

at the Universitat der Bunderswehr Munich in 1980 [9, 12]. This research employs the Kalman

filter and parallel computer as a controller system. The research is continued by developing the

Mercedes benz with a vision guided in 1980 and the S-class Mercedes benz in 1995 [13].

Moreover, in 2005, Defence Advanced Research Project Agency (DARPA) “Grand Challenges”

held by United State Department of Defence‟s sponsor. In Europe the similar completion, The

Europe Land Robot Trial (ELROB) is introduced since 1996 and has been held every year until

now. The purpose is to introduce the recent state of the art of robotics [14].

Page 18: Thesis Budianto 20299965

6

Figure 1-7 Mörri, Autonomous Robot in Military-ELROB 2006 and 2008 [15]

1.4 AutoSim Overview

AutoSim is a simulator developed by the Centre for Intelligent Information Processing Systems

(CIIPS), the School of Electrical, Electronic and Computer Engineering, the University of

Western Australia (UWA). The AutoSim simulator is an open source simulator for robot,

particularly, automobiles simulation. The objective of AutoSim is to provide the user an interface

to program the robot that is able to interact with the simulator‟s world and to visualize the world

so that users can analyses and tests the simulation[9]. To achieve those objectives, the AutoSim

introduces several features such as 3D real-world generated environment and autonomous robots

that have sensors to detect the dynamic environment.

The environment of AutoSim consists of several visualization objects (e.g. terrains and objects)

that represent the real world entities. The road terrains, for instance, are visualized based on the a

open map data retrieved from OpenStreetMap, a free wiki world map [10] [16]. The advantages

is that users can modify the map interactively using Java OpenStreetMap (JOSM) Editor [17].

Other objects are 3D visualization entities that are placed in the environment such as houses and

trees. Special object (e.g. traffic light) also available to perform autonomously desired task in a

changing environment.

The AutoSim software is build in based on the client-server model architecture. The server

provides the simulation data and the dynamic environment to the client through a network and

the client visualizes the environment and provides interface for user‟s interaction. Chapter 3 will

present the AutoSim software in detail including its library and development tools.

Page 19: Thesis Budianto 20299965

7

1.5 The Problem

AutoSim is an active research project in automotive simulation in the University of Western

Australia [9, 10, 18, 19]. The project is developed using C++ object oriented language. This

project developing activities include adding new features, debugging, fixing software defects,

and maintaining system. Hence the evolving software‟s quality is declining and increase the

software complexity. With an increasing complexity and decreasing reusability, the development

progress has been slower than what is expected. On the other hand High code understandability

and good software design makes the subsequent development easier.

Observation on the AutoSim projects shows that code understandability, a key aspect in software

development process to enhance a human-readable code, has been deteriorated. In respect to

code understandability, Martin Fowler said that “Any fool can write code that a computer can understand.

Good programmers write code that humans can understand” [20]. Thus high quality code provides a good

medium of communication for a collaborative software development team.

Additionally, AutoSim also suffer of bad design as a result of continuing writing code without

up-front design which is a notion of design debt, a metaphor of software complexity that refers

to a financial debt [21]. This design debt was accumulated because software developers wrote

code without considering design such that the cost of adding new feature, later on, become

bigger than writing code from scratch.

1.6 Proposed Solutions

This dissertation is about restructuring object oriented programming in AutoSim Project. The

purposes of the refactoring, an object oriented program restructuring, are to solve the problems

of AutoSim: legacy code and design debt. The final goals are to achieve good reusability to

support software maintenance and development in the future. Refactoring can help us to increase

the software qualities in two aspects as follows:

1. Code Quality. Refactoring helps us to restructure a code in order to increase program

comprehension. It not only cleans the legacy code but also maintain the code always

clean. Refactoring will simplify the code and remove the code duplication. As the result,

the code‟s intension become clear and easy to understand.

Page 20: Thesis Budianto 20299965

8

2. Software Design Quality. A good design in advances can avoid a high costly

development and rework. People believe that at the beginning of software development,

they have to plan for a good software design. In fact, a good planning on design does not

guarantee a perfect design without any defect. Refactoring is a complement to design by

restructuring the code to achieve a better design. This involves restructuring a software

design by modifying set of class structure that correspondent to restructuring software

design. Moreover, in extreme programming development, refactoring is employed to a

achieved a well design software from a instant code that is written without any up front

design.

In object oriented programming, refactoring is applied on the code and has impacts to several

levels of software entities: statement, class, and software design. Based on those implications,

the refactoring can be classified into the following types:

1. Statement Level Restructuring involves restructuring on the statement of code of an object

such as methods renaming,

2. Class or Module Restructuring involves restructuring on class that will have an impact on the

structure within an object.

3. Software Design Restructuring involves high level restructuring, a composite of restructuring

techniques, which is applied to achieve a good software pattern.

Furthermore, refactoring also gives many benefits to software development process. Refactoring

activities can be done concurrently with coding activities. Subsequently, these activities will

improve the software process by introducing good practice to the software activities. Moreover,

refactoring also increases software testability by removing high coupling code and providing a

good unit testing to the software product. Since the code becomes easy to understand, it provides

so called a self documenting code and increases the program comprehension.

1.7 Challenges

Provided a good solution for legacy code, refactoring also have various challenges in its

implementation as follows:

1. Preserving behaviors is an essential aspect that needs to be maintenance during the

refactoring. Practically, testing is employed to preserve coding features during

Page 21: Thesis Budianto 20299965

9

refactoring. However, in reality, the complex system with high coupling like AutoSim

has low testability which means no testing availability to help behaviors preservation.

2. Version Control System limitation. To record the code changing, AutoSim employs

subversion, an open source version control system, managing the code evolution.

However the current subversion system only provides a line by line code comparison that

does not records the semantic meaning of refactoring. Hence, sometimes, the refactoring

activities are recorded manually with limited help of subversion system.

3. Limited Refactoring tools for C++ also provides other challenges in the refactoring

process. Many supports in refactoring are come from high object-oriented programming

language such as java and smalltalk but not C++. In AutoSim, the refactoring is triggered

by code smelling activity, an intuitive ways to detect legacy code.

1.8 Major Contributions

This dissertation makes the following contributions:

1. It presents some important problems of AutoSim project especially in the process of

development as a result of lack of software design to anticipate the evolving software

2. It provides some practical implementation of refactoring on AutoSim to repair software

design and code understandability

3. It provides an evaluation the design improvement on the AutoSim.

4. It introduces several high levels refactoring for design pattern.

5. It introduces new graphical user interface for AutoSim Client such as dashboard, loading

progress, gear number, network connection progress, and exception handler message.

6. It introduces some new automation tools for development such as help generator and

testing unit

Next chapter present the motivation of refactoring and describe design pattern and some works

on refactoring. Chapter three provide some low level refactoring implementation common used

in AutoSim restructuring. Chapter four describes some issues on singleton pattern overuse in

AutoSim application and provides a mitigation strategies using refactoring. Chapter five ans six

present the refactoring to achieve state pattern and creational respectively. Chapter seven

introduce the program restructuring in multithreading application. The final chapter provides the

conclusion and future works of AutoSim especially in program refactoring.

Page 22: Thesis Budianto 20299965

10

Chapter 2

Motivation and Related Works

In the beginning of computer era, the experimental development of OS/360, Software Change

was primarily known as program growth dynamic [22, 23]. This investigation pins down the

starting point for understanding that the software flexibility can be used as a vehicle for

addressing the dynamic real life problem. A computer program can control the underlying

hardware which is provided with basic functionality to solve the contextual changing problem

encountered in our life. However, software flexibility also becomes potential future problems.

Refactoring is a bottom up approach to improve the quality of existing program by transforming

the code for better understandability and design without changing its external behavior. When a

program quality has deteriorated into legacy code, refactoring has primary task to maintain the

program quality by structuring the code. This chapter will outline the motivation of refactoring

activities on AutoSim application and some researches on refactoring that gives ideal insight for

the refactoring implementation. Moreover the related works on automotive simulator is also

presented.

2.1 Motivation Examples

The motivation of refactoring will be discussed using the real world code retrieved from several

code versions stored on the subversion‟s repositories. Consider the following pieces of code that

are used to extract the parameters input of the AutoSim application (see Figure 2-1).

Those three parts of code of main.cpp is taken from different version on the repositories: version

873 (8 February 2008), 105 (25 August 2008), and 1101 (6 October 2008). The version 873

shows the initial code that supports three types of arguments namely –Worldfile, -StepPerSec,

and –AutoStart.

Page 23: Thesis Budianto 20299965

11

873 8 February 2008 1050 – 25 August 2008 int main(int argc, char *argv[]

)

{

...

int i = 0;

while(i < argc)

{

if(!strcmp(argv[i], "-WorldFile"))

{

i++;

guiParams->worldFile = argv[i];

}

else if(!strcmp(argv[i], "-StepsPerSec"))

{

i++;

guiParams->stepsPerSec =

RSSTRING::intFromString(STRING(argv[i]));

}

else if(!strcmp(argv[i], "-AutoStart"))

{

guiParams->autoStart = true;

}

i++;

}

...

}

int main(int argc, char *argv[])

{

...

int i = 0;

while(i < argc)

{

if(!strcmp(argv[i], "-WorldFile"))

{

i++;

params->worldFile = argv[i];

CTRL->m_WorldFile = argv[i];

}

else if(!strcmp(argv[i], "-StepsPerSec"))

{

i++;

params->stepsPerSec =

RSSTRING::intFromString(STRING(argv[i]));

}

else if(!strcmp(argv[i], "-windForce"))

{

i++;

params->windForce =

RSSTRING::intFromString(STRING(argv[i]));

}

else if(!strcmp(argv[i], "-AutoStart"))

{

params->autoStart = true;

}

i++;

}

...

}

1101 – 6 October 2008

void printUsage()

{

std::cout<<"AutoSimServer ..."<<endl

<<endl

<<"Example"<<endl

<<endl

<<"AutoSimServer-v0.03.exe

..."<<endl

<<endl

<<"Description"<<endl

<<endl

<<"-AutoStart\tThis ..."<<endl

<<"-Help\t\tDisplay this ..."<<endl

<<"-StepsPerSec\tPerformance ..."

<<"-WindForce\tSpecifies ..."

<<"-WorldFile\tIndicates …."<<endl

<<endl;

}

int main(int argc, char *argv[])

{

...

int i = 0;

while(i < argc)

{

if(!strcmp(argv[i],"-Help") ||

!strcmp(argv[i],"-h"))

{

printUsage();

return 0;

}

if(!strcmp(argv[i], "-WorldFile"))

{

i++;

params->worldFile = argv[i];

CTRL->m_WorldFile = argv[i];

}

else if(!strcmp(argv[i], "-StepsPerSec"))

{

i++;

params->stepsPerSec =

RSSTRING::intFromString(STRING(argv[i]));

}

else if(!strcmp(argv[i], "-windForce"))

{

i++;

params->windForce =

RSSTRING::intFromString(STRING(argv[i]));

}

else if(!strcmp(argv[i], "-AutoStart"))

{

params->autoStart = true;

}

else{ //Default case

std::cout<<"Invalid Argument

Exiting.."<<endl;

printUsage();

return 0;

}

i++; }

...

}

Figure 2-1 A Motivation Examples

δ1 σ1

δ2

σ2

δ3

σ3

σ4 σ5

Page 24: Thesis Budianto 20299965

12

Later the program was evolving by adding new code to program (σ1,2) and change existing code

(δ1−3) in version 1050. Both addition σ1and σ2 on the code is to send the argument value to the

controller class (CTRL) and to accommodate a new argument support for wind force ( -

windForce). Last, the software developer made the three changes (δ1−3) as a result of object

renaming from guiparams to params.

The program continues to evolve and make another argument addition as shown in version 1101.

It introduces two new arguments to support the –help (σ4) and invalid parameter (σ5). When the

invalid parameter is detected, the application will display the usage information using a new

printUsage function (σ3).

In the software development, the software will evolve to meet to the new requirements. For

instance, after two consecutive revisions, the main.cpp code become more complex and it

decrease the code understandability. Thus the main.cpp „s has deviated from its original goals as

a core process.

2.2 Design Pattern

Software design is an essential tool in the software construction process that provides a

implementation guideline and blueprint [24]. During the software design, some elements that

construct the whole system are considered to fulfill the requirement of the software specification.

Software design determines how we choose a programming language, programming style, and

programming implementation. For example, when we develop a web application, it is

ineffective and burdensome to use assembler. Moreover, even we have decided a particular

programming language; our implementation must not run away from the core design.

Software design is essential at least as a model not only for the software implementation (e.g.

software program, coding, etc) but also for software specification. It act as a bridge between the

software specification resulted from the requirement analysis and the implementation of the

software. The software design will depicts how the software implementation will fulfill the

software specification. For instance, we can examine the software design to determine wheter the

software design has deviate from the original blueprint. Moreover, a good software design will

make the implementation easier and lead to produce high quality software.

Page 25: Thesis Budianto 20299965

13

The origin of pattern is came from the architectural discipline which describe repeatable problem

and the core solution to that problem that enable us to reuse the solution again and again [25]. In

Software Engineering, design pattern catalog developed by gang of four help us to provides

pattern catalogs of recurring design in object-oriented system [26]. A more friendly references on

design pattern is available from Eric Freeman and Elisabeth Freeman which describe pattern

using visual example and program code [27].

Software design also important part in documenting the software product. It serves a visual

figure that describes the abstraction of system process that is easy to be understood. In the

software documentation, design pattern will serve as an object-oriented architectural style that

provides strategic reuse [28].

2.3 Works on Refactoring

2.3.1 Early Works on Refactoring

According to Donald B. Robert, Software refactoring term probably is originated by Peter

Deautch in his paper on Software Reusability [29]. However the fundamental work on

refactoring initially is done by William F. Opdyke during his doctoral studies [30]. His work

focuses on providing a refactoring framework for object oriented program restructuring to

improve with software quality. This works also discuss other aspects on the preserving the

external program behavior of refactoring activities.

The result of his doctoral work produces three high-level refactorings: creating an abstract

superclass, subclassing, and simplifying and five set low level refactorings listed on the figure 2-

2. In addition to those refactorings, the seven program properties which are essential in behavior

preservation is discussed.

Page 26: Thesis Budianto 20299965

14

Creating a Program Entity creating an empty class creating a member variable creating a member function.

Deleting a Program Entity deleting an unreferenced class deleting an unreferenced variable deleting a set of member functions.

Changing a Program Entity changing a class name changing a variable name changing a member function name changing the type of a set of variables and functions changing access control mode adding a function argument deleting a function argument reordering function arguments adding a function body deleting a function body convert an instance variable to a variable that points to an instance convert variable references to function calls replacing statement list with function call inlining (ie inline expanding) a function call changing the superclass of a class

Moving a Member Variable moving a member variable to a superclass moving a member variable to a subclass

Less primitive (composite) refactorings abstract access to a member variable convert a code segment to a function moving a class

Figure 2-2. List of Opdyke's Refactoring [30]

The seven program properties include:

1. Uniques Superclass. There is only one unique super class.

2. Distinct Class Name. There must be a unique class name. It is assumed that a class is

unique in the entire program. In other word, there are no nested classes or

namespaces.

3. Distinct Member Names: A class must always have a unique member (both variables

and functions) names. An exception is made on the overridden member function in

subclass.

4. Inherited Member Variables Not Redefined. An member variable which has been

defined in super class must not be declared again the subclasses.

Page 27: Thesis Budianto 20299965

15

5. Compatible signatures in Member Function Redefinition. A inherited function in a

subclass must be compatible with the original function in the superclass. This

includes all attributes of the class.

6. Type-Safe Assignments. In the assignment operation, a left-hand variable must be

assigned by a type or a sub type of the variable type.

7. Semantically Equivalent references and Operations. The Program produced by

refactoring must preserve semantically equivalent references and operations.

2.3.2 Formalizing Refactoring

The work on formalizing refactoring done by Donald B. Roberts at the University of Illinois

introduces formal definition for refactoring [29]. In addition to that, the practical analysis of

refactoring is discussed and explored which later produced a refactoring tools namely refactoring

browser, the first refactoring tools in smalltalk program. Other work to formalize refactorings is

also done by Tom Mets et all using Graph Transformation [31]. The effect of software

transformation and its behavior preserve is proved and visualized using graph.

2.3.3 Refactoring Research

The benefit of refactoring in guiding the evolving software for good design has been investigated

by Lance A. Tokuda [32]. The extension of automating design evolution is discussed as an

addition to the preliminarily research on refactoring by Opdyke [30]. His works extends the

previous works by introduction the refactoring roles on design evolution.

Continuing research in the University of Illinois, Alenjandra Garrido works on refactoring on C

program which consist of mix of two languages namely pure C language and preprocessor

directive [33]. Other research on how refactoring can accommodate in application programming

interface evolution is investigated by Daniel Dig [34].

In the University of Antwerpen, Belgium, refactoring research is carried out by Bart D. Buis. He

studies the impacts of the quality improvement after refactoring. Several software quality aspects

that have impacts after refactoring is discussed [35]:

1. Program comprehension and Understandability

2. Software complexity

3. Coupling and Cohesion

Page 28: Thesis Budianto 20299965

16

2.3.4 Refactoring Tools

The first refactoring tool is to support in smalltalk programming language written by Don

Roberts et all [36]. This application provides a refactoring browser that is used to restructure

smalltalk program automatically.

To support refactoring in java program, Danny Dig writes the JavaRefactor plugin, the first

refactoring tool for java, in JEdit Integrated Development Environment [37]. It provides a

catalog for automated refactoring such as class, field, method, and package renaming and

PushDown and PullUp of methods and fields in an inheritance hierarchy.

Furthermore, XRefactory, an open source refactoring tools, is introduced for Emacs and XEMacs

users [38]. This tool provides refactoring for both C++ and java programming language. More

sophisticated refactoring tools, Refactor Pro is available for visual studio c++ produced by

DevExpress [39].

2.3.5 Refactoring in Practices

The introductory book on software construction is written by Steve McConnell. It discusses the

software construction particularly the code qualities such as high quality code, self documenting

code, variables, and organizing code statement [40]. Michael C. Feathers also provides a good

practical implementation how to repair legacy code effectively. He provides a short suggestion

and solution for typical problems of legacy code [41].

For refactoring implementation, a refactoring catalog along with examples is introduced to

practitioner by Martin Fowler [20]. Some principles in applying refactoring are discussed in

pragmatic ways. Code smelling, an intuitive ways to detect code quality, is introduced as ways in

triggering refactoring activities. In order to maintain the behavior preservation, the solid tests are

designed as a precondition of refactoring. This method is valid provided by the assumption that

tests applied to a program before and after the refactoring produces the same result. Moreover

the assumption that the program provides high testability must be satisfied. In addition to that,

the book from Joshua Kerievsky offers the high level refactoring catalog. His works emphasis on

a practical solution to provides refactoring activities to achieve the good software pattern [42].

Page 29: Thesis Budianto 20299965

17

2.4 Automotive Simulation

The section presents related work on automotive simulator.

The Open Racing Car Simulator (TORCS) is a automotive simulator that consists of two types of

robots namely, computer robot and user defined robot which can be programmed in C++ [43].

Figure 2-3 shows the snapshot of TORCS.

Figure 2-3. TORCS Screenshot [43]

TORCS is an open course car simulation that supports multiplatform operating system such as

Linux, MacOS, FreeBSD, and Windows. TORCS simulation was developed by Eric Espié and

Christophe Guionneau under General Public License. Additionally, it support the following

features [44]:

a. More than 50 cars

b. More than 20 tracks

c. 50 opponents in a race

d. Joystick, Steering wheel support, mouse and keyboard support

e. Damage model, collision, smoke, skidmark, glowing brake disk, wheel and tire

properties, aerodynamics, etc

Page 30: Thesis Budianto 20299965

18

Another simpler automotive simulator is provided by Robot Auto Racing Simulation (RARS).

RARS is developer for a programmer competition and for practitioners particularly in artificial

intelligent[45]. Figure 2-4 shows the screenshot of RARS.

Figure 2-4. RARS Screenshot [45]

RARS is developed under open source license and available for public. It supports both UNIX

and Windows. The simulation comprise of physical simulation of racing car, a control program

that is able to manage the car, and a graphical visualization [45].

Moreover, VAMOS is another automotive simulator that has just been developed to provides

physical simulation using C/C++ [46]. Additionally, there are some other automotive simulators

such as GRacer, a 3D Motor Sport Simulator developed by Takashi Matsuda[47], CarWorld, a

small driving simulator developed under GNU license[48], T1 Car Racing Simulator[49], and

VDrift[50].

Page 31: Thesis Budianto 20299965

19

Chapter 3

AutoSim Functionalities

3.1 AutoSim Graphical User Interfaces

This section outlines some new features that has been added to the current AutoSim

development. This section will be divided into three sections namely, Loading Features,

AutoSim Dashboard, and Network Message Features. We will also outlines briefly the additional

document generator and unit testing that has been integrated into AutoSim project.

3.1.1 Loading Process on AutoSim Server and Client

The loading process has been enhanced in two aspects, the graphical user interface and

restructuring the state transition of both applications, AutoSim Server and AutoSim Client (see

chapter 7). The graphical user interface of AutoSim Server for displaying the state progress is

shown in the figure 3-4. This loading dialog is based on the builder pattern that is implemented

in the new AutoSim Server version (see chapter 8).

Figure 3-1 Graphical User Interface of AutoSim Server with Loading Dialog

Page 32: Thesis Budianto 20299965

20

The progress dialog is determined by steps of loading in ClientWorldBuilder class. At the

beginning of the Load process the dialog shows five percents. Next the AutoSim server loads

the client‟s objects by execute methods: buildWorld, buildGraphic, buildPhysics,

buildObjects, buildTerrain that worth 10%, 30%, 50%, 70%, and 80% respectively. Thus

from the figure above we know that the AutoSim server has finished load all objects. After that

the AutoSim prepares the graphic manager and closes the dialog window.

3.1.2 AutoSim Client Interface

The AutoSim Client provides a graphical user interface that visualizes the simulation objects.

The current AutoSim Client displays the simulation in separate windows and able to display in

full-screen. Figure 3-5 shows the Graphical User Interface of AutoSim client. It also displays the

dashboard visualization with velocity meter. Additionally, it also includes the gear number that

determines the current gear number.

Figure 3-2. Graphical User Interface of AutoSim Client

3.1.3 AutoSim Client Networking Interface

We also introduce new capabilities on handling the networking error on the AutoSim Client. At

the beginning of AutoSim Client‟s execution, it will load the simulation objects similar to the

server. However AutoSim Client needs to connect to the AutoSim Server for simulation objects

Page 33: Thesis Budianto 20299965

21

information exchanges. The connection is handled by RakNetClient class that is control by the

state pattern. The connection process is also displayed in the progress dialog shown in figure 3-6.

Figure 3-3. AutoSim Client's Connection Progress

If the connection is failed, then the message will be displayed as shown in figure 3-7. It give

users three options to reconnect again, to exit application, or to cancel connection. If the first

option (button yes) is pressed, the client application will try to find the server network services

once again. If the second option (button no) is pressed, the client application will close the

connection and close the AutoSim Client application. If the third option (button cancel) is

pressed, the connection is canceled but the AutoSim client is still open. The same dialog is also

displayed when the connection is disconnected or failed.

Figure 3-4. Connection Failed Dialog

Page 34: Thesis Budianto 20299965

22

3.2 AutoSim Structure Overview

AutoSim is an event-driven system which detects, consumes, and reacts to the coming of events

from user‟s input and timer event form the system. Time event is a special event that is generated

automatically by the system when certain time duration has been elapsed.

Figure 3-5The Client Server Architecture of AutoSim [10]

AutoSim consists of two main applications namely, AutoSim Server and AutoSim Client. The

block diagram of the AutoSim is depicted in the figure 1-1. RakNet library, an network engine

library that provides a layer over user datagram protocol (UDP), handle the data communication

between client and server application [51]. AutoSim server application is responsible to manage

the simulation activities by providing physical model data. Whereas, AutoSim client application

is responsible to manage the user‟s input and visualize the physical model in the real time

fashion. The 3D visualization is created by Irrlitch, an open source and cross platform 3D engine

written in C++ programming language [52]. Several clients can run and communicate with a

server concurrently. In addition to those features, the client application also provides a user

program interface for user‟s interaction.

3.2.1 AutoSim Client Design Overview

AutoSim client application is a real-time 3D application that consists of several threads: main

thread, network thread, and user program threads. The client comprise two graphical user

interfaces (GUI) which are created using Qt library, a cross platform application and user

interface (UI) framework [53]. These GUIs receive inputs and display the 3D terrain and objects

to users. The GUI Thread is responsible to manage the graphic module that is responsible to

display 3D terrain and objects. Whereas, the simulation objects are managed in the tree data

structure that is updated upon receiving packet from network thread. For data transmission both

Page 35: Thesis Budianto 20299965

23

client and server transform the data into bit stream and send them through RakNet engine [51].

Thus the data communication between server and client application needs data conversion.

ClientController

Graphics

Network

UserProgram

ControllerState

1 1

DataLoader

GUI RakNet Library

Irrlitch Library

Figure 3-6 The AutoSim Client Basic Block Diagram

Figure 1-2 shows the basic block diagram of the AutoSim Client. The ClientController is the

most important class that manages the whole modules. ClientController acts as a façade object to

other classes of AutoSimClient.

3.2.2 AutoSim Server Design Overview

Basically, the AutoSim Server block diagram is similar to the AutoSim client. Its functions,

along with physical engine, are to manage and update the simulation object‟s properties and send

the data through the network to AutoSim client. The simulation module has responsibilities to

get the physical data from the physic engine and pass it to the appropriate objects. The

interaction with physics engine is organized by a physic layer know as Physical Abstract Layer

(PAL) develop by Adrian Boeing[54].

Page 36: Thesis Budianto 20299965

24

Controller

Network

ControllerState

1 1

DataLoader

GUI

Simulation

RakNet Library

PAL Library

Figure 3-7 The AutoSim Server Basic Block Diagram

Figure 1-3 shows the basic AutoSim server design. The AutoSim has a controller to manages the

whole interrelated modules within the software. The Graphical User Interface (GUI) thread,

Network Thread, User Program Thread, and Simulation thread is controlled by the Server

Controller.

3.3 AutoSim Libraries

As mentioned in the previous section, AutoSim employs several libraries to support networking,

physic processing, data loading, and graphical user interface. These libraries includes:

Qt Framework is a graphical user interface framework that supports various platform

including Unix, Linux and Windows[53, 55].

TinyXML is a free XML parser c++ library that provides services to XML manipulation

[56].

Irrlitch Engine is an open source cross platform 3D engine. It provides application

programming interface (API) in c++ that is essential to developed a 3D simulation

application[52].

Physical Abstract Layer (PAL) is a additional layer that is used to provides an interface

for simulation physical process. It was developed by Adrian Boeing at CIIPS [54].

Page 37: Thesis Budianto 20299965

25

RakNet is a network engine for high performance communication. It provides a datagram

data transmission that is suitable for games application and other similar applications

[51].

3.4 Automation Tools

We introduce two automations tools to increase the productivity of software development: the

doxygen, an documents generation [57] and CPPUnit [58], a open source unit testing framework

in c and c++ programming language.

Figure 3-8. Dialog for Documents generator using KingsTools[59]

Doxygen is a documentation generator that transforms the comment to various document such as

HTML, rich text document (rtf), latex, extensible markup language (XML), and WinHelp. Figure

3-8 shows the dialog to generate automatically the source code documentation. Whereas figure

3-9 shows the example of AutoSim Server documentation in compiled HTML (CHM) format.

Figure 3-9. Example of AutoSim Server Documentation

Page 38: Thesis Budianto 20299965

26

CPPUnit provides a framework that can be used to generate a unit testing for testing automation.

The following code shows a piece of code for test case for StartParameter class. The

CPPUnit_ASSERT is an assert function provided by CPPUnit testing that determine the testing

process.

void StartParamsTest::setUp(void){ ...

t1 = new StartParameters(argc1, argv1);

t1->extractParams();

}

void StartParamsTest::extractTest (void){

...

CPPUNIT_ASSERT (t1->getAutoStart()) ;

CPPUNIT_ASSERT (t1->getAutoStart() != false);

}

Figure 3-10. Piece of Code from StartParameter Testcase

Using unit testing will help us to automate the testing procedures. When we change the code, to

ensure that the new code conform with the specification, we can run the test cases immediately.

The result of the testing is shown in console (see figure 3-11)

Figure 3-11. Example of Testing Result

Page 39: Thesis Budianto 20299965

27

Chapter 4

Refactoring on Code Readability

A computer program, a set of instructions from a man to a computer, must be able to tell the

computer what to do. But it must also communicate its intents to other stakeholders especially

other software developers to ensure the sustainability of software evolution [60]. This aspect of

program quality is known as program comprehension or program understandability. We defined

the smallest unit of program comprehension as code readability.

This chapter begins with programming language overview: its features and its challenges

especially related to refactoring for program understandability. Section 4.2 presents the most

aspects of coding. Section 4.3 presents some code readability issues in AutoSim. Finally, we

discuss some low level refactoring to improve code readability and finished with discussion

some other refactoring techniques for code readability.

4.1 C++

C++ programming language is a high level programming language that supports the modular

programming paradigm. It is a subset of C but better then C in term of data abstraction, object

oriented programming, and generic programming. The name of C++ was coined by Rick

Mascitti that means an extension of C that have no attempt to remove previous features [61].

Some undesirable C++ features that hinder the refactoring activities are:

1. C compatibility. The compatibility of C++ provides support to previous super set such

that an old C programmer can gain the benefit using C++ especially for migration to C

program to C++ [62]. However the features compatibilities also make the program is

difficult to understand (e.g. preprocessor directive).

2. Pointer and Cast Operation. Pointer and Cast operation is an important feature of C++

to support polymorphism. For instance, using a pointer variable we are able to hold a

Page 40: Thesis Budianto 20299965

28

pointer to inheritance objects and use cast operation to perform type conversion between

super classes to sub classes. But they make the program difficult to understand. For

instance, the casting operation on the statement makes the code statement unnecessary

longer.

4.2 The Aspect of Coding

The software construction involves some activities including coding, debugging, design,

construction planning, testing, and other activities [40]. Among these activities, coding is the

central activities of software construction. Essentially every aspects of coding including

debugging, testing, algorithms is worth discussion. But, the following sub section discussed

some aspects of coding in relationship with design, standard, and program comprehension.

4.2.1 Coding and Design

Two perspectives of coding and design can be seen as a top down approach and bottom up

approach as follows:

1. Coding as Detail Design Realization

From the top down view, coding is a design realization. Firstly, software design that is a

model and an abstraction to the software specification is built. This model is constructed

during coding activities. A software design is still a conceptual model until the

implementation detail is constructed [40].

2. Coding as Emergent Design

Another ways to build a software system is using experimental prototyping, which are not

the actual construction activities. It produces neither of model and abstraction of product.

In fact, the prototyping results a resemble system that works on simulated environment.

Steve states that experimental prototyping by writing a small chunk of code to realize a

model is general used to addressing the software design problem. The coding should be

minimum that only try to improve our limited design [40]. A more extreme approach is

namely emergent design, evolve a design using refactoring [20, 63]. Originally, the term

emergent design, a new approach in system engineering, is coined by Cavallo [64].

Emergent design considers the concept that from the existing code we can improve the

design and in some extension, it can improve the software architecture.

Page 41: Thesis Budianto 20299965

29

4.2.2 Program Comprehension

The aspects of program contain a broad spectrum quality ranging from its syntax to its

documentation. This chapter will present some aspects of code quality that is related to

understandability of program in statement level. Here are several aspects of program that makes

a program is easy to understand:

1. Simplicity. A simple program is a short program. It is clear from unimportant part that

influences the program understandability. For instance, many unnecessary temporary

variables reduce its simplicity.

2. Completeness. When a program is simple, it does not means that it replaces or removes

its actual specification. On the other hand the completeness of a program must be

maintained.

3. Clarity. Clarity means is that a programmer can understand the code at the first time

reading.

4.3 Coding Quality in AutoSim

Our experiences working with AutoSim found that the program complexity is caused by

statement level program complexity. It is the most fundamental practical refactoring that leads to

other high level refactoring. The following lists show some major aspects of code that create

complexity:

1. Code Clone

2. Unstructured Statement Organization (unclear Statement)

3. Long Statement

4. Semantic Meaning of Code

4.3.1 Code Clone

Code clone is a fragment of code that has high degree of similarity with other fragment of the

source code. People believe that clone code is a major problem that makes the software

maintenance more difficult [65]. Additionally, code clone increases code length, code

complexity, and code readability. Refactoring code clone allows us to comprehend the code

easily and maintain the code evolution.

Page 42: Thesis Budianto 20299965

30

4.3.2 Unstructured Statement Organization

Statement organization defines the structure of a program. Several possible statement

organizations includes:

1. Statement Order

Program consists of collection of statements that is arranged in particular order to solve a

specific problem. The following code shows a piece of code from AutoSim.

ServerParameters *pServerParameters = new ServerParameters(argc, argv);

pServerParameters->extractParams();

loadGUI(pServerParameters);

Figure 4-1. An Example of Strict Ordering Statement

In respect to their order, statements‟ order can be divided into two types:

Strict Ordering Statements. By strict, we mean that the statements orders cannot

be changed. If the statements order is modified, the meaning of the statement is

different. Figure 4-1 shows an example of that have a specific order

Arbitrary Ordering Statements. On the other hand arbitrary ordering statement

allows us to arrange the statement in any ways. Although the arbitrary ordering

statement can be arranged in several ways, it has an impact on code readability,

performance, and maintainability [40]. Figure 4-2 shows a fragment of code with

arbitrary ordering statements

m_pMessageLoggerThread = NULL;

m_pNetworkThread = NULL;

m_pServerParameters = NULL;

m_pSimulation = NULL;

Figure 4-2. An Example of Arbitrary Ordering Statement

2. Conditional Statement Problem. In programming, conditional statements play important

roles as a logical sequence to make a decision. A good arrangement of conditional

statement can help us to increase code quality.

3. Loop Statement is another common statement that makes code readability low. The

following example shows the inappropriate use of while loop because it has a specified

number of time loops and simple increment (see figure 4-4 left). Hence a good choice for

Page 43: Thesis Budianto 20299965

31

this looping is for loop which not only need no internal control statement but also easy to

understand since the loop set up is defined at the beginning of the loop.

int i = 1;

int m_iArgc = ...;

while(i < m_iArgc)

{

if(...)

{

...

}

i++;

...

}

int m_iArgc = ...;

for (int i=1; i < m_iArgc; i++)

{

if(...)

{

...

}

...

}

Figure 4-3. Looping Statement of Parameter Extraction

Some considerations in using loop control in C++ can be summarized in the following:

table [40].

Looping Test

Location

Increment Style Set Up Condition

For Beginning Simple Increment or Decrement At the beginning of statement

while Beginning Arbitrary increment Before The while loop

Do while End Arbitrary increment Before The while loop

4.3.3 Long Statement

Long statement is a common programming practices by software developer, who is especially

new to object oriented concepts such that an object is threaded as a piece of code that is

sequential [20]. Moreover, early programming language limitation (e.g. the code length and the

conditional usage) bequeaths the sequential long code. But modern programming language

supports more than enough possibilities to write code with many subroutines.

m_pCalcOffset[0] =

(m_pCalcOffset[0]/m_pAreaSize[0])*

(m_pAreaSize[0]/m_heightDataPerArea -1);

m_pCalcOffset[49] =

(m_pCalcOffset[49]/m_pAreaSize[49])*

(m_pAreaSize[49]/m_heightDataPerArea -1);

m_pMainWindow-> ui.robotNameLineEdit->text().toAscii().data();

m_pRenderTargetCamera =

dynamic_cast<GraphicNode*>(

m_pRootGraphicNode->findNode(cameraName)

);

Figure 4-4. Long Statement examples

Page 44: Thesis Budianto 20299965

32

Our exploration of AutoSim found various types of long statement as follows (see figure 4-5):

Long Assignment Statement

Long Methods calls

Long Casting Operation

Long Function Parameters

4.3.4 Semantic Meaning of Program

A program can be viewed in two perspectives: a machine-readable code and human-readable

code. Both perspectives are essential to provide s fundamental concept of semantic meaning of a

program. When a program capture those two perspectives, it will produce a so called self-

documenting program [60].

AutoSim has a low understandability in statement level because it neglects the important of the

self-documenting program, which provides a meaningful identifier to software developer

including identifier name, declaration statement, and symbolic naming using enumeration.

Figure 4-6 show a comparison between two pieces of code which have the same purpose but

different semantic meaning.

...

if ( robotName.CompareTo(“camaro”) == 0)

...

if ( robotName.isEqualsTo(“camaro”) )

Figure 4-5. Semantic Meaning in Program

4.4 Refactoring for Code Readability

This sub section presents refactoring works done in the AutoSim particularly to improve the code

quality in statement level, as follows:

1. Introduce Return Object.

2. Simplify Conditional Statement

3. Replace Temp with Query Refactoring

4. Extract Method Refactoring

5. Rename Method

6. Simplify Long Methods Calls

7. Replace Hard-Coded with Enumeration

Page 45: Thesis Budianto 20299965

33

Introduce Return Object

Sometimes we have several methods that naturally go together. For instance,

getVirtualCameraTextureHeight function and getVirtuaCameraTextureWidth function is used to

retrieve the dimension of the VirtualCameraTexture. Figure 4-7 shows a piece of code of these

two methods that can be merged.

int GraphicObject:getVirtualCameraTextureHeight()

{

Return m_Height;

}

int GraphicObject:getVirtualCameraTextureWidth()

{

Return m_width

}

Figure 4-6. Two Functions that naturally can go together

The steps of introduce a return object are defined as follows:

Find a class or create a new class to represent object value.

class Dimension{

m_weight;

m_height;

public:

Dimension():

m_weight (0),

m_height(0){}

Dimension(int weight, int height):

m_weight(weight),

m_height(height) { }

int getHeight(){ return m_Height; }

int getWidth(){ return m_Width; }

};

Create a new method that returns the new object value.

Dimension getVirtualCameraTextureSize(){

return new Dimension(m_width, m_height);

}

Replace the method calls with the new method calls.

Remove the previous unused methods.

int GraphicObject:getVirtualCameraTextureHeight(){Return m_Height;}

int GraphicObject:getVirtualCameraTextureWidth(){ Return m_width;}

Page 46: Thesis Budianto 20299965

34

Simplifying Conditional Statement

Conditional statement that comprises some comparison statement can reduce program

comprehension. Simplifying the conditional statement can be done in various ways [40] [20].

The following lists present some possible strategies to simplify conditional statement:

1. Normal case should be put after if rather than after else.

if ( value < 0 ){

Printf(“error”);

}

else{

if ( value >= 0 && valur <= 10 ) ...

elseif ( value >=10 && value <= 100) …

}

if ( value >0 ){

if ( value >= 0 && valur <= 10 ) ...

elseif ( value >=10 && value <= 100) …

}

else{

printf(“error”);

}

Figure 4-7. if statement restructuring to Normal Case Ordering

2. Replace Case with Comparison operator.

Bool BuildData::

containsStringArray(STRING tagName)

{

if ( m_MultStringMap.find(tagName) !=

m_MultStringMap.end() )

return true;

else

return false;

}

bool BuildData::

containsStringArray(STRING tagName)

{

return m_MultStringMap.find(tagName)

!= m_MultStringMap.end();

}

Figure 4-8. Simplifying if statement using simple comparison

3. Simplify complicated tests with Booleans

void StartParameters::extractParams()

{

...

if(!strcmp(m_cArgv[i], "-WorldFile"))

{

...

}

else if(!strcmp(m_cArgv[i], "-RobotName"))

{

...

}

else if(!strcmp(m_cArgv[i], "-UserProgram"))

{

...

}

...

}

Bool isEqual(str1, str2)

{

return (str1.compare(str2) == 0);

}

void StartParameters::extractParams()

{

...

if(isEqual(m_strArgv[i], "-WorldFile"))

{

...

}

else if(isEqual(m_strArgv[i], "-RobotName"))

{

...

}

else if(isEqual(m_strArgv[i],

"-UserProgram"))

{

...

}

...

}

Figure 4-9. Simplifying if statement using boolean function

Page 47: Thesis Budianto 20299965

35

Replace Temp with Query

Many temporary variables can reduce the program comprehension. To simplify a program with

many temporary variables, we can employ Replace Temp with Query refactoring (see figure 4-

11) [20].

STRING

robotName=m_pMainWindow->getRobotName();

robotNameLineEdit->setText(robotName.c_str());

STRING ClientController::getRobotName()

{

return m_pMainWindow->getRobotName();

}

robotNameLineEdit->setText(

pParams->getRobotName().c_str());

Figure 4-10. An Example Replace Temp with Query Refactoring

Extract Method

Extract methods is the simplest and powerful ways to simplify the long statement, duplicate

code, and complicate statement organization. It has been already known as the most common

refactoring activities [20, 30].

The following code shows the example of extract methods (see figure 4-12).

Int main()

{

...

Int i = 1;

while(i < m_iArgc)

{

if(!strcmp(m_cArgv[i], "-WorldFile"))

{

i++;

m_strWorldFile = m_cArgv[i];

CC->m_WorldFile = m_cArgv[i];

}

else if(!strcmp(m_cArgv[i], "-RobotName"))

{

i++;

m_strRobotName = STRING(m_cArgv[i]);

}

else if(!strcmp(m_cArgv[i], "-UserProgram"))

{

i++;

m_strUserProgram = STRING(m_cArgv[i]);

}

...

}

void ExtractParameter()

{

while(i < m_iArgc)

{

if(!strcmp(m_cArgv[i], "-WorldFile"))

{

i++;

m_strWorldFile = m_cArgv[i];

CC->m_WorldFile = m_cArgv[i];

}

else if(!strcmp(m_cArgv[i], "-RobotName"))

{

i++;

m_strRobotName = STRING(m_cArgv[i]);

}

else if(!strcmp(m_cArgv[i],

"-UserProgram"))

{

i++;

m_strUserProgram = STRING(m_cArgv[i]);

}

}

int main(

{

...

ExtractParameter ();

...

}

Figure 4-11. An Example of Extract Method Refactoring

Page 48: Thesis Budianto 20299965

36

Rename Method

The purpose of rename method is to communicate its intent to the reader. Figure 4-13 shows an

example of Rename Method refactoring.

int getInt()

{

...

Return result;

}

int getIntegerValue()

{

...

Return result;

}

Figure 4-12. An Example Rename Method Refactoring

Simplify Long Methods Calling

Long method calls caused by chaining methods class makes the program difficult to understand.

AutoSim have a lot of long method calls. Figure 4-14 shows the example you have chaining

methods calls that make the code difficult to comprehend. We can introduce an intermediate

method to improve code comprehension.

m_pMainWindow->

ui.robotNameLineEdit->

text().toAscii().data();

STRING MainWindow::getRobotName()

{

return ui.robotNameLineEdit->

text().toAscii().data();

}

m_pMainWindow->getRobotName();

Figure 4-13. Simplifying Long Methods using Extract Method Refactoring

Replace Hard-Code with Enumeration

In the AutoSim Client Application, ClientController class has responsibility to control and

manage the whole process of the client application. During the process, the controller stores the

status of the process in the enumerated data types as follows:

enum Status{

CREATED = 0,

GUI_LOADED = 1,

LOADING = 2,

LOADED = 3,

CONNECTED = 4,

RENDERING = 5,

USER_PROGRAM_LOADED = 6,

STOP_RENDERING = 7,

RENDERING_STOPPED = 8,

QUIT = 9

};

The code above show the status data types in the client application. It allows expressing the

status in the English language. By replacing the status using enumerations, the code readability is

Page 49: Thesis Budianto 20299965

37

increased. For instance, the code If (controlStatus = 0) can be replaced by with If

(controlStatus = CREATED).

4.5 Discussion

Refactoring at the statement level is the most basic and the most important refactoring. There are

many ways to perform low level refactoring to increase program comprehension introduced by

several refactoring books such as “Working Effectively with Legacy Code” [41], “Code

Complete” [40], and Refactoring: Improving the Design of Existing Code[20].

Our experiences on working with AutoSim show that refactoring at the statement level allows us

to works with the higher level of refactoring. Moreover in many situations, the low level

refactoring can be the preliminary steps in software restructuring activities, when high level

refactoring is obscure. These low level refactorings can lead to big refactoring for design that

will be discusses in the chapter 6 and chapter 7.

Page 50: Thesis Budianto 20299965

38

Chapter 5

Refactoring Multithreading Application

5.1 Multithreading Overview

Thread is a part of process that has its own control. Multithreading program is a program that

consists of several threads that work collaboratively together to aim the common goals [66]. An

executable application has at least a thread called main thread. If the application is a

multithreading application, the main thread will create other threads that use the shared memory

allocation. However, each thread has different its copy of register and its stack of activation

records [67].

Multithreading has several benefits over process as follows:

1. Lightweight Process that shares resources and memory allocation

2. Thread can be scheduled on multiple processor system.

3. Thread is faster than process.

4. The thread size is smaller than process thus greater control of their priority.

5. Efficient communication because they work at the same memory space.

Multithreading has also some disadvantages:

1. Scheduling and Context switching.

2. Difficult to debug.

Bart Jacob et all found that writing multithread application in object oriented programming is

difficult for two reasons: nonlocal nature of object and race condition [68]. By nonlocal nature of

object, Bart means that there is no explicit mechanism to show if an object is shared among

multiple threads. Moreover, the implementation of multithreading programming in C++ is

Page 51: Thesis Budianto 20299965

39

operation system dependent. It means that multithreading application should consider the

operating system‟s thread management.

This chapter explores the AutoSim that comprises various threads to organize the AutoSim‟s

resources. Section 5.2 presents our exploration on the software design of multithreading

management in AutoSim and its fundamental issues. Section 5.3 provides the software

restructuring on AutoSim to remove the unused thread in order to mitigate the central issues of

multithreading management. In Section 5.4 we define the result of our program restructuring

activities and finally, in section 5.5 we summary this chapter.

5.2 AutoSim’s MultiThreadings Management

Controller NetworkThread

m_pNetworkThread

SimulationThread

m_pSimulationThread

GUIThread

m_pGUIThread

Figure 5-1. Original UML Diagram of Threads in AutoSim

AutoSim Server consists of three treads: GUIThread, a thread that executes the graphical user

interface for user, NetworkThread, a thread that provides communication port for AutoSim

Client using RakNet library, and SimulationThread, a thread that run the core simulation

process. In addition to that, the AutoSim server has a controller class that manages those treads

life. Figure 5-1 shows the class diagram of thread management modules in AutoSim Server.

Controller ClientNetworkThread

m_pClientNetworkThread

GraphicThread

m_pSimulationThread

GUIThread

m_pGUIThread

UserProgramThread

m_pUserProgramThread

Figure 5-2. Original UML Diagram of AutoSim Client Threads

Page 52: Thesis Budianto 20299965

40

Whereas AutoSim Client consists of four threads: a GUIThread, a ClientNetworkThread, a

GraphicThread, and a UserProgramThread. In AutoSim client, a ClientNetworkThread

establishes the connection to the server and a SimulationThread is replaced by GraphicThread

that visualizes the simulation object in 3D-Visualization. To manage these threads, AutoSim

client employs a ClientController class, a façade class that provides central services to

threads. Additionally, AutoSim Client also has a UserProgramThread that execute a

customizable user interface such as Qt user interface, a cross platform application and user

interface framework developed by Trolltech [55] or steering wheel joystick. The state class

diagram of the AutoSim Client classes diagram is shown in figure 5-2.

Our observation on software design and code about the multithreading implementation found

that current AutoSim has the following issues:

1. Idle main thread. Every application must have at least a main thread, which is the main

process that has a memory allocation provided by operation system. Both AutoSim server

and client also have main thread that handles the life of other child thread. However,

AutoSim server and client implement the unnecessary busy waiting looping after they

have executed all necessary threads at the beginning. Figure 5-3 shows busy waiting

loops of AutoSim.

Int main(...){

...

/* status != Exit */

while(CTRL->getSimulationStatus() != Controller::QUIT)

Sleep(100)

return 0;

}

Figure 5-3. Busy Waiting Loops in Main.cpp

2. Unsynchronized Threads. At the beginning of program execution, AutoSim Client runs

all thread that will communicate each other. The code in figure 5-4 shows the main.cpp

that call the controller‟s functions (loadGUI and loadSimulation) that start the

GUIThread and SimulationThread respectively. Between these two callings, a second

delay using Sleep(1000) causes a delay, which based on the software developer

assumption to ensure that the GUI will has been loaded before the Simulation is running.

Page 53: Thesis Budianto 20299965

41

As a matter of fact, running on slow computer, this assumption sometimes is broken and

causes the program termination since the simulation tries to read and write on the GUI.

Int main(...){

...

CTRL->loadGUI(params);

Sleep(1000);

CTRL->loadSimulation()

...

}

Figure 5-4. Sleep Methods to delay between Thread Calling

3. Difficulty in Exception Handler Implementation. During the program execution,

sometimes some object or data is not available. For instance, when a network connection

is not available or is disconnected, the simulation data is empty. Thus AutoSim client

should catch the network exception properly, display error message and resume the

connection with server. However, we found that exception handling is difficult to be

realized since every error occurs in various places. Moreover, the Qt widget does not

allow to show message window expect in main thread or in the Qt implementation, which

is an busy waiting thread [69].

4. Unnecessary Thread. Figure 5-1 and figure 5-2 shows the threads usage in the AutoSim

which contain GUIThread, which manage the user interface visualization using Qt

library. In fact, the user interface should be run in the main thread which is doing a busy

waiting loop.

5.3 Restructuring Multithreading

At this point, we have presented some issues that arise in AutoSim Application both on the

server application and client application particularly in term of multithreading management.

Hence, software refactoring to mitigate the issues must be employed to increase the AutoSim‟s

quality.

Having the above issues, we decide to replace the busy waiting of the main thread with user

interface of the GUIThread such that the number of threads is reduced and the application‟s

efficiency is increased. This replacement is essential since the nature of user interface which is a

central of application is the main thread. Hence user interface, the main thread of application,

Page 54: Thesis Budianto 20299965

42

manages threads execution. In other word, it means that the GUIThread‟s contents is moved to

main thread and all the main thread will be added to the controller.

Figure 5-5 shows the sequence diagram of AutoSim client along with a fragment code that

represent the user interface calls. Other calling includes various methods calling such as

simulation thread, network thread, and delay.

main.cpp Controller GUIThread

loadGUI()

m_GUIThread->Start()

run

Other Calling

Other Calling

Other Calling

int argc = 0;

char **argv = 0;

m_pQApplication =

new QApplication(argc, argv);

m_pMainWindow =

new MainWindow(m_pMainWindowParams);

m_pMainWindow->show();

m_pQApplication->connect(

m_pQApplication,

SIGNAL(lastWindowClosed()),

m_pMainWindow,

SLOT(on_actionQuit_activated()));

m_pQApplication->exec();

return 1;

Figure 5-5. Sequence Diagram of GUIThread implementation in AutoSim Client

The refactoring activities to remove the GUIThread can be divided into three steps as follows:

MoveMethod Refactoring moves the run function and replaces the loadGUI. Figure 5-6

shows that the content of run function replaces the loadGUI function of main.cpp.

Page 55: Thesis Budianto 20299965

43

main.cpp Controller GUIThread

loadGUI()

m_GUIThread->Start()

Other Calling

Other Calling

Other Calling

run

m_pQApplication =

new QApplication(argc, argv);

m_pMainWindow =

new MainWindow(m_pMainWindowParams);

m_pMainWindow->show();

m_pQApplication->connect(

m_pQApplication,

SIGNAL(lastWindowClosed()),

m_pMainWindow,

SLOT(on_actionQuit_activated()));

m_pQApplication->exec();

return 1;

Figure 5-6. MoveMethod Refactoring on the show methods

Remove the GUIThread and other duplication methods. The result is depicted in figure 5-

6. The cross lines on the object and methods show the object is being removed.

MoveMethod Refactoring on main.cpp. This step involves move any methods calls on

the main.cpp to mainwindow (see figure 5-7). The main window is called from the

loadGUI method and is part of the whole user interface of AutoSim.

main.cpp Controllerm_pMainWindow

Other Calling

Other Calling

Other Calling

loadGUI()

show

Figure 5-7. MoveMethod on main.cpp

Page 56: Thesis Budianto 20299965

44

5.4 AutoSim’s Structure

This section presents the AutoSim‟s class structure after refactoring on MultiThreading and

refactoring for State Pattern (see chapter 6). Figure 5-8 shows the static class diagram of

AutoSim Server along with its ControlState, which is a state pattern to control the

application‟s state transition. The detail description about the ControlState is available on

section 6.5.1.

ActivateSimulation()

ActivateNetwork()

RunNetwork()

RunSimulation()

StopControl()

ChangeState()

ControlState

Controller NetworkThread

m_pNetworkThreadm_pControllerState

Simulation

m_pSimulation

Figure 5-8. AutoSim Server's Class Diagram

The simulation process is grouped as a simulation module (see figure 5-8). Figure 5-9 shows the

content of simulation module which consists of SimulationThread, that simulates on the

physical engine and SimulationState which manages the simulation state‟s transition.

Simulation

Load()

Run()

Pause()

Stop()

toString()

ChangeState()

SimulationState

SimulationThread

m_pSimulationThread

m_pSimulationState

Figure 5-9. AutoSim Server's Simulation Package

Page 57: Thesis Budianto 20299965

45

5.5 Impact after Multithreading Resructuring

We observe that simple multithreading restructuring have various impacts. Firstly, it solves the

issues mentioned on section 5.2. It is obvious that the main thread is used as part of graphical

user interface and the GUIThread is removed such that the performance is increased. In addition

to that we can improve the threads synchronization since the number of threads is reduced.

The AutoSim application particularly the server class structure allows us to develop the system

without worrying about the synchronization. For instance, we can eliminate the time delay

between GUI loading and Simulation loading because Simulation Loading is done by GUI that

has been loaded before that as part of main thread.

Furthermore, the new implementation enables us to add new loading progress dialog that is

called by the main thread during the loading time. Every loading progress is conveyed to the

dialog such that users can monitor the progress. Among several improvement achieved after the

multithreading restructuring, we choose exception handler features that will be discussed in the

next sub section.

5.6 Exception Handler Features

The motivation of Multithread restructuring is not only to solve the issues found in the AutoSim

Application but also to increase the possibilities to add new features. After refactoring, we

introduce a new exception handler to the AutoSim Client to catch the error and display it to

users. Moreover, the exception handler also gives user option to control the application.

Having mentioned the difficulty to implement exception handler in section 5.2, AutoSim Client

cannot send an exception message that happened within a thread. However, the new design of

threading management makes the possibilities to handle message to users.

Page 58: Thesis Budianto 20299965

46

RakNetClient HandlerRequest QHandleEvent QApplication

HandleRequest(p)

new

QEvent

PostEvent(QEvent)

Figure 5-10. Exception Handler's Message Sending from RakNetClient to QApplication

Figure 5-10 shows the exception handling mechanisms. The RakNetClient is part of the

Networking module. Suppose an error occurs because of the network disconnection is catch by

RakNetClient; it will send a HandleRequest(p) message to a HandlerRequest class that will

create a new QHandleEvent, an inheritance class of QEvent (an abstract class from Qt

framework to define user defined event). Then a HandlerRequest class will post the event to the

QApplication using PostEvent(QEvent) which tells the QApplication that an event occurs.

We implement PostEvent because, Qt does not allow us to display error message from thread

other that main thread in which the QApplication.

void MainWindow::customEvent ( QEvent * event )

{

if( event->type() == QHandlerEvent::CONNECTION_LOST){

QMessageBox msgBox;

msgBox.setText("The Connection is Lost");

msgBox.setInformativeText("Do you want to exit?");

msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);

msgBox.setDefaultButton(QMessageBox::No);

int ret = msgBox.exec();

if (ret == QMessageBox::No){ CC->StopAll(); }

else{ CC->quitApplication(); }

}

}

class QHandlerEvent :

public QEvent{

public:

enum EVENT_TYPE{

CONNECTION_LOST = 10000

};

QHandlerEvent(int EventType);

~QHandlerEvent(void);

};

Figure 5-11. Exception Handler of AutoSim Client

Page 59: Thesis Budianto 20299965

47

This event, which is posted using QApplication, can be caught by MainWindows by redefining

customEvent. Figure 5-11 shows the code of the event handling which is part of the

mainwindow. The event caught is a custom event that is declare in QHandlerEvent with a unique

user defined number.

5.7 Summary

AutoSim is a multithreading application that has some discrepancies in threading

implementation. But, multithreading implementation is the important construction that built up

the fundamental architectural level of both AutoSim server and client that have many

independent processes. Simple refactoring that is performed by removing unnecessary thread

allows us to improve the next development in AutoSim application.

Page 60: Thesis Budianto 20299965

48

Chapter 6

Refactoring Singleton Pattern Overuse

This chapter discusses our experiences in refactoring singleton pattern overuse in AutoSim

project. It starts with the overview of singleton pattern (section 1) and continues with the

example of singleton (section 6.2). In section 6.3, the singleton overuses exist on the AutoSim

will be discussed: their motivations, impacts and consequences. The last two sections include

refactoring activities to mitigate the singleton overuse impacts and other possible mitigation

strategies.

6.1 Singleton Overview

Singleton pattern is the simplest design pattern introduced by the Gang of Four [26]. The

simplicity lies on its implementation which requires only a class with at least two static

members: a member variable to hold an instance of its own class and a member function to

retrieve its own instance. Moreover, a sole instance of object and global accessibility also

characterize a uniqueness of singleton pattern among many design patterns.

class Singleton

{

static Singleton instance;

public Singleton(){...}

public:

...

static Singleton *getInstance()

{

return &instance;

}

};

Figure 6-1. Singleton Pattern

Figure 6-1 shows the class diagram of a singleton pattern and its implementation using c++. The

variable instance is a static member variable that has private accessibility and getInstance is a

static member function that can be accessed from outside the class. More important to ensure its

solitary, the constructor of singleton class is defined as private, which means that the object

Singleton

static Singleton instance

Singleton()

static getInstance()

operations()

Static member

function

Static member

variable

Page 61: Thesis Budianto 20299965

49

creation can only be done using a public static member function getInstance. In the real world

application, singleton pattern is frequently employed in the context that a general services is

needed for the whole application. For example, a printer spooler object or database connection

object should be defined as singleton pattern because most part of application needs to access a

printer and database.

ClientController.h

#define CC ClientController::getInstance()

class ClientController : public Singleton<ClientController>

{

public:

...

};

Main.cpp ClientWorldBuilder.cpp

int main(int argc, char *argv[])

{

CC->pParams = new StartParameters();

int i = 1;

while(i < argc)

{

if(!strcmp(argv[i], "-WorldFile"))

{

i++;

CC->pParams->worldfile = argv[i];

CC->m_WorldFile = argv[i];

}

...

}

CC->loadGUI(CC->pParams);

if(CC->pParams->starttype == 1)

CC->loadWorld();

else if(CC->pParams->starttype == 2)

{

CC->loadWorld();

CC->startNetwork();

CC->startGraphics();

CC->startUserProgram();

}

}

...

void

ClientWorldBuilder::buildGraphics(BuildData

*BD){

...

if(params->Fullscreen){

...

}

else {

params->WindowId =

CC->getIrrlichtWindowID();

params->WindowSize.Width=

CC->getIrrlichtWindowWidth();

params->WindowSize.Height =

CC->getIrrlichtWindowHeight();

}

...

}

...

ClientUserProgramAPI.cpp MainWindow.cpp

namespace ClientUserProgramAPI

{

int getImageHeight(){

return

CC->getVirtualCameraTextureHeight();

}

int getImageWidth(){

return

CC->getVirtualCameraTextureWidth();

}

...

void unlockImage(){

CC->unlockVirtualCameraTexture();

}

}

...

void MainWindow::on_actionLoad_activated(){

CC->loadWorld(pQProgressDlg);

...

}

void MainWindow::on_actionRun_activated(){

CC->startAllThreads();

}

void MainWindow::runSimulationAutomatically()

{

if (CC->m_pParams->getAutoStart()){

on_actionLoad_activated();

CC->startAllThreads();

}

}

Figure 6-2. ClientController class.

Page 62: Thesis Budianto 20299965

50

6.2 Example of Singleton in AutoSim

The ClientController class is a controller class that manages the interaction of objects in the

AutoSim client. As such, this class is defined as singleton pattern that exists during the

application lifetime (figure 6-2). In this example, the predecessor directive CC is used to get an

instance of this class (figure 6-2). The example of CC usage can be found in code with bold font.

6.3 Singleton Overuse

Erich Gamma states that singleton pattern provides some benefits on controlling accessibility to

sole instance, reducing namespace, permitting refinement of operations and representations, and

flexibilities [26]. On the other hand, the benefits turn into a nightmare when the singleton pattern

is used often than the requirement. The addiction to the Singleton pattern is called singletonitis

by Joshua Kerievsky [42]. We are going to use singleton overuse to refer the singletonitis.

This section will present the result of our finding on singleton usage in AutoSim, its impacts and

consequences. An example of debugging activities that caused by singleton overuse is also

discussed.

6.3.1 Motivation of singleton usage

Both AutoSim Server and Client application use singleton pattern intensively to provide global

communication among objects. Our investigation found several the motivation of singleton usage

as follows:

1. Global Accessibility. Object oriented programming provides an encapsulation for information

hiding. In fact, a module or a class also need to passing information to other object. In order

to achieve that there are several ways such as inheritance, parameter object, relationship, and

global object. Most of message communication in AutoSim is by employing the singleton

pattern on some important class.

2. Data sharing for multithreading implementation. Multithreading application requires data

sharing among the threads. Global access of singleton pattern provides the easiest solution.

However this solution also lead to race condition, undesirable situation where two thread try

to write on the same data [70].

3. Software design Ignorance. Software design is hard; designing reusable object oriented is

harder. The software design ignorance is simplest way to run away from the difficult task.

Page 63: Thesis Budianto 20299965

51

6.3.2 An Example: Debugging Experience in Singleton Overuse Design

This section discusses an example from our experience in debugging a system with singleton

overuse. Because the system occasionally cannot be started, we conduct debugging to find the

faulty location. Based on the debugging tools, the fault is located in loading module. Further

investigation found that the AutoSim Server calls the MessageList operator <<, which access

the graphical user interface (GUI) which has not been initialize (see figure 6-3). But, the

information about faulty location does not help us to find the cause since the failure is happened

occasionally and our code review shows that the GUI has been initialized before. After a few

week of searching for the exact location, we found nothing and the debugging activities is

postponed.

MessageList& MessageList::operator<<(const STRING& str)

{

...

CTRL->m_pGUIThread->m_pMainWindow->ui.messagesTextEdit->append( str.c_str() );

...

}

Figure 6-3. The Fault location in the MessageList class

Later, during refactoring activities, the fault location is found in the main.cpp, which is located

far away from the loading module. The cause is software developer‟s assumption about the

thread‟s communication. It is assumed that the GUI loading process faster for 1 second than

Simulation loading process (see Figure 6-4).

CTRL->loadGUI(pStartParam);

Sleep(1000);

CTRL->loadSimulation();

Figure 6-4. The Actual Fault Location

The difficulty in finding the fault location in the above example is caused by singleton pattern

overuse which provides undesirable global accessibilities and multithreading, which require a

synchronization mechanism. In fact, the simulation loading should be called by the controller not

by the main thread. In the above problem, a software developer can called the simulation process

anywhere within the program.

Page 64: Thesis Budianto 20299965

52

6.3.3 Consequences of Singleton Overuse

The singleton overuse occurs when a software developer begins to employ singleton pattern so

deeply into the software design that it starting lording the entire design. Thus the global

accessibilities are found at any places of the software. The Singletonitis has several bad

consequences:

1. Re-entrant Code Problem. The code that over use singleton pattern has many ways to be

accessed. In multithreading application, the singleton is possible to be shared among different

process [42]. In this situation, the effort to keep the meaning of global singleton is tested.

And when this global singleton is used, it is difficult to detect whether it is has been modified

or accessed in some other place in the program. Thus it makes the program is difficult to

understand [41].

2. Low Reusability. Software engineering is different from other kinds of engineering. The

major is different lies on its flexibilities strike any other engineering disciplines that enable

software to modified easily. A industrial report shows that a systematic reuse can obtain cost

and time savings in some company such as AT&T, Brooklyn Union Gas, ericsson, GTE,

Hewlett-Packard, IBM, Motorola, NEC, and Toshiba [71]. Its flexibility can be employed

effectively by reusing the existing software system. To achieve good reusability, a software

system must be designed in such a way it provides abstraction by hiding the detail of the

implementation. However, the system with singleton overuse works in the opposite

directions. By introduction global access, the software system suffers from high

dependencies between classes relationships which focus on the detail of the software design

rather that the abstraction.

3. Low Readability. After software design is created, it is implemented by coding in the

particular programming language. Although having the same software design, two software

developer can produces totally different code. Coding is a creative implementation of

software developer based on their personal styles and taste. Several issues in the software

implementation such as indentation, coding line length, commenting styles in not important

to be standardized in to a common rules or standard [72]. However good code readabilities

are essential in software development. Failing to provide high readabilities can put the

software project in risk of failure. It becomes difficult to be changed, maintenanced,

debugged, and developed.

Page 65: Thesis Budianto 20299965

53

4. Low Testability. Human is not perfect and so is the software made by human. Because we are

not perfect, the software testing is essential to find the software defects. Knowing that no

silver bullet for software defect and get rid of our confidence about the perfect software is a

fundamental requirement for software testing [73, 74]. Realizing about the nature of software

and the need of software testing does not imply that software testing can be conduct easily. In

fact, software testability determines the degree of unit-test and system-test of a system can be

done. When software suffers from high coupling caused by singleton overuse, it becomes

dependent to many classes and thus the unit testing is difficult to be performed.

5. Difficult in Debugging. Debugging is important to find and fix the defect when the software

specification is violated. However when the software has many singletonitis (singleton

addition), debugging can be frustrated as it can jump from one class to another class in

unstructured way. Moreover, the effective debugging technique available is only an

“inserting print statements” since the debugging tools cannot be employed in unmanaged

multithreading [75].

6. Unsafe Message Sharing among Thread. AutoSim is multithreading and client server

application that need to share data. The data communication employed is global variable

using singleton.

6.4 Singleton Mitigation

Reducing the impact of singleton overuse in complex system can be a difficult task. In reality,

We suggest some possible practical solution to mitigate its impact in the future by refactoring the

problem. This section gives us some rule of thumb that might be employed to mitigate the

singleton overuse are defined in table 1.

Table 6-1.Refactoring Steps for Singleton Pattern Overuse Mitigation

Steps. Refactoring Name Description

Step 1 Show Method Change the Constructor Method accessibility to public

Step 2 Add Field Add a new object or new pointer of object to store an

object

Step 3 Add Parameter Object Add parameter object to pass the object to classes that use

the singleton

Step 4 Replace Singleton Pattern with Class Change the Singleton Class to ordinary class

Page 66: Thesis Budianto 20299965

54

6.4.1 Example

Suppose we want to remove singleton pattern from the Graphics class from our software design.

Firstly we need to explore any classes that use the graphic class. In the belowed example, we

found there are three classes namely, GraphicThread, ClientWorldBuilder, and

ClientController class has defined a Graphics class using singleton. The finding classes need to

be considered for the next step to determine in which class we might store our reference to

graphic.

Graphics.cpp GraphicThread class

#define GRAPHICS Graphics::getInstance()

class Graphics

{

static Graphics *m_pGraphics;

Graphics(){

...

}

public:

static Graphics* getInstance(){

If (m_pGraphics == NULL)

m_pGraphics = new Graphics()

return m_pGraphics;

}

...

};

class GraphicThread : public Thread

{

public:

int Run()

{

GRAPHICS->run();

}

};

ClientWorldBuilder class ClientController class

class ClientWorldBuilder : public WorldBuilder

{

public:

...

void buildGraphics( BuildData *BD )

{

GRAPHICS->init(

createIrrlichtParams(BD),

static_cast<unsigned int>(

BD->getDouble("Detail")

)

);

}

...

};

class ClientController{

...

int* getVirtualCameraTexture(

STRING cameraName){

...

clock_t time = clock();

GRAPHICS->getRenderedTexture(cameraName);

...

}

...

};

Page 67: Thesis Budianto 20299965

55

1. Show Method

Change the Singleton‟s constructor accessibility from private to public

-Graphics()

Graphics

+Graphics()

Graphics

class Graphics

{

static Graphics *m_pGraphics;

Graphics(){

...

}

public:

static Graphics* getInstance(){

If (m_pGraphics == NULL)

m_pGraphics = new Graphics()

return m_pGraphics;

}

...

};

class Graphics

{

static Graphics *m_pGraphics;

public:

Graphics(){

...

}

static Graphics* getInstance(){

If (m_pGraphics == NULL)

m_pGraphics = new Graphics()

return m_pGraphics;

}

...

};

2. Add Field.

Among many classes in our system, we have to select which class that should store

our references to the singleton class. The class selected should have some criteria

such as a Façade class or the parent class.

Suppose we choose ClientController and we need to declare a reference variable

that store the Graphic Object (σ1) and initiate on the init function (σ2).

ClientController

-m_Graphics

ClientController

class ClientController{

...

public:

void ClientController ():

{

...

}

...

}

class ClientController{

...

Graphics *m_pGraphics;

public:

void ClientController ():

m_pGraphics(new Graphics())

{

...

}

...

int* getVirtualCameraTexture(STRING

cameraName){

...

};

}

σ1

σ2

Page 68: Thesis Budianto 20299965

56

3. Add Parameter Object

Each call in classes that access the singleton class must be replaced. As a rule of

thumb, the replacement strategies depend on the frequency of the calls made. If the

number of singleton calling is few, the temporary parameter object can be used. By

temporary parameter object, we mean the parameter object that pass to a method and

is used temporality within a method. If the number of singleton calling is many, it is

preferable to store the parameter object passed to the method.

class ClientWorldBuilder

{

public:

...

void buildGraphics(...)

{

GRAPHICS->init(

createIrrlichtParams(BD),

static_cast<unsigned int>(

BD->getDouble("Detail")

)

);

}

...

private:

...

};

class ClientWorldBuilder

{

public:

...

void buildGraphics( ..., Graphics *pGraphics)

{

pGraphics->init(

createIrrlichtParams(BD),

static_cast<unsigned int>(

BD->getDouble("Detail")

)

);

}

...

private:

...

};

Other consideration is when an object is passed as a parameter object. In the

temporary parameter object, an object is passed when the method is called. However

when an object references is stored as member of a class, the object can be passed in

various time. Most are passed on the beginning of class creation through its

constructor/. Some which do not exist at that time, can be passed as soon as possible

through a parameter object, when a method of the class is called.

class GraphicThread : public Thread

{

...

public:

int Run()

{

GRAPHICS->run();

}

...

};

class GraphicThread : public Thread

{

Graphics* m_pGraphic;

...

public:

GraphicThread(Graphics *pGraphics):

m_pGraphic(pGraphics)

{

}

int Run()

{

pGraphic->run();

}

...

};

τ1

Page 69: Thesis Budianto 20299965

57

4. Replace Singleton Pattern with Class

The last treatment of singleton pattern overuse is to replace with an ordinary class. It

was done by deleting static member variable that hold its object and deleting static

member method that get its own instance. Moreover, the preprocessor directive that

represents the static member methods must also be removed.

#define GRAPHICS Graphics::getInstance()

class Graphics

{

static Graphics *m_pGraphics;

Graphics(){

...

}

...

public:

static Graphics* getInstance(){

If (m_pGraphics == NULL)

m_pGraphics = new Graphics()

return m_pGraphics;

}

...

};

class Graphics

{

Graphics(){

...

}

...

public:

...

};

6.5 Other Strategies for Singleton Overuse Mitigation

When a software developer has a tendency in using singleton pattern, the software design will

suffer a singleton addiction. This symptom will lead to problem such as chaos design. Moreover

the testability of the software design becomes difficult to achieve as a result of high coupling and

dependencies among classes. Joshua suggests object passing usage to remove singleton overuse.

He also proposes the inline singleton usage [42]. Inline singleton is not a singleton pattern but a

refactoring technique that is commonly applied to remove of singleton overuse and move the

object feature to the class that accesses the object.

Kent beck report that after removing singleton overuse, the following result is achieved [42]:

a. Flexible and neat software design

b. Stable Testability

c. Sense of Relief

Page 70: Thesis Budianto 20299965

58

Other strategies that can be used to mitigate the impact of global accessibility of singleton is

registry, an object that can provides services or can be used to find other object [20]. Registry is

singleton pattern that have different implementation in the different scopes. Registry is based on

limiting the scope of accessibility of object.

6.6 Conclusion

Software design pattern allows us to communicate the design to other stakeholders during

software development activities. Singleton pattern also helps us to understand a software design.

However singleton overuse that is implemented incorrectly makes the system difficult to be

maintained and reused. This chapter has discussed the singleton pattern and singleton overuse

mitigation.

However we have not removed some singleton overuse in AutoSim application due to high

coupling problem. Future work, particularly related to singleton overuse, should be considered.

Page 71: Thesis Budianto 20299965

59

Chapter 7

Refactoring for State Pattern

In this chapter, we focus on the techniques for modeling and implementing simulation‟s state.

Modeling simulation‟s states transition will provides semantic information about the behavior of

the system, its elements, its interactions, and its transitions that represent the system‟s properties

changes.

Firstly, the finite state machine, a famous behavior model, will be discussed to provide a basic

theoretical aspect of this simulation model. After that several possible code implementations of

finite state machine in programming language is discussed. Finally, our implementation of

refactoring to state pattern to improve the current AutoSim design will be outlined.

7.1 Modeling Simulation System

An important part in system development to understand its behavior is a system model, which is

an abstraction of how the system works. There are various model notations that can be used to

document system behavior ranging from data flow diagram to state diagram. A data flow

diagram records the flow of data and presents the data transition among system elements.

Whereas flowchart diagram is very useful to present the algorithm sequence of program such as

conditional statement (e.g. if then else) and repeating behavior (e.g. looping). However neither of

them is capable to document the system‟s state transition, which characterized the simulation

system‟s behavior.

The need of notation to represent the system‟s state transition is addressed by automata theory,

the theoretical computing discipline that study about a graph representation [76]. In automate

Page 72: Thesis Budianto 20299965

60

theory, finite state machine (FSM) provides a conceptual model describes as the number of states

and their transitions.

7.1.1 Statecharts Overview

Statecharts is an extension model of FSM that provides a graphical notation for modeling

reactive system from the point of view of the system‟s behavior. Using statecharts, we are allows

to trace the system‟s process and analyze the system‟s transition. Statecharts provide facilities to

capture the following information:

System’s behavior transition is essential for tracing the system‟s changing.

System’s states dependencies and their entry and exit criteria.

System’s Concurrency Processes.

System’s timing information.

Statecharts helps software developers by documenting system behavior and allows them to

reason and to validate the systems‟ completeness and correctness. By completeness and

correctness, we mean that a system can be views as a holistic and complete system which needs

to be validated. In addition to that, a behavior model also acts as a communication tools for

stakeholders during the whole system development process [28].

Furthermore, statechart provides an effective modeling diagram that help us in modeling a state-

driven system by reducing the behavioral complexity [77]. In other word, it means that statechart

is suitable for modeling a dynamic aspect of a system that employed highly state-dependent [78].

Statechart notation consists of collection of states and input events that generate the transition

between states. A state is depicted as a circular or rectangular shape that determines the

recognizable situation of entity or system at a given time. An event is an atomic trigger that

happens at a particular time. Examples of events are Gas Pedal pressed or the break pressed. In

statechart, the transition depends not only to input event but also to the current state. Sometime,

the event has no impact to the current state and the system remains in the same state. For

instance, the gas pedal does not move a car when the current state is on engine off.

Page 73: Thesis Budianto 20299965

61

Paused

Stopped

Running

/ Stop/ Run

/ Stop

/ Pause

/ Run

/ Initialize / Terminate

Figure 7-1 Simple Finite State Machine (FSM) Diagram.

An event can be divided into two types: input events and special events called timer. Timer event

is event that happen every particular defined elapsed time (e.g. 10ms, 1s, etc). A timer that has an

elapsed time s = 10 second will send a trigger message after ten seconds elapses time has been

finished after started, the events is triggered automatically by the timer.

Figure 7-1 shows an example of simple statechart with three states: Stopped, Paused and

Running. Moreover, the system also has two special states: Start state (black circle) and End

state (black circle with line). The Start state determines the beginning of the statechart before

the system is started. After the system started, the state changes to the Stopped state immediately.

Whereas the End state is when the system is turn off. The above system also consists of transition

with the trigger name that determines the event that causes the transition. For instance when

currently the system is in the Stopped state and the Run Event is called or triggers, the system‟s

state move the Running state.

7.2 State Diagram Implementation Example

A statechart diagram or FSM can be realized into various code implementations in different type

of programming language. In C++, a system state can be represented using a variable that hold

the enumeration value, a user defined types in C and C++ program. The current value of variable

determines the current state of system. A transition to other state is done by modifying the value

of the variable. A table or an array that hold a collection of functions that represent events can

Page 74: Thesis Budianto 20299965

62

also represent the statechart or FSM. Moreover, Gamma et all also introduce more sophisticated

approach by applying so called state pattern where every states are represented as objects and the

transition is done by changing the a parent object hold an instance of particular object that

represent the current object [26]. The summary of the implementation of state diagram will

discuss in the following sub sections along with their advantages and disadvantages.

7.2.1 Nested Switch Statement and Variable status

A status variable is the simplest way to represent FSM. A variable hold the enumeration value

that represent current state of system. To implement the transition, the variable value is modified

to other enumeration value. In this implementation, a program must employ the nested switch or

other conditional statement (e.g. if else statement) that is used to validates the transition among

state (figure 7-2).

enum CLIENTSTATE_TYPE{

STOPPED,

PAUSED,

RUNNING

};

CLIENTSTATE_TYPE ClientStatus;

...

Switch(ClientStatus){

case STOPPED:

...

ClientStatus = RUNNING

break;

case PAUSED:

... // Client Load Function

ClientStatus = RUNNING

break;

case RUNNING:

...

break;

}

Figure 7-2 FSM Implementation using Nested State Switch.

FSM implementation using nested switch statement or if-statement has the following

benefit:

- Easy to implement and simple

- Program Comprehension achieves using enumeration.

- Efficient memory usage.

Page 75: Thesis Budianto 20299965

63

However the nested switch implementation also has some disadvantages as follows:

- Low Program Comprehension in complex FSM. Suppose an FSM consist of many nested

states, the code become difficult to understand because the code implementation consists

of many switch statement.

- No separation of FSM implementation and other Implementations. The nested switch

statement is part of the program which consists of not only FSM implementation but also

other system‟s implementation such as data structures implementation. Thus the code

become complex and also decrease modularity of the system.

- No type safety Support. Even though enumeration increase the program comprehension.

In C++ enumeration is treated as integer value which provides no type safety in

assignment operation.

- Low reusability. Variable implementation does not provides any modularity to the system

that increase the reusability of object-oriented system.

7.2.2 State table

Figure 7-3 and figure 7-4 shows the table state representation and the table state implementation

in C++. In figure 7-4, a statechart transition is modeled using a table or an array (σ1). The row

of table represents the possible states and each column of a given state represents the possible

transitions. The transition implementation is defined in functions (σ2). When an event occurs,

the changeState function will call find the current appropriate function from the transition table

(σ3).

Figure 7-3 State Table of statechart on Figure 7-1

&Run()

&Pause()

EMPTY

&Stop()

&Run() &Stop()

Stopped State

Running State

Paused State

Transitions

Page 76: Thesis Budianto 20299965

64

void init(State *s){

...

setState(s, LOADING);

};

void Load(State *s, Event *e) {...};

void Run(state *s, Event *e) {...};

void Stop(State *s, Event *e) {...};

static const Transision trans_table[][] = {

{ (Trasisision)& init, EMPTY },

{ (Trasisision)& Run, (Trasisision)& Pause },

{ (Transision)& Stop, EMPTY } };

struct StateTable{

Transision *trans_table;

Int State;

Int n_state;

Int n_trans;

};

void setState(StateTable, int state)

{

s->State = state;

}

void ChangeState(StateTable *s, Event *e)

{

assert(e->n_trans > s->n_trans);

Transision* t = s->trans_table[s->State * s->n_state + e->event_idx);

(*t)(s, e);

}

Figure 7-4 State Table Implementation

FSM implementation using table state has the following benefits:

- State table provides a good structure to represent states and their transition.

- Better Type safety. The state is changed using a function which has two parameters:

current state and the event that generate transition.

- Better program comprehension by hiding detail implementation in table and function.

State and transition is implemented separately using variable and functions that stored in

state table.

σ1

σ2

σ3

Page 77: Thesis Budianto 20299965

65

However the state table implementation also has some disadvantages as follows:

- Medium Memory usage (compare with variable usage). The table size equals to the

multiplication between number of states and the number of transitions.

- The availability of Empty Data. When the number of transition varies among different

states, there will be a lot of empty data stored in the table since each row have the same

number of column.

- Low reusability. When a new state or a new transition is introduced. A original array size

must be change and the code must added by new function to represent a new transition.

- No type safety. The implementation of state is represented using integer value which can

hold any integer number.

- Intertwined Event Implementation. The if-statement sometimes must be used to check

several events that have the same name from various states. For example: both Paused

State and Running State have the same function Stop, the if-statement must be

employed to differentiate between those two events. Other solution, we have to define

different function name for those states.

7.2.3 State Pattern

If object oriented programming is used, statechart can be realized using a state pattern [26]. A

class, which is inherited from an abstract parent class, is used to represent each possible state. In

the program, a member variable is declared as the abstract parent class to hold an instance of any

inheritance class.

Run()

Stop()

Pause()

ChangeState()

State

Stop()

Run()

Paused

Run()

Stopped

Pause()

Stop()

Running

Run()

Stop()

Pause()

Client m_status

m_state->Run

Figure 7-5. UML Diagram of State pattern

Page 78: Thesis Budianto 20299965

66

Figure 7-5 shows the class diagram of the state pattern. A client is a program or class that

declares a variable to store a particular state. Each state represent as an object such as Paused,

Stopped or Running. When an event occurs, an instance of class that represents the system state

will call an appropriate function and move to the next state.

A Statechart implementation using state pattern has the following benefits:

1. Separated Event Implementation. The event implementation is unique for each state even

the name of the event is the same. For instance, the Paused and Running State inherits

Run function with different implementation.

2. High reusability. Each state is realized using a class. When a new state is introduced, we

can be derived from the abstract parent class.

3. Good Type Safety. Using class representation, a variable that hold the system‟s state is

type safe only to possible instance of inheritance class. Moreover this implementation

provide transition protection by specify different event. For instance when the current

state is Stopped and the function stop is triggered, the system will ignore the event.

4. Provide Abstraction for Communication among stakeholder. The design pattern can be

used to communicate the system behavior‟s implementation to stakeholder during the

system development.

However the state pattern implementation also has some disadvantages as follows:

1. Complicate Implementation. For a system with simple state transition, state pattern

provides complicated implementation.

2. High memory usage. Each state is realized using a class along with its implementation

and parent data.

7.3 AutoSim: State Transition Design and Problems

Both AutoSim Server and Client have state transitions implemented using a variable that stores

the current state and if statement to validate the state‟s value. If the event is triggered, the value

of variable is modified to show the transition to other state. The possible state is represented

using enumeration data type.

Page 79: Thesis Budianto 20299965

67

Class Controller:...

{

...

Public:

enum

{

INITIALIZED = 1,

GUI_LOADED = 2,

LOADING = 3,

LOADED = 4,

RUNNING = 5,

PAUSED = 6,

STOPPING = 7,

STOPPED = 8,

QUIT = 9

};

int m_SimulationStatus;

...

};

Controller::Controller() {}

void Controller::init()

{

...

m_SimulationStatus = INITIALIZED;

}

void Controller::loadGUI(...)

{

if( ... && m_SimulationStatus

== INITIALIZED)

{

...

m_SimulationStatus = GUI_LOADED;

}

}

void Controller::loadSimulation()

{

...

if( ... && m_SimulationStatus == GUI_LOADED)

{

m_SimulationStatus = LOADING;

...

m_SimulationStatus = LOADED;

}

}

void Controller::runSimulation()

{

if(m_SimulationStatus == LOADED)

{

...

m_SimulationStatus = RUNNING;

}

else if (m_SimulationStatus == PAUSED)

{

...

m_SimulationStatus = RUNNING;

}

}

void Controller::pauseSimulation()

{

if(m_SimulationStatus == RUNNING)

{

...

m_SimulationStatus = PAUSED;

}

}

void Controller::stopSimulation()

{

if ( m_SimulationStatus == RUNNING ||

m_SimulationStatus == PAUSED )

{

...

m_SimulationStatus = STOPPED;

}

}

Figure 7-6 A Piece of code that represents AutoSim Implementation

The figure 7-6 shows a piece of the code that implements the state transition. However the

FSM‟s is not clearly represents the state transition. For instance the enumeration represents

several different level of state such as state for the simulation and states for the application itself.

Thus the system becomes complicated.

The software developer declares the possible state using enumeration (σ1) and the application‟s

state is defined using a member variable, m_SimulationStatus with integer type (σ2). Before

using it, this variable is initialized with default state of the system, INITIALIZED (σ3).

Moreover software developer provides several functions that are called when an event is

triggered. When a function is called, first it validates the current state stored in the variable using

σ1

σ3

σ2

α1

β1

α6

α5

β6

β5

β4

β2

β3

α2

α3

α4

Page 80: Thesis Budianto 20299965

68

if statement (α1−6). When the current state is valid, the program continues by running the next

process and finished the process by change the current state to the next state (β1−6).

7.3.1 Problem of AutoSim’s state transition

The state transition implementation of AutoSim has four problems as follows:

a. User Interface State. From the user‟s point of view, the graphical user interface should

represent the visible current state of system. For instance, when the system is stopped, the

stop button should be disabled.

b. Public Accessibility. The simulation‟s state variable, m_SimulationStatus, has public

accessibilities. It means that the software developer allows variable modification in any

classes within the system. The following question is difficult to answer: When does

AutoSim change from a state to another state? What object is responsible to change the

system‟s state? What happened to the system when the system‟s state is changed?

c. Exception Handling. During the integration testing, the system‟s stability is unpredictable

caused by unhandled exception during the state transition. When an exception is trigger,

the error is not caught. However exception handling cannot be realized since it is

occurred in various places across the system modules. What makes worse, the Qt

architecture does not allow displaying an error message dialog at any code

implementation except at main thread. Hence the state transition implementation will

influence on implementing exception handling.

d. State Transition Design. The application‟s state transition is difficult to understand. Front

enumeration declaration, we found nine states (σ1). Moreover, the state transitions are

complicate as a result of duplication and unclear intents. AutoSim should provide an

abstraction to represent the current nine states and their transitions for better program

comprehension.

7.4 Refactoring to State Pattern

This section presents the refactoring steps for state pattern. Table 7-1 shows the summary of

refactoring steps for state pattern. The following sub sections describe each step.

Page 81: Thesis Budianto 20299965

69

Table 7-1 Refactoring Steps for State Pattern

Steps. Refactoring Name Description

Step 1 Add new Empty Class Add new empty class to represent the state of context class

Step 2 Move Field Move the enumeration type to the new class

Step 3 Extract Sub Class Extract sub class based on the new

Step 4 Replace Data Value With Object Replace the enumeration data value to the type safe object

Step 5 Add Methods Add new method (ChangeState) on both context class and

new Class for State Pattern

Step 6 Move Method Move the state transition implementation from the context

class to the appropriate inheritance class.

7.4.1 Example

Consider an example of Client‟s state implementation in figure 7-8 and its corresponding class

diagram in figure 7-7.

+Run()

+Stop()

+Pause()

Client

Figure 7-7 Client Class

This class is the code implementation of the statechart in figure 7-1, which consist of three event

functions namely, Run, Stop, and Pause.

Page 82: Thesis Budianto 20299965

70

class Client{

enum state_type{

STOPPED,

RUNNING,

PAUSED

};

state_type currentState;

public:

Client(){

currentState = STOPPED;

}

void run(){

if (currentState == STOPPED){

cout << "STOPPED to RUNNING" << endl;

currentState = RUNNING;

}

}

void stop(){

if (currentState == RUNNING){

cout << "RUNNING to STOPPED" << endl;

currentState = STOPPED;

}

else if ( currentState == PAUSED){

cout << "PAUSED to STOPPED" << endl;

currentState = STOPPED;

}

}

void pause(){

if (currentState == RUNNING){

cout << "RUNNING to PAUSED" << endl;

currentState = PAUSED;

}

}

};

Figure 7-8 A Piece of Original AutoSim Code

1. Add new Empty Class. Create a new class with name ClientState and Compile. This

class will be used as a parent of the state pattern.

class ClientState{

};

Page 83: Thesis Budianto 20299965

71

2. Move Field. Move Enumeration Type to new class and change all assignment to

enumeration to ClientState enumeration.

class Client{

enum state_type{

STOPPED,

RUNNING,

PAUSED

};

state_type currentState;

public:

Client(){

currentState = STOPPED;

}

void run(){

if (currentState == STOPPED){

cout << "STOPPED to RUNNING\n";

currentState = RUNNING;

}

}

void stop(){

if (currentState == RUNNING){

cout << "RUNNING to STOPPED\n";

currentState = STOPPED;

}

else if ( currentState == PAUSED){

cout << "PAUSED to STOPPED\n";

currentState = STOPPED;

}

}

void pause(){

if (currentState == RUNNING){

cout << "RUNNING to PAUSED\n";

currentState = PAUSED;

}

}

};

class ClientState{

public:

enum state_type{

STOPPED,

RUNNING,

PAUSED

};

};

class Client{

ClientState::state_type currentState;

public:

Client(){

currentState = ClientState::STOPPED;

}

void run(){

if (currentState == ClientState::STOPPED){

cout << "STOPPED to RUNNING\n";

currentState = ClientState::RUNNING;

}

}

void stop(){

if (currentState == ClientState::RUNNING){

cout << "RUNNING to STOPPED\n";

currentState = ClientState::STOPPED;

}

else if ( currentState == ClientState::PAUSED){

cout << "PAUSED to STOPPED\n";

currentState = ClientState::STOPPED;

}

}

void pause(){

if (currentState == ClientState::RUNNING){

cout << "RUNNING to PAUSED\n";

currentState = ClientState::PAUSED;

}

}

};

Figure 7-9 Move Field Refactoring

Page 84: Thesis Budianto 20299965

72

3. Extract Sub Class. Create new inheritance singleton classes (class

ClientStateStopped, ClientStatePaused, and ClientStateRunning, are extends

from ClientState) that represent every possible states.

ClientState

+Instance()

-m_State

ClientStateStopped

+Instance()

-m_State

ClientStateRunning

+Instance()

-m_State

ClientStatePaused

Figure 7-10 UML Diagram of SubClasses after Extract Sub Class Refactoring

class ClientState{

public:

enum state_type{

STOPPED,

RUNNING,

PAUSED

};

};

class ClientStateStopped : public ClientState{

static ClientStateStopped m_State;

public:

static ClientStateStopped* Instance(){

return &m_State;

}

};

class ClientStateRunning : public ClientState{

static ClientStateRunning m_State;

public:

static ClientStateRunning* Instance(){

return &m_State;

}

};

class ClientStatePaused : public ClientState{

static ClientStatePaused m_State;

public:

static ClientStatePaused* Instance(){

return &m_State;

}

};

Figure 7-11 Extract Sub Class Refactoring

Page 85: Thesis Budianto 20299965

73

4. Replace Data Value With Object. Change the enumeration data value (unsafe-type) in

context class to object type (safe-type)

+Run()

+Stop()

+Pause()

ClientClientState

+Instance()

-m_State

ClientStateStopped

+Instance()

-m_State

ClientStateRunning

+Instance()

-m_State

ClientStatePaused

currentState

Figure 7-12 Class diagram after Replace Data Value with Object Refactoring

class Client{

ClientState::state_type currentState;

public:

Client(){

currentState = ClientState::STOPPED;

}

void run(){

if (currentState ==

ClientState::STOPPED){

cout << "STOPPED to RUNNING" << endl;

currentState =

ClientState::RUNNING;

}

}

void stop(){

if (currentState ==

ClientState::RUNNING){

cout << "RUNNING to STOPPED" << endl;

currentState =

ClientState::STOPPED;

}

else if (currentState ==

ClientState::PAUSED){

cout << "PAUSED to STOPPED" << endl;

currentState =

ClientState::STOPPED;

}

}

void pause(){

if (currentState ==

ClientState::RUNNING){

cout << "RUNNING to PAUSED" << endl;

currentState =

ClientState::PAUSED;

}

}

};

class Client{

ClientState *currentState;

public:

Client(){

currentState = ClientStateStopped::Instance();

}

void run(){

if (currentState ==

ClientStateStopped::Instance()){

cout << " STOPPED to RUNNING" << endl;

currentState =

ClientStateRunning::Instance();

}

}

void stop(){

if (currentState ==

ClientStateRunning::Instance()){

cout << "RUNNING to STOPPED" << endl;

currentState =

ClientStateStopped::Instance();

}

else if (currentState==

ClientStatePaused::Instance()){

cout << "PAUSED to STOPPED" << endl;

currentState =

ClientStateStopped::Instance();

}

}

void pause(){

if (currentState ==

ClientStateRunning::Instance()){

cout << "RUNNING to PAUSED" << endl;

currentState =

ClientStatePaused::Instance();

}

}

};

Figure 7-13 Replace Data Value with Object Refactoring

Page 86: Thesis Budianto 20299965

74

5. Add Methods. Add new method both on Client and ClientState

+Run()

+Stop()

+Pause()

+ChangeState(in pState)

Client

+ChangeState(in pClient, in pState)

ClientState

+Instance()

-m_State

ClientStateStopped

+Instance()

-m_State

ClientStateRunning

+Instance()

-m_State

ClientStatePaused

currentState

Figure 7-14 Class Diagram after Add Method Refactoring

class ClientState{

...

public:

...

protected:

void ChangeState(Client* pClient, ClientState *pState){

pClient->ChangeState(pState);

}

};

class Client{

...

public:

...

void ChangeState(ControlState *pState){

currentState = pState;

}

};

Figure 7-15 Add Method Refactoring

Page 87: Thesis Budianto 20299965

75

6. Add event function both on the ClientState and the corresponding Inheritance class

+Run()

+Stop()

+Pause()

+ChangeState(in pState)

Client

+ChangeState(in pClient, in pState)

+run()

+stop()

+pause()

ClientState

+Instance()

+run()

-m_State

ClientStateStopped

+Instance()

+stop()

+pause()

-m_State

ClientStateRunning

+Instance()

+run()

+pause()

-m_State

ClientStatePaused

currentState

Figure 7-16 Class Diagram after Move Method Refactoring

class ClientState{

...

public:

...

};

class ClientStateStopped : public ClientState{

...

public:

...

};

class Client{

...

public:

void run(){

if

(currentState==ClientStateStopped::Instance()){

cout << " STOPPED to RUNNING" << endl;

currentState =

ClientStateRunning::Instance();

}

}

};

class ClientState{

public:

virtual void run(){}

...

};

class ClientStateStopped : public ClientState{

...

public:

...

void run(Client* pClient){

cout << " STOPPED to RUNNING" << endl;

ChangeState(pClient,

ClientStateRunning::Instance());

}

};

Class Client{

...

Public:

...

void run(){

currentState->run();

}

};

Figure 7-17 Move Method Refactoring

Page 88: Thesis Budianto 20299965

76

7.5 AutoSim’s StateCharts

In previous section, the refactoring process is discussed. After several refactoring activities is

carried out to both AutoSim Server and AutoSim Client, this section summary the result of

refactoring to state patterns.

7.5.1 State Pattern on AutoSim’s Server

The AutoSim Server consists of two statechart: the application statechart and the simulation

statechart. The application statechart is the core transition state that represents the whole

AutoSim Server application (figure 7-18). The simulation statechart represents the state

transition of the simulation which is the subset of the application statechart.

ControlInActive

ControlSimulationActive

ControlNetworkActiveControlNetworkRunning

ControlSimulationRunning

/ Initialize / Terminate

/ ActivateSimulation

/ ActivateNetwork

/ RunNetwork

/ RunSimulation

/ Stop

Figure 7-18 AutoSim State Transition Diagram

Initially, the state is ControlInActive that represent the starting state of the AutoSim‟s Server.

When the Load button is pressed, the ActivateSimulation event is occurs and the state

transitions to ControlSimulationActive. Moreover this event also triggers simulation state

which is part of the AutoSim. The simulation state transition is described later in the current sub

section.

Page 89: Thesis Budianto 20299965

77

Instance()

RunNetwork()

toString()

ControlNetworkActivate

Instance()

RunSimulation()

toString()

ControlNetworkRunning

Instance()

ActivateNetwork()

toString()

ControlSimulationActive

Instance()

StopControl()

toString()

ControlSimulationRunning

ActivateSimulation()

ActivateNetwork()

RunNetwork()

RunSimulation()

StopControl()

toString()

ChangeState()

ControlState

Instance()

ActivateSimulation()

toString()

ControlInActive

Figure 7-19 State Pattern of AutoSim's Server Application

When the start button is pressed, the ActiveNetwork, RunNetwork, and RunSimulation events

are called in sequence. The Application state pattern as shown in figure 60-19 provides

fundamental state transition implementation for future development such as network exception

handling and simulation reload process.

Figure 7-19 shows the state design pattern of the application statechart that have five states

represents as inheritance classes.

Running

Stopped

Loaded

Paused

/ Initialize

/ Load

/ Run

/ Pause

/ Run

/ Stop / Stop

/ Terminate

Figure 7-20 FSM of Simulation States

Figure 7-20 shows a statechart that represent the simulation state transition. Initially, the state is

Stopped. When the Load button is pressed, the Load event is occurs and the state transitions to

Loaded. When users press the run button, the state Loaded transitions to Running State. From

state Running, a user can pause the simulation that makes the simulation‟s state transitions to

Page 90: Thesis Budianto 20299965

78

Paused or a user can stop the simulation that makes the state transitions to Stopped. When the

application is closed, the whole application will be terminated.

Instance()

Run()

SimulationLoaded

Load()

Run()

Pause()

Stop()

ChangeState()

SimulationState

Instance()

Pause()

Stop()

SimulationRunning

Instance()

Run()

Stop()

SimulationPaused

Load()

Instance()

SimulationStopped

Simulation()

Load()

Run()

Pause()

Stop()

ChangeState()

run()

Simulation

m_pSimulationState

Figure 7-21 State Pattern of Simulation's State

This simulation statechart is realized using state pattern shown in figure 7-21. The key idea of

this implementation is the SimulationState that provides an abstraction for the Simulation‟s

state stored in the m_pSimulationState.

7.5.2 State Pattern on AutoSim Client

ClientStopped

ClientLoaded

ClientRakNetConnected

ClientRakNetEstablihed

ClientIrrllitchRendering

/ Initialize

/ Load

/ Connect

/ StartNetworkThread/ StartGraphicThread

ClientUILoaded

/ LoadUI

/ Stop

/ ReConnect

/ Stop

/ Terminate

Figure 7-22 AutoSim Client's State Transition Diagram

Figure 7-22 shows a statechart that represents the Client Application state transition and Figure

7-23 shows the realization of the client statechart. Initially, the state is ClientStopped. When

Page 91: Thesis Budianto 20299965

79

the Load button is pressed, the Load event is occurs and the state transitions to ClientLoaded.

When users press the run button, the state Loaded transitions to ClientRakNetConnected State.

Before entering the ClientRaknetConnected, the system will validate the network connection.

If the client cannot connect to the server, it will ask the user whether the reconnection process

should be established. The user can stop the connection process and change to stop or continue

connection process.

loadWorld()

quitApplication()

Connect()

startGraphics()

startNetwork()

startUserProgram()

ChangeState()

ClientController

Instance()

Connect()

toString()

ClientLoaded

StartNetworkThread()

Instance()

ClientRakNetConnected

Instance()

StartGraphicThread()

toString()

ClientRakNetEstablished

Load()

Connect()

StartNetworkThread()

StartGraphicThread()

LoadUI()

Stop()

ChangeState()

ClientState

Instance()

Load()

ClientStopped

Stop()

Instance()

ClientUILoaded

LoadUI()

Instance()

ClientIrrlitchRendering

-m_pClientState

1 *

Figure 7-23 State Pattern of AutoSim's Client State Diagram

When a connection is successful, the application‟s state transitions to

RakNetClientEstablished state, which means that the data transfer between client and server

has been established. The system then continues to trigger the StartGraphicThread event that

transitions the current state to ClientIrrlitchRendering state. In this state, the application has

started the rendering the simulation objects to the 3D engine. Lastly, the client application will

trigger the LoadUI to transitions to ClientUILoaded in which the User Program (e.g. Joystick or

GUI), a user interface between user and AutoSim, is loaded.

7.6 Conclusion and Future Works

Intuitively, Simulation system must employ the state transition that represents different stages in

simulation process. Refactoring to state patterns in AutoSim improves the software design and

separates the transition implementation into specified state such that it simplify the AutoSim

simulation complexity.

Page 92: Thesis Budianto 20299965

80

Some state implementation on AutoSim has not been finished. For instance how to replay the

loading state. By replay, we mean that it is possible to reload the simulation objects. Our attempt

to learn about the loading process has not finished such that the state transition has not been

implemented fully particularly in which we cannot change from state to other state for a

particular reason.

As a matter of fact, our works shows that the state pattern has benefit in increasing the software

desing quality. We have provided the underlying design to implement state transition of the

application that need to be extended in the future. For instance, we can improve the state

transition of AutoSim by including the reloading simulation or replaying running simulation.

Page 93: Thesis Budianto 20299965

81

Chapter 8

Refactoring for Creational Pattern

This chapter will present some practical aspect of refactoring to achieve good creational pattern

which is used to manage the objects creation. In addition, an example on creating a builder

pattern, a type of creational pattern that has responsibility for constructing objects, will be

discussed using the real code found in the AutoSim application.

8.1 Overview

AutoSim application has a lot of simulation objects that represent various entities of simulation

or parts of entity such as physical objects, graphics object, and networking objects. Objects, in

object oriented programming, play an important role to represent the entities that build up an

application system. In addition, these objects can be an abstract and a concrete object that

represents the real-world entity.

In AutoSim, objects creational mechanism is managed by creational module. As their number

and types is increasing, as a result of requirement changes, the object creation management is

essential to ensure the independent implementation of objects creational process. Creational

pattern allow us to design this implementation, by separating the construction of simulation

objects from their representation.

Creational pattern is a set of pattern that is used to organize the object creation in an application.

Applying creational pattern also allows us to create a flexible application especially in objects

creation process: when it is created, and how it is created [26].

8.2 AutoSim Objects

The AutoSim have various objects stored in extensible markup language (XML) format, a

general purpose markup language to describe data as structured information. For instance, a

Page 94: Thesis Budianto 20299965

82

world file, an XML file type, is employed to document simulation world properties (e.g. graphic

engine, screen default value, etc).

Using XML to store the information about the simulation properties offers several benefits:

XML provide readable information

Tools support for application developer, such as XML reader library

It provide customizable application by modifying information using a general text editor

To retrieve the data element from the XML file, AutoSim employs the BuildData class. In this

class, the data retrieval is done by reading, extracting, and storing XML data to data collection.

8.2.1 BuildData Class

Figure 8-1 shows the BuildData class diagram that consists of several elements that is essential

to create and store object properties of Simulation. This class provides data services such as

retrieving data from XML file and storing reading data to MAP data collection, a standard

template library (STL) container that stores element in table with index and mapped data.

+BuildData(in h : TiXmlHandle*)

+toXML()

+getType() : string &

+getName() : string &

+getDouble(in tagName : string) : double

+getDouble(in tagName : string, in attribName : string) : double

+getString(in tagName : string) : string &

+getString(in tagName : string, in attribName : string) : string &

+containsDouble(in tagName : string) : bool

+containsDoubleArray(in tagName : string) : bool

+containsString(in tagName : string) : bool

+containsStringArray(in tagName : string) : bool

#fromXML(in h : TiXmlHandle*)

#getAttributeCount(in e : TiXmlElement*) : int

+m_StringMap : map<std::string,std::string>

+m_DoubleMap : map<std::string,double>

+m_MultDoubleMap : map

+m_MultStringMap : map

#m_type : string

#m_name : string

BuildData

Figure 8-1. BuildData Class Diagram

Furthermore, Buildata class also employs four MAP data collections namely, m_StringMap,

m_DoubleMap, m_MultDoubleMap, and m_MultStringMap to store various data type. Both

Page 95: Thesis Budianto 20299965

83

m_StringMap and m_DoubleMap are collections that are used to save the data element with

double and string values respectively. Additionally, the variable m_MultDoubleMap and

m_MultStringMap are collection that used to save a collection of type double and type string

data value respectively. In other word, both m_MultDoubleMap and m_MultStringMap are a

collection of collection.

The advantage of MAP data collection is not only that this allows us to store data elements, it also

provides searching capabilities to retrieve data element using a string index. A client class of

BuildData, given a string index value as function‟s parameter, can use the MAP searching

services by calling either getDouble or getString function, which is used to get single data

element. If the data consists of a collection of data elements (e.g. a collection of double type or a

collection of string type value), a client class must provide two parameters, the string index for

the collection and the string index for a particular element of the collection.

In additional to retrieve data, BuildData also provide fromXML functions to extract the data

elements from XML file and store them to the Map collection. The fromXML function is essential

function that maps the reading data to the MAP collection.

The following XML shows Graphics properties of AutoSim Application.

<Graphics name="graphics">

<Driver type="DIRECT3D9" />

<FullscreenResolution width="1280.0" height="800.0" />

<Fullscreen value="false" />

<AntiAlias value="false" />

<Stencilbuffer value ="false" />

<Vsync value="false" />

<Detail value="100.0" />

<Debug type="OFF" />

<RenderTargetTexture width="512.0" height="512.0"/>

</Graphics>

This element consists of seven elements with their attributes. Some of the elements has only a

value. For instance, Driver Elements has only an attribute type with value DIRECT3D9. Some

others have several attributes such as FullscreenResolution has two attributes width and height.

If the element consist of multiple attributes, the elements and its attributes is stored into

Page 96: Thesis Budianto 20299965

84

collection of collection MAP. Those data values are stored to appropriate data types, double and

string data type.

Index Data Element

Driver DIRECT3D9

FullscreenResolution

Index Data Element

width 1280.0

height 800.0

a

Fullscreen False

AntiAlias False

Stencilbuffer False

Vsync False

Detail 100.0

Debug OFF

RenderTargetTexture

width 512.0

height 512.0

aa

Figure 8-2 The MAP Collection of Graphic tag

In this example, the Graphic tag consists of ten elements as shown in figure 8-2. The element can

be listed as follows:

Collection of Double: Detail

Collection of String: Driver, Fullscreen, antiAlias, Stencilbuffer, Vsync, and Debug

Collection of Collection of Double : FullscreenResolution and RenderTargetTexture

Collection of Collection of String: -

8.3 Refactoring to BuildDataCreator

This section will outline the steps of refactoring the BuildData Class. Table 8-1 shows the

summary of the refactoring activities.

Page 97: Thesis Budianto 20299965

85

Table 8-1 Refactoring Steps for Builder Pattern

Steps. Refactoring Name Description

Step 1 Extract Method Decompose long methods into small piece of methods that

is easy to understand and provides self documenting.

Step 2 Replace Hard-Coded with Enumeration Replace hard-coded statement can give us semantic

meaning to a variable

Step 3 Extract Class Decompose big class that have many functions into

several classes

Step 4 Introduce Builder Pattern Replace the object construction with a Builder Pattern

which is a simple creation pattern.

8.3.1 Extract Method

Martin Fowler state that he commonly works with Extract Method Refactoring when he found a

long methods [20]. This refactoring has aims to extract a particular long method into several

pieces of methods that are more meaningful. By meaningful, we means that the code is self

document such that the methods can provide self explained comments.

BuildData consist of fromXML function which will be the first target of refactoring because this

function is long and have a lot of logical statement that is difficult to understand. By employing

Extract Method several times, we can decompose this function into several simple functions.

Figure 8-3 shows the fragment of fromXML function that is used to extract the XML data values

and stored them into collections. Refactoring this function must consider two types variable

unmodified variable and modified variable

Unmodified Variable, a variable that is modified in fragment of code.

Modified Variable will be modified in the fragment of code.

Page 98: Thesis Budianto 20299965

86

void BuildData::fromXML(TiXmlHandle *h)

{

...

for (...) // For Each Element of XML

{

// count the number of attribute of an

element

int ac = getAttributeCount(pE);

if ( ac == 1 ) // an attributes found

{

double d;

if (...) {

...

} else {

...

}

}

else if ( ac > 1 ) // more than an

attributes

{

...

if (...) {

...

for ( ... )

{

...

}

} else {

...

for (...)

{

...

}

}

}

else

{

...

}

}

}

void BuildData::fromXML(TiXmlHandle *h)

{

for ( ... ) // For Each Element of XML

{

int ac = getAttributeCount(pE);

if ( ac == 1 )

XMLExtractSingleData(pE);

else if ( ac > 1 )

XMLExtractArrayData(pE);

else

{

cerr << "tag doesn't contain

information" << endl;

}

}

}

void

BuildData::XMLExtractSingleData(TiXmlElement

*pE)

{

double d;

if ( ... ) {

...

} else {

...

}

}

void

BuildData::XMLExtractArrayData(TiXmlElement

*pE)

{

double d;

if ( ... ) {

...

for (...)

{

...

}

} else {

...

for (...)

{

...

}

}

}

Figure 8-3 The First Extract Method Refactoring on fromXML function

The Extract Method Refactoring is done by extracting the content of if-statement that is used to

extract xml data value for a data value and a collection of data values. Figure 8-3 shows the side-

by-side the code before and after the first Extract Method.

Page 99: Thesis Budianto 20299965

87

The next Extract Method can be seen in figure 8-4.

void BuildData::fromXML(TiXmlHandle *h)

{

for ( ... ) // For Each Element of XML

{

int ac = getAttributeCount(pE);

if ( ac == 1 )

XMLExtractSingleData(pE);

else if ( ac > 1 )

XMLExtractArrayData(pE);

else

{

cerr << "tag doesn't contain

information" << endl;

}

}

}

void BuildData:: fromXML (TiXmlHandle *h)

{

for ( ... ) // For Each Element of XML

{

XMLExtraction(...);

}

}

void BuildData::XMLExtraction(TiXmlElement *pE)

{

int ac = getAttributeCount(pE);

if ( ac == 1 )

XMLExtractSingleData(pE);

else if ( ac > 1 )

XMLExtractArrayData(pE);

else

{

cerr << "tag doesn't contain

information" << endl;

}

}

Figure 8-4 The Second Extract Method Refactoring on fromXML function

Since the fromXML function has no semantic meaning we move this function‟s content into the

caller function which is the BuildData constructor. This refactoring is known as Inline Method.

BuildData::BuildData(TiXmlHandle *h)

{

fromXML (pE);

}

void BuildData:: fromXML (TiXmlHandle *h)

{

for ( ... ) // For Each Element of XML

{

XMLExtraction(...);

}

}

BuildData::BuildData(TiXmlHandle *h)

{

for ( ... ) // For Each Element of XML

{

XMLExtraction(...);

}

}

Figure 8-5 Inline Method in fromXML function

At this point, we have a simple method for XMLExtraction and BuildData construction.

However we need to continue our method composition activities to BuildData‟s function. From

the first Extract Method refactoring, we have and XMLExtractArrayData function, which has a

long method symptom.

Page 100: Thesis Budianto 20299965

88

void

BuildData::XMLExtractArrayData(TiXmlElement

*pE)

{

double d;

if ( /* is Array of Double */ ) {

...

for ( /* Each Array of double Element */ )

{

...

}

} else {

...

for (/* Each Array of string Element */ )

{

...

}

}

}

void

BuildData::XMLExtractArrayData(TiXmlElement

*pE)

{

double d;

if ( /* is Array of Double */ ) {

XMLGetArrayDouble(pE);

} else {

XMLGetArrayString(pE);

}

}

void BuildData::XMLGetArrayDouble(TiXMLElement

*pE)

{

for (/* Each Array of double Element */ )

{

...

}

}

void BuildData::XMLGetArrayString(pE)

{

for (/* Each Array of string Element */ )

{

...

}

}

Figure 8-6 The Extract Method Refactoring on XMLExtractArrayData function

At this point we have a code that is simpler since each part of function has already defined in

such as way to have clear intents. We continue this refactoring until each function in the class

become relative small. The figure 8-7 shows the growing number of function after the

ExtractMethod finished.

Page 101: Thesis Budianto 20299965

89

BuildData()

getType()

getName()

getDouble()

getDouble()

getString()

getString()

containsDouble()

containsDoubleArray()

containsString()

containsStringArray()

XMLExtraction()

XMLExtractSingleData()

XMLExtractArrayData()

getElementSize()

doubleSetData()

stringSetData()

isGetNumberValueTo()

XMLGetArrayDouble()

XMLGetArrayString()

m_StringMapData

m_DoubleMapData

m_DoubleArrayMapData

m_StringArrayMapData

m_type

m_name

BuildData

Figure 8-7 BuildData Class Diagram after ExtractMethod Refactoring

However some piece of code still difficult to understand as the result of hard-coded program that

needs to be restructured. The next steps involve some effort to add semantic meaning by

replacing hard-coded with enumeration.

8.3.2 Replace Hard-Coded with Enumeration

Replace Hard-Coded with Enumeration refactoring purposes is to add a semantic meaning to

hard-coded data type. This refactoring consists of the following steps:

1. Add Enumeration to the BuildData class to represent three data type for collection for

Single data type (DMT_SINGLE), Collection data type (DMT_MULTIPLE), and undefined data

type (DMT_UNKNOWN).

class BuildData

{

...

private:

enum DMT_DATATYPE{

DMT_UNKNOWN,

DMT_SINGLE,

DMT_MULTIPLE

};

...

};

Page 102: Thesis Budianto 20299965

90

After providing enumeration, we need to change the getAttributesCount function to

return the enumeration data type, temporary variable, and we also need to change the

getAttributes Function.

int BuildData::getAttributeCount(TiXmlElement

*e)

{

if ( /* Element is Valid */ )

return 0;

int count = 0;

for ( /*Each Element */ )

count++;

return count;

}

void BuildData::XMLExtraction(TiXmlElement

*pE)

{

int ac = getAttributeCount(pE);

if ( ac == 1 )

XMLExtractSingleData(pE);

else if (ac > 1) \

XMLExtractArrayData(pE);

else cerr << "tag doesn't contain

information" << endl;

}

int BuildData:: getAttributeCount

(TiXmlElement *e)

{

if (/* Element is Valid */)

return DMT_UNKNOWN;

int count = 0;

for ( /*Each Element */ )

count++;

if ( count == 1)

return DMT_SINGLE;

else if (count > 1 )

return DMT_MULTIPLE;

else return DMT_UNKNOWN;

}

void BuildData::XMLExtraction(TiXmlElement

*pE)

{

int ac = getAttributeCount(pE);

if ( ac == DMT_SINGLE )

XMLExtractSingleData(pE);

else if (ac == DMT_MULTIPLE)

XMLExtractArrayData(pE);

else cerr << "tag doesn't contain

information" << endl;

}

2. Replace Temp with Query

void BuildData::XMLExtraction(TiXmlElement

*pE)

{

int ac = getAttributeCount(pE);

if ( ac == DMT_SINGLE )

XMLExtractSingleData(pE);

else if (ac == DMT_MULTIPLE)

XMLExtractArrayData(pE);

else cerr << "tag doesn't contain

information" << endl;

}

void BuildData::XMLExtraction(TiXmlElement

*pE)

{

if(getAttributeCount(pE) == DMT_SINGLE )

XMLExtractSingleData(pE);

else if (getAttributeCount(pE) ==

DMT_MULTIPLE)

XMLExtractArrayData(pE);

else cerr << "tag doesn't contain

information" << endl;

}

Page 103: Thesis Budianto 20299965

91

3. ExtractMethods

At this point, we need to decompose the getAttributeCount function to have more

semantic meaning after introducing an enumeration values. Thus we again do

ExtractMethods Refactoring.

int BuildData:: getAttributeCount

(TiXmlElement *e)

{

if (/* Element is Valid */)

return DMT_UNKNOWN;

int count = 0;

for ( /*Each Element */ )

count++;

if ( count == 1) return DMT_SINGLE;

else if (count > 1 ) return DMT_MULTIPLE;

else return DMT_UNKNOWN;

}

int BuildData:: getAttributeCount

(TiXmlElement *e)

{

int count = getElementSize(e);

if ( count == 1) return DMT_SINGLE;

else if (count > 1 ) return DMT_MULTIPLE;

else return DMT_UNKNOWN;

}

int BuildData::getElementSize(TiXmlElement

*e)

{

if ( e && 0 == e->ToElement() ) return -1;

int count = 0;

for (/*Each Element */) count++;

return count;

}

4. Rename Method

void BuildData::XMLExtraction(TiXmlElement

*pE)

{

if(getAttributeCount(pE) == DMT_SINGLE )

XMLExtractSingleData(pE);

else if (getAttributeCount(pE) ==

DMT_MULTIPLE)

XMLExtractArrayData(pE);

else cerr << "tag doesn't contain

information" << endl;

}

int BuildData:: getAttributeCount

(TiXmlElement *e)

{

int count = getElementSize(e);

if ( count == 1) return DMT_SINGLE;

else if (count > 1 ) return DMT_MULTIPLE;

else return DMT_UNKNOWN;

}

void BuildData::XMLExtraction(TiXmlElement

*pE)

{

if(getElementType (pE) == DMT_SINGLE )

XMLExtractSingleData(pE);

else if (getElementType (pE) ==

DMT_MULTIPLE)

XMLExtractArrayData(pE);

else cerr << "tag doesn't contain

information" << endl;

}

int BuildData:: getElementType (TiXmlElement

*e)

{

int count = getElementSize(e);

if ( count == 1) return DMT_SINGLE;

else if (count > 1 ) return DMT_MULTIPLE;

else return DMT_UNKNOWN;

}

Page 104: Thesis Budianto 20299965

92

At this point, we already have a piece of code that has better semantic meaning. This code has

several advantages as follows:

1. Simple and Easy to understand.

2. Method has clear intent and responsibilities

3. Self Documenting Method

4. These methods helps us to identify to extract the class

One of the disadvantages is the performance decreasing. Performance is decrease because of a lot

of calling on methods. On the other hand, refactoring indeed make the software slow during the

refactoring, but refactoring makes the software easier to optimized later because the program is

easy to understand and program optimization is easy to be done [20].

8.3.3 Extract Class

The refactoring activities are never ended until we found no way for refactoring. Refactoring is

continuously process that to have a good design. Decomposition can be use to break down a

complicated coding into simple and easy to understand small pieces of coding such as function.

However when the number of functions become enormous, it create a new problem in class

management. The function is simple since it has clear statement but the class become unclear and

complicated since it has a lot of number functions.

Refactoring also deals with organizing the coding into good design. Thus the decomposition

activities must be changed its direction from simplifying the coding into organizing the coding

toward good design which is simple. There are several refactoring catalog can be used to

organizing the coding such as extract class, pull up methods Pull Up constructor Body, and

providing abstraction.

We choose Extract Class refactoring to organize the BuildData class into several classes that

have clear intends. The result is shown in figure 8-8. These four classes, StringMapData,

StringArrayMapData, DoubleMapData, and DoubleArrayMapData, is corresponse to those four

member Map datatype of BuildData class, m_StringMap, m_StringArrayMap, m_DoubleMap,

and m_DoubleArrayMap. Also some methods in BuildData can be simplified and eliminated.

For instance four methods of BuildData, stringSetData, doubleSetData,

XMLGetArrayDouble, XMLGetArrayString can be pull to the wrapper class (see figure 8-9).

Page 105: Thesis Budianto 20299965

93

BuildData()

getType()

getName()

getDouble()

getDouble()

getString()

getString()

containsDouble()

containsDoubleArray()

containsString()

containsStringArray()

getElementType()

getAttributeCount()

XMLExtraction()

XMLExtractSingleData()

XMLExtractArrayData()

isGetNumberValueTo()

getElementSize()

m_StringMapData

m_DoubleMapData

m_DoubleArrayMapData

m_StringArrayMapData

m_type

m_name

BuildData

getDouble()

setData()

containsDoubleArray()

getIteratorStart()

getIteratorEnd()

m_DoubleArrayMap

DoubleArrayMapData

getDouble()

setData()

containsDouble()

m_DoubleMap

DoubleMapData

getString()

setData()

containsString()

getIteratorStart()

getIteratorEnd()

m_StringArrayMap

StringArrayMapData

getString()

setData()

containsString()

getIteratorStart()

getIteratorEnd()

m_StringMap

StringMapData

Figure 8-8 Class Diagram after Extract Class Refactoring

class BuildData

{

...

MAP <STRING, STRING> m_StringMap;

MAP <STRING, double> m_DoubleMap;

MAP <STRING, MAP<STRING, double> *>

m_MultDoubleMap;

MAP <STRING, MAP<STRING, STRING> *>

m_MultStringMap;

...

Public:

...

Double getDouble(tagName);

Double getDouble(tagName, attribName);

STRING getString(tagName);

STRING getString(tagName, attribName);

Void XMLExtractSingleData(...);

Void doubleSetData(...);

void stringSetData(...);

void XMLExtractArrayData(...);

XMLGetArrayDouble(...);

Void XMLGetArrayString(...);

};

class BuildData

{

...

StringMapData m_StringMapData;

DoubleMapData m_DoubleMapData;

DoubleArrayMapData m_DoubleArrayMapData;

StringArrayMapData m_StringArrayMapData;

...

Public:

...

Double getDouble(tagName);

Double getDouble(tagName, attribName);

STRING getString(tagName);

STRING getString(tagName, attribName);

Void XMLExtractSingleData(...);

void XMLExtractArrayData(...);

};

Figure 8-9 BuildData class before and after Extract Class Refactoring

Page 106: Thesis Budianto 20299965

94

8.3.4 Introduce BuildDataCreator

When a Client Class needs to create the BuildData object, it has to call the constructor of the

particular XML elements. For instance, It want to create a BuildData object for Graphics Data

then it has to call a BuildData constructor and pass the appropriate XML element as parameter

that is appropriate to Graphics. Here is the piece of code:

new BuildData(m_pWorld->getTiXMLHandle("Graphics"));

Now suppose a client class needs an array of BuildData Object, it has to call the following

statements:

VECTOR<BuildData *>* ObjectsBuildDataVector = new VECTOR<BuildData *>();

TiXmlHandle *hSection = m_pWorld->getTiXMLHandle("Objects");

for ( TiXmlElement *epElem = hSection->FirstChildElement().ToElement();

epElem != 0; epElem = epElem->NextSiblingElement() )

ObjectsBuildDataVector->push_back( new BuildData( new TiXmlHandle(epElem)

) );

return ObjectsBuildDataVector;

To simplify the creational process, we wrap the BuildData class using the BuildDataCreator

class. This class responsible to construct a complex objects. Figure 8-10 shows the

BuildDataCreator implementation. This class helps us to create an abstraction in creating

BuildData.

+BuildDataCreator(in pWorld : XMLFileLoader*)

+createBDGraphics() : BuildData *

+createBDPhysics() : BuildData *

+createBDObjects() : vector<BuildData*> *

+createBDTerrain() : BuildData *

-m_pWorld : XMLFileLoader *

BuildDataCreator

return new BuildData(

m_pWorld->getTiXMLHandle("Graphics")

);

VECTOR<BuildData *>* ObjectsBuildDataVector =

new VECTOR<BuildData *>();

TiXmlHandle *hSection =

m_pWorld->getTiXMLHandle("Objects");

for (TiXmlElement *epElem =

hSection->FirstChildElement().ToElement();

epElem != 0;

epElem = epElem->NextSiblingElement() )

ObjectsBuildDataVector->push_back(

new BuildData(

new TiXmlHandle(epElem)));

return ObjectsBuildDataVector;

Figure 8-10 BuildDataCreator class

Page 107: Thesis Budianto 20299965

95

8.4 Discussion

8.4.1 Possible extension to creational pattern

We have introduced builder pattern as a creational pattern to AutoSim application. Even though

it simplifies the previous implementation, we found several possible extension to improve the

AutoSim design. The following list shows some possible extension that might be introduced to

the system including:

1. Replace data structure to store the XML data such that improve the searching

performance. This also includes the replacement on string comparison in current MAP

searching with other optimal searching strategies.

2. Replace how the data is retrieved. The current implementation does not change how the

client of BuildData retrieves data. Suppose we can change how to retrieve data directly

to data structure, it would simplify and increase performance.

3. Introduce other creational class, a BuildDataCreator class, that provides an abstraction

to the BuildData creation.

Page 108: Thesis Budianto 20299965

96

Chapter 9

Conclusion

9.1 Summary of Contribution

Our works makes the following contributions:

1. It adds some new graphical user interface features to the AutoSim Clients such as

dashboard, gear number, loading progress, and connection progress.

2. It introduces the automatic code documentation generation using doxygen [57].

3. It introduces the unit testing for testing automation.

4. It introduces exception handler to the AutoSim client particularly to handle the

networking failure. By implementing state pattern on the AutoSim, we can handle any

exceptions thrown.

5. It identifies some important problems in AutoSim project especially in software design

and program comprehension. Most of the fundamental issues of AutoSim are the

software design that hinders the software development.

6. It shows how to perform refactoring to improve the software design. We provide a real

world example of refactoring activities on the AutoSim.

7. Our experiences in refactoring produce several refactoring catalog. This refactoring

catalog includes: Refactoring to State Pattern and Refactoring to introduce type-safe

value.

Page 109: Thesis Budianto 20299965

97

9.2 Lesson Learned

The following list shows some lesson learned from our refactoring activities:

1. Refactoring is difficult to be performed and costly. Given a complicated and legacy code

such as AutoSim. Design is hard, design in object oriented in harder [30]. Refactoring

that has a goal of good software design is the hardest. It has many challenges. The nature

of C++ and the absent of the refactoring reduce the efficiency of refactoring activities.

2. Refactoring is step by step activities. Our experiences show that step-by-step activities of

refactoring will work well. On the other hand, dramatic refactoring will not work. The

behavior of system becomes difficult to be maintained. If the system is too complex to be

understood, it is better for us to start with small step using low level refactoring. Only if

we are really sure about how to perform a big refactoring, we can perform the high level

refactoring directly.

3. Refactoring is continuous activities to improve the software design. Sometimes it is

difficult to determine the absolute design good of refactoring. However by continues

work on small step on refactoring enable us to, at some point when the code shows the

possible design solution, to determine what good design is.

4. Refactoring is an active code review. By active, we mean that refactoring can help us to

understand how the system works. The traditional approach of code review is time costly

and ineffective because the program comprehension is low.

9.3 Future Works

These are several other works that need further investigation:

1. Our activities of refactoring for good software design especially to reduce the singleton

overuse which has not finished should be part of concern in the development of AutoSim.

The singleton overuse mitigation is the fundamental issues to achieve design with high

cohesion and low coupling.

2. Some state transition implementation on AutoSim is not finished. For instance how to

replay the loading state. By replay, we mean that it is possible to reload the simulation

object. Our attempt to learn about the loading process has not finished such that the state

Page 110: Thesis Budianto 20299965

98

transition has not been implemented fully. However some fundamental state transition

has been introduced for further works.

3. The multithreading implementation can produce race condition. The locking mechanism

has not been implemented to ensure the safe multithreading implementation

4. Tools to automate the refactoring are needed to improve the efficiency and the

effectiveness.

5. The refactoring on the Graphic objects and other data structure has not been performed.

Refactoring in these part will allows us to improve the state transition discusses in item

number 2 and also allow us to improves the AutoSim‟s performance.

Page 111: Thesis Budianto 20299965

99

References

1. J.J. Slob, State-of-the-Art Driving Simulators, a Literature Survey, Eindhoven University of

Technology, Department Mechanical Engineering, Control Systems Technology Group,

2008.

2. T. Orme, “Sensory Perception: Test-Driving the Daimler-Benz Simulator,” Motor Trend,

vol. 40, no. 4, 1988, pp. 89;

3. Mitsubishi, “DS-6000 Type II,”

http://www.mpcnet.co.jp/product/simulation/simulator/index.html.

4. T.S. K.YOSHIMOTO, “The History of Research and Development of Driving Simulators

in Japan,” Journal of Mechanical Systems for Transportation and Logistics, vol. 1, no. 2,

2008, pp. 159-169;

5. T. SUETOMI, “The Driving Simulator with Large Amplitude Motion System,” SAE Paper

No. 910113, 1991;

6. Mitsubishi, “Simulator For Education & Training,”

http://www.mpcnet.co.jp/e/e_product/sim/sim02/index.html.

7. Freeman, “The Iowa Driving Simulator: An Implementation and Application Overview,”

SAE Paper 950174, 1994;

8. NASA, “NASA's Mars Exploration Program,”

http://marsprogram.jpl.nasa.gov/missions/log/.

9. T. Sommer, Physics for a 3D Driving Simulator, Thesis, School of Electrical, Electronic,

and Computer Eng., The Univ. of Western Australia, 2008.

10. J.G. Brand, Graphics for a 3D Driving Simulator, Thesis, School of Electrical, Electronic,

and Computer Eng., The Univ. of Western Australia, 2008.

11. D.R. Williams, “Mars Pathfinder Project Information,” 2005;

http://nssdc.gsfc.nasa.gov/planetary/mesur.html.

12. E.D. Dickmanns, Dynamic Vision for Perception and Control of Motion, Springer-Verlag,

2007.

13. J. Schmidhuber, “History of Self-Driving Car,” 2007;

http://www.idsia.ch/~juergen/robotcars.html.

14. ELROB, “ELROB is a trial!,” 2008; http://www.elrob.org/.

15. RoboticsGroup, “M-ELROB, Military European Land-Robot Trial 2008,”

http://www.ee.oulu.fi/research/isg/projects/MELROB.

16. OpenStreetMap, “Open Street Maps,” http://www.openstreetmap.org/.

17. JOSM, “Java OpenStreetMap Editor,” 2009; http://www.openstreetmap.org/.

Page 112: Thesis Budianto 20299965

100

18. P.S. Ruud, “Evaluation of a Vision-based Driver Assistance System in Simulation,” School

of Electrical, Electronic, and Computer Eng., The Univ. of Western Australia, Perth, 2008.

19. N. Dike, “Physics Simulation for an Automotive Simulator,” School of Electrical,

Electronic, and Computer Eng., The Univ. of Western Australia, Perth, 2008.

20. M. Fowler, Refactoring:Improving The Design of Existing Code, Addison Wesley 1999.

21. DesignDebt, “Design Debt,” 2004; http://c2.com/cgi/wiki?DesignDebt.

22. M.L. Meir and F.R. Juan, “Software Evolution and Software Evolution Processes,” Ann.

Softw. Eng., vol. 14, no. 1-4, 2002, pp. 275-309;

23. H.B. Keith, et al., “Software maintenance and evolution: a roadmap,” Proc. Proceedings of

the Conference on The Future of Software Engineering, ACM, 2000.

24. J. Krauskopf, “Elemental Concerns (Software Design),” Potentials, IEEE, vol. 9, no. 1,

1990, pp. 13-15;

25. C. Alexander, et al., A Pattern Language: Towns, Buildings, Construction (Center for

Environmental Structure Series), {Oxford University Press}, 1978.

26. R.H. Erich Gamma, Ralph Johnson, John Vlissides, Design Pattern Elements of Reusable

Object-Oriented Software, Addison Wesley, 1995.

27. E. Freeman, et al., Head First Design Patterns, O'Reilly, 2004.

28. C. Paul, et al., Documenting Software Architectures: Views and Beyond, Pearson

Education, 2002, p. 512.

29. B.R. Donald, Practical Analysis for Refactoring, University of Illinois at Urbana-

Champaign, 1999.

30. F.O. William, “Refactoring object-oriented frameworks,” University of Illinois at Urbana-

Champaign, 1992.

31. T. Mens, et al., “Formalizing refactorings with graph transformations,” Journal of software

maintenance and evolution, vol. 17, no. 4, 2005, pp. 247-276;

32. T. Lance and B. Don, “Evolving Object-Oriented Designs with Refactorings,” Automated

Software Engg., vol. 8, no. 1, 2001, pp. 89-120;

33. G. Alejandra, “Program refactoring in the presence of preprocessor directives,” University

of Illinois at Urbana-Champaign, 2005.

34. D. Danny and J. Ralph, “Automated upgrading of component-based applications,” Proc.

Companion to the 21st ACM SIGPLAN symposium on Object-oriented programming

systems, languages, and applications, ACM, 2006.

35. B. Bart Du, “A study of quality improvements by refactoring,” Universiteit Antwerpen

(Belgium), 2006.

36. R. Don, et al., “A refactoring tool for Smalltalk,” Theor. Pract. Object Syst., vol. 3, no. 4,

1997, pp. 253-263;

37. D. Danny, “JavaRefactor,” 2002; http://plugins.jedit.org/plugins/?JavaRefactor.

38. “xrefactory,” http://www.xref.sk/xrefactory/main.html.

39. Devexpress, “Refactor! Pro,” http://www.devexpress.com/Products/Visual_Studio_Add-

in/Refactoring/.

Page 113: Thesis Budianto 20299965

101

40. M. Steve, Code Complete, Second Edition, Microsoft Press, 2004.

41. M. Feathers, Working Effectively with Legacy Code, Prentice Hall PTR, 2004.

42. K. Joshua, Refactoring to Patterns, Addison Wesley, 2004.

43. TORCS, “Welcome on The TORCS Racing Board,” http://www.berniw.org/trb/index.php.

44. TORCS, “About TORCS,”

http://torcs.sourceforge.net/index.php?name=Sections&op=viewarticle&artid=1.

45. RARS, “Robot Auto Racing Simulator,” http://rars.sourceforge.net/.

46. VAMOS, “About VAMOS,” http://vamos.sourceforge.net/about.html.

47. T. Matsuda, “GRacer - 3D Motor Sports Simulator,” 2002; http://gracer.sourceforge.net/.

48. CarWorld, “Car World,” http://carworld.sourceforge.net/.

49. T1, “T1 Car Racing Simulation,” 2003; http://t1-crs.sourceforge.net/.

50. VDrift, “Welcome to VDrift,” 2009; http://vdrift.net/.

51. RakNet, “RakNet Library,” http://www.jenkinssoftware.com/.

52. Irrlicht, “Irrlicht Graphics Engine,” http://irrlicht.sourceforge.net/.

53. B. Jasmin and S. Mark, C++ GUI Programming with Qt 4, Prentice Hall PTR, 2006.

54. A. Boeing, “Evaluation of real-time physics simulation systems,” School of Electrical,

Electronic and Computer Engineering, the Univ. of Western Australia, 2007.

55. Trolltech, “Qt - A cross-platform application and UI framework,”

http://www.qtsoftware.com/.

56. Y.B. Lee Thomason, Andrew Ellerton “TinyXml Documentation,” 2006;

http://www.grinninglizard.com/tinyxmldocs/index.html.

57. D.V. Heesch, “Doxygen,” 2008-12-12; http://www.stack.nl/~dimitri/doxygen/.

58. cppunit, “cppunit,” 2008; http://cppunit.sourceforge.net.

59. S. King, “Useful enhancements for Visual Studio .NET,” 2003;

http://www.codeproject.com/KB/macros/kingstools.aspx.

60. Fred P. Brooks, Jr., “The Mythical Man-Month (20th Anniversary Edition) by Frederi,”

UNIX review, vol. 14, no. 1, 1996, pp. 66;

61. B. Stroustrup, The C++ Programming Language (Special 3rd Edition), Addison-Wesley

Professional, 2000.

62. F.O. William, “Refactoring C++ Programs,” Lucent Technologies/Bell Labs, 1999.

63. M. Stephens, “Emergent Design vs Early Prototyping,” 2003;

http://www.softwarereality.com/design/early_prototyping.jsp.

64. D. Cavallo, “Emergent design and learning environments: building on indigenous

konwledge,” IBM Syst. J., vol. 39, no. 3-4, 2000, pp. 768-781;

65. H. Yoshiki, et al., “A metric-based approach to identifying refactoring opportunities for

merging code clones in a Java software system,” J. Softw. Maint. Evol., vol. 20, no. 6,

2008, pp. 435-461;

66. H. Leiserson C.E. and Prokop, “A Minicourse on Multithreaded Programming,”

Unpublished, 1998;

Page 114: Thesis Budianto 20299965

102

67. H.C. Richard and T. Kuo-Chung, Modern Multithreading: Implementing, Testing, and

Debugging Multithreaded Java and C++/Pthreads/Win32 Programs, Wiley-Interscience,

2005.

68. J. Bart, et al., “A programming model for concurrent object-oriented programs,” ACM

Trans. Program. Lang. Syst., vol. 31, no. 1, 2008, pp. 1-48;

69. “Debug: Widgets must be created in the GUI-Thread,” 2007; http://lists.trolltech.com/qt-

interest/2007-10/thread00643-0.html.

70. S.T. Andrew, Modern Operating Systems, Prentice Hall Press, 2007, p. 1104.

71. I. Jacobson, Griss, Martin L., Jonsson, P., Software reuse: Architecture, process, and

organization for business success, Addison Wesley Longman, 1997.

72. A.A. Herb Sutter, C++ Coding Standards 101 Rules, Guidleines, and Best Practices,

Addison Wesley, 2007.

73. F.P. Brooks, Jr., “NO SILVER BULLET: ESSENCE AND ACCIDENTS OF SOFTWARE

ENGINEERING,” Computer, vol. 20, no. 4, 1987, pp. 10-19;

74. M.W. Gerald, Perfect Software: And Other Illusions about Testing, Dorset House

Publishing Co., Inc., 2008, p. 200.

75. L. Henry, “The debugging scandal and what to do about it,” Communications of the ACM,

vol. 40, no. 4, 1997, pp. 26;

76. I.C. Daniel, Introduction to computer theory, John Wiley & Sons, Inc., 1986, p. 823.

77. D. Bruce Powel, Doing hard time: developing real-time systems with UML, objects,

frameworks, and patterns, Addison-Wesley Longman Publishing Co., Inc., 1999, p. 749.

78. G. Hassan, Designing Concurrent, Distributed, and Real-Time Applications with Uml,

Addison-Wesley Longman Publishing Co., Inc., 2000, p. 816.