Understanding Source Code Differences by Separating Refactoring Effects
1. UNDERSTANDING SOURCE CODE DIFFERENCES
BY SEPARATING REFACTORING EFFECTS
*Sirinut Thangthumachit, Shinpei Hayashi, Motoshi Saeki
Tokyo Institute of Technology, Japan
2. 2
Motivation
• Source code differences
• Comparing and reading the differences of old and new
versions of source code
• Refactoring complicates differences[1,2]
• Refactoring: the technique to restructuring source code
that will not change program’s behavior
• makes large amount of differences
• shows same differences multiple times
• hides other changes’ differences
[1] K. Prete et al, “Template-based reconstruction of complex refactorings” ,
ICSM2010.
[2] Weißgerber et al, “Identifying refactoring from source-code changes” ,
ASE2006.
4. Example
4
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCreator creator)
throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary fix for thread
hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
protected void setupThread(WorkerThread
threadconfigureTask(AbstractRxTask task) {
synchronized (threadtask) {
thread.setPooltask.setTaskPool(this);
thread.setName(thread// task.setName(task.getClass
().getName() + "[" + inc() + "]");
thread// task.setDaemon(true);
thread// task.setPriority(Thread.MAX_PRIORITY);
thread// task.start();
try {thread.wait(500); }catch ( InterruptedException x ) {}
}
}
Apache Tomcat 6.0.4 – 6.0.5
5. Example
5
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCr
eator creator) throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary
fix for thread hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
6. Example
6
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCr
eator creator) throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary
fix for thread hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
Delete ‘for-loop’
7. Example
7
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCr
eator creator) throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary
fix for thread hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
Class ‘ThreadPool’ → ‘RxTaskPool’
Delete ‘for-loop’
8. Example
8
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCr
eator creator) throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary
fix for thread hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
Class ‘ThreadPool’ → ‘RxTaskPool’
Parameter ‘maxThreads’ → ‘maxTasks’
Delete ‘for-loop’
9. Example
9
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCr
eator creator) throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary
fix for thread hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
Class ‘ThreadPool’ → ‘RxTaskPool’
Parameter ‘maxThreads’ → ‘maxTasks’
4 more refactorings
Delete ‘for-loop’
10. Example
10
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCr
eator creator) throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary
fix for thread hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
Delete ‘for-loop’
Refactorings
11. Example
11
public ThreadPool (int maxThreads, int minThreads,
ThreadCreatorRxTaskPool (int maxTasks, int minTasks, TaskCreator creator)
throws Exception {
// fill up the pool with worker threads
this.maxThreads = maxThreadsmaxTasks = maxTasks;
this.minThreads = minThreadsminTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxThreads; i++) { //temporary fix for thread
hand off problem
WorkerThread thread = creator.getWorkerThread();
setupThread(thread);
idle.add (thread);
}
}
protected void setupThread(WorkerThread
threadconfigureTask(AbstractRxTask task) {
synchronized (threadtask) {
thread.setPooltask.setTaskPool(this);
thread.setName(thread// task.setName(task.getClass
().getName() + "[" + inc() + "]");
thread// task.setDaemon(true);
thread// task.setPriority(Thread.MAX_PRIORITY);
thread// task.start();
try {thread.wait(500); }catch ( InterruptedException x ) {}
}
}
Apache Tomcat 6.0.4 – 6.0.5
18. 18
Basic Ideas
• Developer knows refactoring well
• ‘ThreadPool’ was renamed to ‘RxTaskPool’
• → It is no need to read refactorings in source code
differences
• ThreadPoolRxTaskPool
• → Extract & Eliminate Refactorings
• Source code differences without refactoring
• → Show refactoring information to user
19. Separating Refactorings
19
public RxTaskPool (int maxTasks, int minTasks, TaskCreator creator)
throws Exception {
// fill up the pool with worker threads
this.maxTasks = maxTasks;
this.minTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxTasks; i++) { //temporary fix for thread hand
off problem
AbstractRxTask thread = creator.createRxTask();
configureTask(thread);
idle.add (thread);
}
}
protected void configureTask(AbstractRxTask task) {
synchronized (task) {
task.setTaskPool(this);
// task.setName(task.getClass().getName() + "[" + inc() + "]");
// task.setDaemon(true);
// task.setPriority(Thread.MAX_PRIORITY);
// task.start();
try {Thread.wait(500); }catch ( InterruptedException x ) {}
}
}
‘ThreadPool’ → ‘RxTaskPool’
‘setupThread’ → ‘configureTask’
and 8 more.
20. Separating Refactorings
20
public ThreadPool (int maxThreads, int minThre
public RxTaskPool (int maxTasks, ThreadCreatorRxTaskPool (int maxTasks, int minTa
int minTasks, TaskCreator creator)
throws Exception {
throws Exception {
// fill up the pool with worker threads
up the pool with worker threads
// fill
this.maxTasks = maxTasks;
this.maxThreads = maxThreadsmaxTasks = maxTa
this.minTasks = minTasks;
this.minThreads = minThreadsminTasks = minTa
this.creator = creator;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxTasks; i++) for//temporary fix <for thread hand
{ (int i = 0; i maxThreads; i++) { //tem
off problem
hand off problem
AbstractRxTask thread = creator.createRxTask();
WorkerThread thread = creator.getWorkerThr
configureTask(thread);
setupThread(thread);
idle.add (thread);
idle.add (thread);
}
}
}
}
protected void configureTask(AbstractRxTask task) setupThread(WorkerThread
protected void {
synchronized (task) {
threadconfigureTask(AbstractRxTask task) {
task.setTaskPool(this);
synchronized (threadtask) {
// task.setName(task.getClass().getName() + "[" + inc() + "]");
thread.setPooltask.setTaskPool(this);
// task.setDaemon(true);
thread.setName(thread// task.se
// task.setPriority(Thread.MAX_PRIORITY);
+ inc() + "]");
().getName() + "["
// task.start();
thread// task.setDaemon(true);
try {Thread.wait(500); }catch ( InterruptedException xtask.setPriority(Threa
thread// ) {}
}
thread// task.start();
}
try {thread.wait(500); }catch ( Interrupte
‘ThreadPool’ → ‘RxTaskPool’
}
Without Refactorings
} With Refactorings
‘setupThread’ → ‘configureTask’
and 8 more.
21. Separating Refactorings
21
public RxTaskPool (int maxTasks, int minTasks, TaskCreator creator)
throws Exception {
// fill up the pool with worker threads
this.maxTasks = maxTasks;
this.minTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxTasks; i++) { //temporary fix for thread hand
off problem
AbstractRxTask thread = creator.createRxTask();
configureTask(thread);
idle.add (thread);
}
}
protected void configureTask(AbstractRxTask task) {
Delete 'for-loop'
synchronized (task) {
task.setTaskPool(this);
// task.setName(task.getClass().getName() + "[" + inc() + "]");
// task.setDaemon(true);
// task.setPriority(Thread.MAX_PRIORITY);
// task.start();
try {Thread.wait(500); }catch ( InterruptedException x ) {}
}
}
‘ThreadPool’ → ‘RxTaskPool’
‘setupThread’ → ‘configureTask’
and 8 more.
22. Separating Refactorings
22
public RxTaskPool (int maxTasks, int minTasks, TaskCreator creator)
throws Exception {
// fill up the pool with worker threads
this.maxTasks = maxTasks;
this.minTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxTasks; i++) { //temporary fix for thread hand
off problem
AbstractRxTask thread = creator.createRxTask();
configureTask(thread);
idle.add (thread);
}
}
protected void configureTask(AbstractRxTask task) {
Delete 'for-loop'
synchronized (task) {
task.setTaskPool(this);
Comment out
// task.setName(task.getClass().getName() + "[" + inc() + "]");
// task.setDaemon(true);
// task.setPriority(Thread.MAX_PRIORITY);
// task.start();
try {Thread.wait(500); }catch ( InterruptedException x ) {}
}
}
‘ThreadPool’ → ‘RxTaskPool’
‘setupThread’ → ‘configureTask’
and 8 more.
23. Separating Refactorings
23
public RxTaskPool (int maxTasks, int minTasks, TaskCreator creator)
throws Exception {
// fill up the pool with worker threads
this.maxTasks = maxTasks;
this.minTasks = minTasks;
this.creator = creator;
//for (int i = 0; i < minThreads; i++) {
for (int i = 0; i < maxTasks; i++) { //temporary fix for thread hand
off problem
AbstractRxTask thread = creator.createRxTask();
configureTask(thread);
idle.add (thread);
}
}
protected void configureTask(AbstractRxTask task) {
Delete 'for-loop'
synchronized (task) {
task.setTaskPool(this);
Comment out
// task.setName(task.getClass().getName() + "[" + inc() + "]");
// task.setDaemon(true);
Delete 'try&catch'
// task.setPriority(Thread.MAX_PRIORITY);
// task.start();
try {Thread.wait(500); }catch ( InterruptedException x ) {}
}
}
‘ThreadPool’ → ‘RxTaskPool’
‘setupThread’ → ‘configureTask’
and 8 more.
24. 24
Old
Old version of source code
New version of source code
Approach
New
Source code differences
refactoring
Old
New
Old
Modified
New
25. 25
Overview of the proposed technique
New Ver.
Separating Comparing
Old Ver.
Refactorings
Source Code
Inputs
Source Code
Differences
without Refactoring
Ordered List
of Refactorings
Outputs
26. 26
Overview of the proposed technique
New Ver.
Input 2
Extracting
Old Ver.
Refactorings
Input 1
Ordered List of
Refactorings
Applying " Modified
Refactorings
Ver.
Output 2
Output 1
27. 27
Overview of the proposed technique
New
Method" Comparing
Old
Package
File
Class
Local
Source Code
Field
Inputs
Source Code
Differences
without Refactoring
Ordered List
of Refactorings
Outputs
29. Evaluations
• Application on OSS
• Can extracted refactorings be applied?
• Can separating refactorings reduce the amount of source
code differences?
• Human Subject Study
• With approach, can subjects understand more changes in
the same limited time?
• Does the approach satisfy subjects?
29
30. Evaluation 1 (Application on OSS)
• Target projects
• OW2 Carol 1.0.1-1.8.5 (30 pairs)
• Result
• Tool found refactorings in 5 pairs
• 1.0.1–1.3.0, 1.4.0–1.4.2, 1.5.2–1.5.3, 1.5.6–1.5.7, 1.5.8–1.6.
• Refactorings application
Found
Successfully applied
Detected Refactorings 21
18
False 5
2
True
16
16
30
• → All real refactorings were applied successfully
31. Evaluation 1
• The amount of source code differences
Changed lines
WO: without approach 18,721 (100%)
A: with approach
14,624 (78.12%)
WO - A
4,097 (21.88%)
→ Approach reduced more than 21%
• Can extracted refactorings be applied?
• → Yes
• Can separating refactorings reduce the amount of source
code differences?
31
• → Yes
32. Evaluation 2 (Human Subject)
• Procedure
• Let subjects read the source code differences with and
without our approach.
• Ask them to answer what was changed between the
versions
• Evaluate by time and changes found
• Target Projects
• OW2 Carol 1.5.6-1.5.7
• Apache Tomcat 6.0.4-6.0.5
32
33. 33
Evaluation 2
• Subjects
Subjects
A
B
C
D
Carol
Approach
w/o Approach
Approach
w/o approach
Tomcat
w/o Approach
Approach
w/o Approach
Approach
• Result
Changes Time Efficiency
found
(minute)
(changes found/ time)
w/o Approach
28.3
112.75
0.25 (100%)
average
Approach
39.25
120
0.33 (132%)
• → Approach made 32% higher efficiency
34. 34
Evaluation 2
• Questionnaires
• All subjects agreed that our approach is useful
• Especially, renaming class.
• With approach, can subjects understand more changes in
the same limited time?
• → Yes
• Does the approach satisfy subjects?
• → Yes
35. Conclusion
• Understanding source code differences by
separating refactorings effects
• Separating refactorings
• Implemented supporting tool
• Rename + Move refactorings
• Evaluations
• Approach is applicable to OSS
• Separating refactorings helps understanding differences
• Future Works
• Better tool
• Support more refactoring types 35