Sie sind auf Seite 1von 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


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

ii
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.

iii
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.

iv
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

v
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

vi
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

vii
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

viii
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

ix
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

x
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

xi
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

xii
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

1
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]

2
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

3
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]

4
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].

5
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.

6
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.

7
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

8
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.
9
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.

10
873  8 February 2008 1050 – 25 August 2008
int main(int argc, char *argv[] int main(int argc, char *argv[])
{
) ...
{ int i = 0;
... while(i < argc)
int i = 0; {
while(i < argc) if(!strcmp(argv[i], "-WorldFile"))
{ {
if(!strcmp(argv[i], "-WorldFile")) i++; δ1 σ1
{ params->worldFile = argv[i];
i++; CTRL->m_WorldFile = argv[i];
guiParams->worldFile = argv[i]; }
} else if(!strcmp(argv[i], "-StepsPerSec"))
else if(!strcmp(argv[i], "-StepsPerSec")) {
{ i++; δ2
i++; params->stepsPerSec =
guiParams->stepsPerSec = σ2
RSSTRING::intFromString(STRING(argv[i]));
}
RSSTRING::intFromString(STRING(argv[i])); else if(!strcmp(argv[i], "-windForce"))
} {
else if(!strcmp(argv[i], "-AutoStart")) i++;
{ params->windForce =
guiParams->autoStart = true; RSSTRING::intFromString(STRING(argv[i]));
} }
i++; else if(!strcmp(argv[i], "-AutoStart"))
} {
... params->autoStart = true;
} } δ3
i++;
}
...
}
1101 – 6 October 2008
void printUsage()
{
std::cout<<"AutoSimServer ..."<<endl
σ3 if(!strcmp(argv[i], "-WorldFile"))
<<endl {
<<"Example"<<endl i++;
<<endl params->worldFile = argv[i];
<<"AutoSimServer-v0.03.exe CTRL->m_WorldFile = argv[i];
..."<<endl }
<<endl else if(!strcmp(argv[i], "-StepsPerSec"))
<<"Description"<<endl {
<<endl i++;
<<"-AutoStart\tThis ..."<<endl params->stepsPerSec =
<<"-Help\t\tDisplay this ..."<<endl RSSTRING::intFromString(STRING(argv[i]));
<<"-StepsPerSec\tPerformance ..." }
<<"-WindForce\tSpecifies ..." else if(!strcmp(argv[i], "-windForce"))
<<"-WorldFile\tIndicates …."<<endl {
<<endl; i++;
} params->windForce =
RSSTRING::intFromString(STRING(argv[i]));
int main(int argc, char *argv[]) }
{ else if(!strcmp(argv[i], "-AutoStart"))
... {
int i = 0; params->autoStart = true; σ5
while(i < argc) σ4 }
{ else{ //Default case
if(!strcmp(argv[i],"-Help") || std::cout<<"Invalid Argument
!strcmp(argv[i],"-h")) Exiting.."<<endl;
{ printUsage();
printUsage(); return 0;
return 0; }
} i++;
}
...
}
Figure 2-1 A Motivation Examples

11
Later the program was evolving by adding new code to program (σ1,2 ) and change existing code
(δ1−3 ) in version 1050. Both addition σ1 and σ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.

12
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.

13
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.

14
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

15
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].

16
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

17
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].

18
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

19
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

20
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

21
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

22
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.

ControllerState

Graphics Irrlitch Library

ClientController

GUI Network RakNet Library


1 1

UserProgram

DataLoader

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].

23
ControllerState

Simulation PAL Library

Controller

GUI
1 1

Network RakNet Library

DataLoader

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].
24
 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

25
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

26
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
27
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.

28
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.

29
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

30
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 = ...;


int m_iArgc = ...;
while(i < m_iArgc) for (int i=1; i < m_iArgc; i++)
{ {
if(...) if(...)
{ {
... ...
} }
i++; ...
... }
}
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 Increment Style Set Up Condition


Location
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

31
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

32
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;}

33
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 ){ if ( value >0 ){


Printf(“error”); if ( value >= 0 && valur <= 10 ) ...
} elseif ( value >=10 && value <= 100) …
else{ }
if ( value >= 0 && valur <= 10 ) ... else{
elseif ( value >=10 && value <= 100) … printf(“error”);
} }

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


