Upload
shinpei-hayashi
View
2.467
Download
3
Tags:
Embed Size (px)
Citation preview
UNDERSTANDING SOURCE CODE DIFFERENCES BY SEPARATING REFACTORING EFFECTS
*Sirinut Thangthumachit, Shinpei Hayashi, Motoshi Saeki Tokyo Institute of Technology, Japan
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
2
[1] K. Prete et al, “Template-based reconstruction of complex refactorings” , ICSM2010. [2] Weißgerber et al, “Identifying refactoring from source-code changes” , ASE2006.
Apache Tomcat 6.0.4 – 6.0.5
4 Example
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 ) {} } }
5 Example
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
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
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’
Class ‘ThreadPool’ → ‘RxTaskPool’
8 Example
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’
Class ‘ThreadPool’ → ‘RxTaskPool’ Parameter ‘maxThreads’ → ‘maxTasks’
9 Example
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’
Class ‘ThreadPool’ → ‘RxTaskPool’ Parameter ‘maxThreads’ → ‘maxTasks’
4 more refactorings
10 Example
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
Apache Tomcat 6.0.4 – 6.0.5
11 Example
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 ) {} } }
12 Example
protected void setupThread(WorkerThread threadconfigure Task(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 ) {} } }
13 Example
protected void setupThread(WorkerThread threadconfigure Task(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 ) {} } }
Comment Out
14 Example
protected void setupThread(WorkerThread threadconfigure Task(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 ) {} } }
Comment Out
Method ‘setupThread’ → ‘configureTask’
15 Example
protected void setupThread(WorkerThread threadconfigure Task(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 ) {} } }
Comment Out
Method ‘setupThread’ → ‘configureTask’ Parameter ‘thread’ → ‘task’
16 Example
protected void setupThread(WorkerThread threadconfigure Task(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 ) {} } }
Comment Out
Method ‘setupThread’ → ‘configureTask’ Parameter ‘thread’ → ‘task’
2 more refactorings
17 Example
protected void setupThread(WorkerThread threadconfigure Task(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 ) {} } }
Comment Out Refactorings
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
18
Separating Refactorings 19
‘ThreadPool’ → ‘RxTaskPool’ ‘setupThread’ → ‘configureTask’ and 8 more.
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 ) {} } }
Separating Refactorings 20
‘ThreadPool’ → ‘RxTaskPool’ ‘setupThread’ → ‘configureTask’ and 8 more.
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 ) {} } }
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 ) {} } } With Refactorings Without Refactorings
Separating Refactorings 21
‘ThreadPool’ → ‘RxTaskPool’ ‘setupThread’ → ‘configureTask’ and 8 more.
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 ) {} } }
Delete 'for-loop'
Separating Refactorings 22
‘ThreadPool’ → ‘RxTaskPool’ ‘setupThread’ → ‘configureTask’ and 8 more.
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 ) {} } }
Delete 'for-loop' Comment out
Separating Refactorings 23
‘ThreadPool’ → ‘RxTaskPool’ ‘setupThread’ → ‘configureTask’ and 8 more.
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 ) {} } }
Delete 'for-loop' Comment out
Delete 'try&catch'
Approach
24
Old New Modified
Old New
Old version of source code New version of source code Source code differences refactoring
New
Old
Overview of the proposed technique
25
Comparing Source Code
Ordered Listof Refactorings
Source Code Differences
without Refactoring
Outputs
New Ver.
Old Ver.
Inputs
Separating Refactorings
Overview of the proposed technique
26
Extracting Refactorings
Ordered List of Refactorings
Output 1
Applying "Refactorings
Output 2
Old Ver.
Input 1
New Ver. Input 2
ModifiedVer.
Overview of the proposed technique
27
Comparing Source Code
Ordered Listof Refactorings
Source Code Differences
without Refactoring
Outputs
New
Old
Inputs
File Class Method"
Field Local Package
28
Supporting tool
Extraction Application
Rename packages, files, classes, interfaces,
enums, methods all elements
Move files, methods files, methods
Extract - methods
• Refactoring Extraction • Automatical extraction • External Input
• Refactoring Application • Automatically apply by using Eclipse Refactoring
Browser
• 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
Evaluations
• 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
• → All real refactorings were applied successfully 30
Evaluation 1 (Application on OSS)
Found Successfully applied
Detected Refactorings 21 18
False 5 2
True 16 16
• The amount of source code differences
→ Approach reduced more than 21% • Can extracted refactorings be applied?
• → Yes • Can separating refactorings reduce the amount of source
code differences? • → Yes
31
Changed lines
WO: without approach 18,721 (100%) A: with approach 14,624 (78.12%) WO - A 4,097 (21.88%)
Evaluation 1
• 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
Evaluation 2 (Human Subject)
• Subjects
• Result
• → Approach made 32% higher efficiency
Changes found
Time (minute)
Efficiency (changes found/ time)
average w/o Approach 28.3 112.75 0.25 (100%)
Approach 39.25 120 0.33 (132%)
Evaluation 2
Subjects A B C D Carol Approach w/o Approach Approach w/o approach
Tomcat w/o Approach Approach w/o Approach Approach
33
• 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
Evaluation 2
34
• 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
Conclusion