2. Replace Case with Comparison operator.

Bool BuildData:: bool BuildData::


containsStringArray(STRING tagName) containsStringArray(STRING tagName)
{ {
if ( m_MultStringMap.find(tagName) != return m_MultStringMap.find(tagName)
m_MultStringMap.end() ) != m_MultStringMap.end();
return true; }
else
return false;
}

Figure 4-8. Simplifying if statement using simple comparison


3. Simplify complicated tests with Booleans

void StartParameters::extractParams() Bool isEqual(str1, str2)


{ {
... return (str1.compare(str2) == 0);
if(!strcmp(m_cArgv[i], "-WorldFile")) }
{
... void StartParameters::extractParams()
} {
else if(!strcmp(m_cArgv[i], "-RobotName")) ...
{
... if(isEqual(m_strArgv[i], "-WorldFile"))
} {
else if(!strcmp(m_cArgv[i], "-UserProgram")) ...
{ }
... else if(isEqual(m_strArgv[i], "-RobotName"))
} {
... ...
} }
else if(isEqual(m_strArgv[i],
"-UserProgram"))
{
...
}
...
}
Figure 4-9. Simplifying if statement using boolean function

34
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 STRING ClientController::getRobotName()


robotName=m_pMainWindow->getRobotName(); {
return m_pMainWindow->getRobotName();
}

robotNameLineEdit->setText(robotName.c_str()); 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() void ExtractParameter()


{ {
... while(i < m_iArgc)
Int i = 1; {
while(i < m_iArgc) if(!strcmp(m_cArgv[i], "-WorldFile"))
{ {
if(!strcmp(m_cArgv[i], "-WorldFile")) i++;
{ m_strWorldFile = m_cArgv[i];
i++; CC->m_WorldFile = m_cArgv[i];
m_strWorldFile = m_cArgv[i]; }
CC->m_WorldFile = m_cArgv[i]; else if(!strcmp(m_cArgv[i], "-RobotName"))
} {
else if(!strcmp(m_cArgv[i], "-RobotName")) i++;
{ m_strRobotName = STRING(m_cArgv[i]);
i++; }
m_strRobotName = STRING(m_cArgv[i]); else if(!strcmp(m_cArgv[i],
} "-UserProgram"))
else if(!strcmp(m_cArgv[i], "-UserProgram")) {
{ i++;
i++; m_strUserProgram = STRING(m_cArgv[i]);
m_strUserProgram = STRING(m_cArgv[i]); }
}
... }

} int main(
{
...
ExtractParameter ();
...
}
Figure 4-11. An Example of Extract Method Refactoring

35
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() int getIntegerValue()


{ {
... ...
Return result; 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-> STRING MainWindow::getRobotName()
text().toAscii().data(); {
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

36
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.

37
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

38
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


GUIThread

m_pGUIThread
m_pNetworkThread
Controller NetworkThread

m_pSimulationThread

SimulationThread

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.

GUIThread

m_pGUIThread
m_pClientNetworkThread
UserProgramThread Controller ClientNetworkThread

m_pUserProgramThread
m_pSimulationThread

GraphicThread

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

39
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.

40
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,

41
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

int argc = 0;
char **argv = 0;
loadGUI()
m_pQApplication =
m_GUIThread->Start()
new QApplication(argc, argv);
m_pMainWindow =
run new MainWindow(m_pMainWindowParams);

m_pMainWindow->show();
m_pQApplication->connect(
m_pQApplication,
Other Calling SIGNAL(lastWindowClosed()),
m_pMainWindow,
Other Calling SLOT(on_actionQuit_activated()));

Other Calling 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.

42
main.cpp Controller GUIThread

m_pQApplication =
new QApplication(argc, argv);
loadGUI()
m_GUIThread->Start() m_pMainWindow =
new MainWindow(m_pMainWindowParams);

run m_pMainWindow->show();
m_pQApplication->connect(
m_pQApplication,
SIGNAL(lastWindowClosed()),
m_pMainWindow,
Other Calling SLOT(on_actionQuit_activated()));

Other Calling m_pQApplication->exec();


Other Calling 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 m_pMainWindow Controller

loadGUI()

show

Other Calling

Other Calling

Other Calling

Figure 5-7. MoveMethod on main.cpp

43
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.

ControlState
ActivateSimulation()
ActivateNetwork()
RunNetwork()
RunSimulation()
StopControl()
ChangeState()

m_pControllerState
m_pNetworkThread
Controller NetworkThread

m_pSimulation

Simulation

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.

SimulationState
Load()
Run()
Pause()
Stop()
toString()
ChangeState()

m_pSimulationState
m_pSimulationThread
Simulation SimulationThread

Figure 5-9. AutoSim Server's Simulation Package

44
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.

45
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

46
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.

47
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
Singleton {
Static member static Singleton instance;
variable public Singleton(){...}
static Singleton instance public:
Singleton() ...
static Singleton *getInstance()
{
static getInstance() Static member
return &instance;
operations() function }
};

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

48
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(); void
ClientWorldBuilder::buildGraphics(BuildData
int i = 1; *BD){
while(i < argc) ...
{ if(params->Fullscreen){
if(!strcmp(argv[i], "-WorldFile")) ...
{ }
i++; else {
CC->pParams->worldfile = argv[i]; params->WindowId =
CC->m_WorldFile = argv[i]; CC->getIrrlichtWindowID();
} params->WindowSize.Width=
... CC->getIrrlichtWindowWidth();
} params->WindowSize.Height =
CC->loadGUI(CC->pParams); CC->getIrrlichtWindowHeight();
}
if(CC->pParams->starttype == 1) ...
CC->loadWorld(); }
else if(CC->pParams->starttype == 2)
{ ...
CC->loadWorld();
CC->startNetwork();
CC->startGraphics();
CC->startUserProgram();
}
}
ClientUserProgramAPI.cpp MainWindow.cpp
namespace ClientUserProgramAPI ...
{ void MainWindow::on_actionLoad_activated(){
int getImageHeight(){ CC->loadWorld(pQProgressDlg);
return ...
CC->getVirtualCameraTextureHeight(); }
} void MainWindow::on_actionRun_activated(){
int getImageWidth(){ CC->startAllThreads();
return }
CC->getVirtualCameraTextureWidth();
} void MainWindow::runSimulationAutomatically()
... {
void unlockImage(){ if (CC->m_pParams->getAutoStart()){
CC->unlockVirtualCameraTexture(); on_actionLoad_activated();
} CC->startAllThreads();
} }
}
Figure 6-2. ClientController class.

49
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.

50
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.

51
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.

52
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

53
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 GraphicThread : public Thread
{
class Graphics public:
{ int Run()
static Graphics *m_pGraphics; {
GRAPHICS->run();
Graphics(){ }
... };
}

public:

static Graphics* getInstance(){


If (m_pGraphics == NULL)
m_pGraphics = new Graphics()
return m_pGraphics;
}
...

};

ClientWorldBuilder class ClientController class


class ClientWorldBuilder : public WorldBuilder class ClientController{
{ ...

public: int* getVirtualCameraTexture(


STRING cameraName){
... ...
clock_t time = clock();
void buildGraphics( BuildData *BD ) GRAPHICS->getRenderedTexture(cameraName);
{ ...
GRAPHICS->init( }
createIrrlichtParams(BD),
static_cast<unsigned int>( ...
BD->getDouble("Detail") };
)
);
}

...

};

54
1. Show Method
 Change the Singleton‟s constructor accessibility from private to public

Graphics Graphics

-Graphics() +Graphics()

class Graphics class Graphics


{ {
static Graphics *m_pGraphics; static Graphics *m_pGraphics;

Graphics(){
... public:
} Graphics(){
public: ...
}
static Graphics* getInstance(){
If (m_pGraphics == NULL) static Graphics* getInstance(){
m_pGraphics = new Graphics() If (m_pGraphics == NULL)
return m_pGraphics; 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 ClientController
-m_Graphics

class ClientController{ class ClientController{


... ...
Graphics *m_pGraphics;
σ1
public:
void ClientController ():
{ public:
... void ClientController ():
} m_pGraphics(new Graphics()) σ2
{
...
} ...
}
...
int* getVirtualCameraTexture(STRING
cameraName){
...
};
}

55
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 class ClientWorldBuilder


{ {
public: public:
... ...
void buildGraphics(...) void buildGraphics( ..., Graphics *pGraphics)
{ {
GRAPHICS->init(
createIrrlichtParams(BD), pGraphics->init(
static_cast<unsigned int>( createIrrlichtParams(BD),
BD->getDouble("Detail") static_cast<unsigned int>(
) BD->getDouble("Detail")
)
); );
} }

... ...

private: 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 class GraphicThread : public Thread


{ {
... Graphics* m_pGraphic;
...
public: public:

int Run()
{
τ1 GraphicThread(Graphics *pGraphics):
m_pGraphic(pGraphics)
GRAPHICS->run(); {
} }
...
}; int Run()
{
pGraphic->run();
}

...
};

56
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
class Graphics {
{
static Graphics *m_pGraphics; Graphics(){
...
Graphics(){ }
...
} ...

...

public: public:

static Graphics* getInstance(){ ...


If (m_pGraphics == NULL)
m_pGraphics = new Graphics() };
return m_pGraphics;
}

...

};

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
57
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.

58
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

59
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.

60
/ Initialize / Terminate

/ Stop Stopped
/ Run

/ Stop
/ Run
Paused Running

/ Pause

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

61
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.

62
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 ).

Transitions

Stopped State &Run() EMPTY

Running State &Pause() &Stop()

Paused State &Run() &Stop()

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

63
void init(State *s){
...
setState(s, LOADING);
};

void Load(State *s, Event *e) {...};


void Run(state *s, Event *e) {...}; σ2
void Stop(State *s, Event *e) {...};

static const Transision trans_table[][] = {


{ (Trasisision)& init, EMPTY },
{ (Trasisision)& Run, (Trasisision)& Pause }, σ1
{ (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)


{ σ3
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.

64
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.

Client m_status
Run() State
Stop() Run()
Pause() Stop()
Pause()
ChangeState()

m_state->Run

Paused Stopped Running


Stop() Run() Pause()
Run() Stop()
Figure 7-5. UML Diagram of State pattern

65
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.

66
void Controller::loadSimulation()
Class Controller:...
{
{
...
α2
... if( ... && m_SimulationStatus == GUI_LOADED)
Public: {
m_SimulationStatus = LOADING;
enum ... β2
{ m_SimulationStatus = LOADED;
INITIALIZED = 1, }
GUI_LOADED = 2,
LOADING = 3,
σ1 }

LOADED = 4, void Controller::runSimulation()


RUNNING = 5, { α3
PAUSED = 6, if(m_SimulationStatus == LOADED)
STOPPING = 7, {
STOPPED = 8,
QUIT = 9
...
m_SimulationStatus = RUNNING;
β3
}; }
else if (m_SimulationStatus == PAUSED) α4
int m_SimulationStatus; σ2 {
... ...
}; m_SimulationStatus = RUNNING;
}
β4
Controller::Controller() {} }

void Controller::init() void Controller::pauseSimulation()


{ {
...
m_SimulationStatus = INITIALIZED;
σ3 if(m_SimulationStatus == RUNNING)
{ α5
} ...
m_SimulationStatus = PAUSED;
void Controller::loadGUI(...) } β5
{ }
if( ... && m_SimulationStatus α1
== INITIALIZED) void Controller::stopSimulation()
{ {
α6
... if ( m_SimulationStatus == RUNNING ||
m_SimulationStatus = GUI_LOADED; β1 m_SimulationStatus == PAUSED )
} {
} ...
m_SimulationStatus = STOPPED; β6
}
}
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

67
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.

68
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.

Client

+Run()
+Stop()
+Pause()
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.

69
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{

};

70
2. Move Field. Move Enumeration Type to new class and change all assignment to
enumeration to ClientState enumeration.

class ClientState{
public:
enum state_type{
STOPPED,
RUNNING,
PAUSED
};

};

class Client{ class Client{


enum state_type{
STOPPED,
RUNNING,
PAUSED
};

state_type currentState; ClientState::state_type currentState;

public: public:
Client(){ Client(){
currentState = STOPPED; currentState = ClientState::STOPPED;
} }

void run(){ void run(){


if (currentState == STOPPED){ if (currentState == ClientState::STOPPED){
cout << "STOPPED to RUNNING\n"; cout << "STOPPED to RUNNING\n";
currentState = RUNNING; currentState = ClientState::RUNNING;
} }
} }

void stop(){ void stop(){


if (currentState == RUNNING){ if (currentState == ClientState::RUNNING){
cout << "RUNNING to STOPPED\n"; cout << "RUNNING to STOPPED\n";
currentState = STOPPED; currentState = ClientState::STOPPED;
} }
else if ( currentState == PAUSED){ else if ( currentState == ClientState::PAUSED){
cout << "PAUSED to STOPPED\n"; cout << "PAUSED to STOPPED\n";
currentState = STOPPED; currentState = ClientState::STOPPED;
} }
} }

void pause(){ void pause(){


if (currentState == RUNNING){ if (currentState == ClientState::RUNNING){
cout << "RUNNING to PAUSED\n"; cout << "RUNNING to PAUSED\n";
currentState = PAUSED; currentState = ClientState::PAUSED;
} }
} }
}; };
Figure 7-9 Move Field Refactoring

71
3. Extract Sub Class. Create new inheritance singleton classes (class
ClientStateStopped, ClientStatePaused, and ClientStateRunning, are extends
from ClientState) that represent every possible states.

ClientState

ClientStateStopped ClientStateRunning ClientStatePaused


-m_State -m_State -m_State
+Instance() +Instance() +Instance()

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

class ClientState{ class ClientStateStopped : public ClientState{


public: static ClientStateStopped m_State;
enum state_type{ public:
STOPPED, static ClientStateStopped* Instance(){
RUNNING, return &m_State;
PAUSED }
}; };

}; 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

72
4. Replace Data Value With Object. Change the enumeration data value (unsafe-type) in
context class to object type (safe-type)

Client
currentState ClientState

+Run()
+Stop()
+Pause()

ClientStateStopped ClientStateRunning ClientStatePaused


-m_State -m_State -m_State
+Instance() +Instance() +Instance()
Figure 7-12 Class diagram after Replace Data Value with Object Refactoring

class Client{ class Client{

ClientState::state_type currentState; ClientState *currentState;

public: public:
Client(){ Client(){
currentState = ClientState::STOPPED; currentState = ClientStateStopped::Instance();
} }

void run(){ void run(){


if (currentState == if (currentState ==
ClientState::STOPPED){ ClientStateStopped::Instance()){
cout << "STOPPED to RUNNING" << endl; cout << " STOPPED to RUNNING" << endl;
currentState = currentState =
ClientState::RUNNING; ClientStateRunning::Instance();
} }
} }

void stop(){ void stop(){


if (currentState == if (currentState ==
ClientState::RUNNING){ ClientStateRunning::Instance()){
cout << "RUNNING to STOPPED" << endl; cout << "RUNNING to STOPPED" << endl;
currentState = currentState =
ClientState::STOPPED; ClientStateStopped::Instance();
} }
else if (currentState == else if (currentState==
ClientState::PAUSED){ ClientStatePaused::Instance()){
cout << "PAUSED to STOPPED" << endl; cout << "PAUSED to STOPPED" << endl;
currentState = currentState =
ClientState::STOPPED; ClientStateStopped::Instance();
} }
} }

void pause(){ void pause(){


if (currentState == if (currentState ==
ClientState::RUNNING){ ClientStateRunning::Instance()){
cout << "RUNNING to PAUSED" << endl; cout << "RUNNING to PAUSED" << endl;
currentState = currentState =
ClientState::PAUSED; ClientStatePaused::Instance();
} }
} }
}; };
Figure 7-13 Replace Data Value with Object Refactoring

73
5. Add Methods. Add new method both on Client and ClientState

Client
currentState ClientState
+Run()
+Stop()
+ChangeState(in pClient, in pState)
+Pause()
+ChangeState(in pState)

ClientStateStopped ClientStateRunning ClientStatePaused


-m_State -m_State -m_State
+Instance() +Instance() +Instance()

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

74
6. Add event function both on the ClientState and the corresponding Inheritance class

Client ClientState
currentState
+Run() +ChangeState(in pClient, in pState)
+Stop() +run()
+Pause() +stop()
+ChangeState(in pState) +pause()

ClientStateStopped ClientStateRunning ClientStatePaused


-m_State -m_State -m_State
+Instance() +Instance() +Instance()
+run() +stop() +run()
+pause() +pause()
Figure 7-16 Class Diagram after Move Method Refactoring

class ClientState{
class ClientState{ public:
... virtual void run(){}
public: ...
... };
};

class ClientStateStopped : public ClientState{ class ClientStateStopped : public ClientState{


... ...
public: public:
... ...
};
void run(Client* pClient){
class Client{ cout << " STOPPED to RUNNING" << endl;
... ChangeState(pClient,
public:
ClientStateRunning::Instance());
void run(){ }
if };
(currentState==ClientStateStopped::Instance()){
cout << " STOPPED to RUNNING" << endl; Class Client{
currentState = ...
ClientStateRunning::Instance(); Public:
} ...
} void run(){
}; currentState->run();
}
};
Figure 7-17 Move Method Refactoring

75
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.

/ Initialize / Terminate

/ Stop / ActivateSimulation
ControlInActive

ControlSimulationRunning ControlSimulationActive

/ ActivateNetwork
/ RunSimulation

ControlNetworkActive
ControlNetworkRunning

/ RunNetwork

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.

76
ControlState
ActivateSimulation()
ActivateNetwork()
RunNetwork()
RunSimulation()
StopControl()
toString()
ChangeState()

ControlNetworkActivate ControlInActive ControlSimulationActive ControlNetworkRunning ControlSimulationRunning


Instance() Instance() Instance() Instance() Instance()
RunNetwork() ActivateSimulation() ActivateNetwork() RunSimulation() StopControl()
toString() toString() toString() toString() toString()

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.

/ Initialize
/ Terminate

Stopped

/ Load

/ Stop / Stop

Loaded

/ Run
/ Run

Running Paused
/ Pause

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

77
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.

Simulation
Simulation() SimulationState
Load() m_pSimulationState Load()
Run() Run()
Pause() Pause()
Stop() Stop()
ChangeState() ChangeState()
run()

SimulationLoaded SimulationRunning SimulationPaused SimulationStopped


Instance() Instance() Instance() Load()
Run() Pause() Run() Instance()
Stop() Stop()

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

/ Initialize
/ Terminate

/ Stop
ClientStopped

/ Load

ClientLoaded
ClientUILoaded
/ Stop
/ Connect
/ LoadUI
/ ReConnect

ClientRakNetConnected
ClientIrrllitchRendering

/ StartNetworkThread
/ StartGraphicThread
ClientRakNetEstablihed

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

78
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.

ClientController ClientState
loadWorld() Load()
quitApplication() -m_pClientState Connect()
Connect() StartNetworkThread()
startGraphics() StartGraphicThread()
startNetwork() 1 * LoadUI()
startUserProgram() Stop()
ChangeState() ChangeState()

ClientLoaded ClientRakNetEstablished
ClientUILoaded
Instance() Instance()
Stop()
Connect() StartGraphicThread()
Instance()
toString() toString()

ClientStopped ClientRakNetConnected ClientIrrlitchRendering


Instance() StartNetworkThread() LoadUI()
Load() Instance() Instance()

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.

79
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.

80
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

81
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
+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(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
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

82
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

83
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.

84
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.

85
void BuildData::fromXML(TiXmlHandle *h) void BuildData::fromXML(TiXmlHandle *h)
{ {
... for ( ... ) // For Each Element of XML
for (...) // For Each Element of XML {
{ int ac = getAttributeCount(pE);
// count the number of attribute of an if ( ac == 1 )
element XMLExtractSingleData(pE);
int ac = getAttributeCount(pE); else if ( ac > 1 )
if ( ac == 1 ) // an attributes found XMLExtractArrayData(pE);
{ else
double d; {
if (...) { cerr << "tag doesn't contain
... information" << endl;
} else { }
... }
} }
}
else if ( ac > 1 ) // more than an
attributes void
{ BuildData::XMLExtractSingleData(TiXmlElement
... *pE)
if (...) { {
... double d;
for ( ... ) if ( ... ) {
{ ...
... } else {
} ...
} else { }
... }
for (...)
{
... void
} BuildData::XMLExtractArrayData(TiXmlElement
} *pE)
} {
else 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.

86
The next Extract Method can be seen in figure 8-4.

void BuildData:: fromXML (TiXmlHandle *h)


void BuildData::fromXML(TiXmlHandle *h) {
{ for ( ... ) // For Each Element of XML
for ( ... ) // For Each Element of XML {
{ XMLExtraction(...);
int ac = getAttributeCount(pE); }
if ( ac == 1 ) }
XMLExtractSingleData(pE);
else if ( ac > 1 )
XMLExtractArrayData(pE); void BuildData::XMLExtraction(TiXmlElement *pE)
else {
{ int ac = getAttributeCount(pE);
cerr << "tag doesn't contain if ( ac == 1 )
information" << endl; 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)
BuildData::BuildData(TiXmlHandle *h) {
{ for ( ... ) // For Each Element of XML
fromXML (pE); {
} XMLExtraction(...);
}
}
void BuildData:: fromXML (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.

87
void void
BuildData::XMLExtractArrayData(TiXmlElement BuildData::XMLExtractArrayData(TiXmlElement
*pE) *pE)
{ {
double d; double d;
if ( /* is Array of Double */ ) { if ( /* is Array of Double */ ) {
... XMLGetArrayDouble(pE);
for ( /* Each Array of double Element */ ) } else {
{ XMLGetArrayString(pE);
... }
} }
} else {
... void BuildData::XMLGetArrayDouble(TiXMLElement
for (/* Each Array of string Element */ ) *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.

88
BuildData
m_StringMapData
m_DoubleMapData
m_DoubleArrayMapData
m_StringArrayMapData
m_type
m_name
BuildData()
getType()
getName()
getDouble()
getDouble()
getString()
getString()
containsDouble()
containsDoubleArray()
containsString()
containsStringArray()
XMLExtraction()
XMLExtractSingleData()
XMLExtractArrayData()
getElementSize()
doubleSetData()
stringSetData()
isGetNumberValueTo()
XMLGetArrayDouble()
XMLGetArrayString()
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
};
...
};

89
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 int BuildData:: getAttributeCount


*e) (TiXmlElement *e)
{ {
if ( /* Element is Valid */ ) if (/* Element is Valid */)
return 0; return DMT_UNKNOWN;

int count = 0; int count = 0;


for ( /*Each Element */ )
count++; for ( /*Each Element */ )
return count; count++;
}
if ( count == 1)
return DMT_SINGLE;
void BuildData::XMLExtraction(TiXmlElement else if (count > 1 )
*pE) return DMT_MULTIPLE;
{ else return DMT_UNKNOWN;
int ac = getAttributeCount(pE); }
if ( ac == 1 )
XMLExtractSingleData(pE); void BuildData::XMLExtraction(TiXmlElement
else if (ac > 1) \ *pE)
XMLExtractArrayData(pE); {
else cerr << "tag doesn't contain int ac = getAttributeCount(pE);
information" << endl; 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 void BuildData::XMLExtraction(TiXmlElement


*pE) *pE)
{ {
int ac = getAttributeCount(pE); if(getAttributeCount(pE) == DMT_SINGLE )
if ( ac == DMT_SINGLE ) XMLExtractSingleData(pE);
XMLExtractSingleData(pE); else if (getAttributeCount(pE) ==
else if (ac == DMT_MULTIPLE) DMT_MULTIPLE)
XMLExtractArrayData(pE); XMLExtractArrayData(pE);
else cerr << "tag doesn't contain else cerr << "tag doesn't contain
information" << endl; information" << endl;
} }

90
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 int BuildData:: getAttributeCount


(TiXmlElement *e) (TiXmlElement *e)
{ {
if (/* Element is Valid */)
return DMT_UNKNOWN; int count = getElementSize(e);

int count = 0; if ( count == 1) return DMT_SINGLE;


for ( /*Each Element */ ) else if (count > 1 ) return DMT_MULTIPLE;
count++; else return DMT_UNKNOWN;
}
if ( count == 1) return DMT_SINGLE;
else if (count > 1 ) return DMT_MULTIPLE; int BuildData::getElementSize(TiXmlElement
else return DMT_UNKNOWN; *e)
} {
if ( e && 0 == e->ToElement() ) return -1;
int count = 0;
for (/*Each Element */) count++;
return count;
}

4. Rename Method

void BuildData::XMLExtraction(TiXmlElement void BuildData::XMLExtraction(TiXmlElement


*pE) *pE)
{ {
if(getAttributeCount(pE) == DMT_SINGLE ) if(getElementType (pE) == DMT_SINGLE )
XMLExtractSingleData(pE); XMLExtractSingleData(pE);
else if (getAttributeCount(pE) == else if (getElementType (pE) ==
DMT_MULTIPLE) DMT_MULTIPLE)
XMLExtractArrayData(pE); XMLExtractArrayData(pE);
else cerr << "tag doesn't contain else cerr << "tag doesn't contain
information" << endl; information" << endl;
} }

int BuildData:: getAttributeCount int BuildData:: getElementType (TiXmlElement


(TiXmlElement *e) *e)
{ {

int count = getElementSize(e); int count = getElementSize(e);

if ( count == 1) return DMT_SINGLE; if ( count == 1) return DMT_SINGLE;


else if (count > 1 ) return DMT_MULTIPLE; else if (count > 1 ) return DMT_MULTIPLE;
else return DMT_UNKNOWN; else return DMT_UNKNOWN;
} }

91
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).
92
BuildData
StringMapData m_StringMapData
m_DoubleMapData
m_StringMap
m_DoubleArrayMapData
getString() m_StringArrayMapData DoubleArrayMapData
setData() m_type
containsString() m_DoubleArrayMap
m_name
getIteratorStart() BuildData() getDouble()
getIteratorEnd() getType() setData()
getName() containsDoubleArray()
getDouble() getIteratorStart()
getDouble() getIteratorEnd()
getString()
getString()
containsDouble()
containsDoubleArray() StringArrayMapData
DoubleMapData containsString()
containsStringArray() m_StringArrayMap
m_DoubleMap
getElementType() getString()
getDouble() getAttributeCount() setData()
setData() XMLExtraction() containsString()
containsDouble() XMLExtractSingleData() getIteratorStart()
XMLExtractArrayData() getIteratorEnd()
isGetNumberValueTo()
getElementSize()

Figure 8-8 Class Diagram after Extract Class Refactoring


class BuildData class BuildData
{ {
... ...
MAP <STRING, STRING> m_StringMap; StringMapData m_StringMapData;
MAP <STRING, double> m_DoubleMap; DoubleMapData m_DoubleMapData;
MAP <STRING, MAP<STRING, double> *> DoubleArrayMapData m_DoubleArrayMapData;
m_MultDoubleMap; StringArrayMapData m_StringArrayMapData;
MAP <STRING, MAP<STRING, STRING> *> ...
m_MultStringMap; Public:
... ...
Public: Double getDouble(tagName);
... Double getDouble(tagName, attribName);
Double getDouble(tagName); STRING getString(tagName);
Double getDouble(tagName, attribName); STRING getString(tagName, attribName);
STRING getString(tagName); Void XMLExtractSingleData(...);
STRING getString(tagName, attribName); void XMLExtractArrayData(...);
Void XMLExtractSingleData(...); };
Void doubleSetData(...);
void stringSetData(...);
void XMLExtractArrayData(...);
XMLGetArrayDouble(...);
Void XMLGetArrayString(...);
};

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

93
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.

return new BuildData(


m_pWorld->getTiXMLHandle("Graphics")
);

BuildDataCreator
VECTOR<BuildData *>* ObjectsBuildDataVector =
-m_pWorld : XMLFileLoader *
new VECTOR<BuildData *>();
+BuildDataCreator(in pWorld : XMLFileLoader*)
+createBDGraphics() : BuildData *
TiXmlHandle *hSection =
+createBDPhysics() : BuildData * m_pWorld->getTiXMLHandle("Objects");
+createBDObjects() : vector<BuildData*> * for (TiXmlElement *epElem =
+createBDTerrain() : BuildData * hSection->FirstChildElement().ToElement();
epElem != 0;
epElem = epElem->NextSiblingElement() )
ObjectsBuildDataVector->push_back(
new BuildData(
new TiXmlHandle(epElem)));

return ObjectsBuildDataVector;

Figure 8-10 BuildDataCreator class

94
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.

95
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.

96
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

97
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.

98
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/.

99
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/.

100
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;

101
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.

102

Das könnte Ihnen auch gefallen