Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Understanding Source Code Differences by Separating Refactoring Effects

14 238 vues

Publié le

Presented at APSEC 2011 by Sirinut Thangthumachit
http://dx.doi.org/10.1109/APSEC.2011.47

Publié dans : Technologie

Understanding Source Code Differences by Separating Refactoring Effects

  1. 1. UNDERSTANDING SOURCE CODE DIFFERENCES BY SEPARATING REFACTORING EFFECTS *Sirinut Thangthumachit, Shinpei Hayashi, Motoshi Saeki Tokyo Institute of Technology, Japan
  2. 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.
  3. 3. 3 Source Code Differences public ThreadPoolRxTaskPool (int … RED: deleted code BLUE: added code
  4. 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. 5. Example 5 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++) { //temporaryfix for thread hand off problem WorkerThread thread = creator.getWorkerThread(); setupThread(thread); idle.add (thread); } }
  6. 6. Example 6 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++) { //temporaryfix for thread hand off problem WorkerThread thread = creator.getWorkerThread(); setupThread(thread); idle.add (thread); } } Delete ‘for-loop’
  7. 7. Example 7 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++) { //temporaryfix for thread hand off problem WorkerThread thread = creator.getWorkerThread(); setupThread(thread); idle.add (thread); } } Class ‘ThreadPool’ → ‘RxTaskPool’ Delete ‘for-loop’
  8. 8. Example 8 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++) { //temporaryfix for thread hand off problem WorkerThread thread = creator.getWorkerThread(); setupThread(thread); idle.add (thread); } } Class ‘ThreadPool’ → ‘RxTaskPool’ Parameter ‘maxThreads’ → ‘maxTasks’ Delete ‘for-loop’
  9. 9. Example 9 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++) { //temporaryfix 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. 10. Example 10 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++) { //temporaryfix for thread hand off problem WorkerThread thread = creator.getWorkerThread(); setupThread(thread); idle.add (thread); } } Delete ‘for-loop’ Refactorings
  11. 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
  12. 12. Example 12 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 ) } }
  13. 13. Example 13 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 ) } } Comment Out
  14. 14. Example 14 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 ) } } Method ‘setupThread’ → ‘configureTask’ Comment Out
  15. 15. Example 15 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 ) } } Method ‘setupThread’ → ‘configureTask’ Parameter ‘thread’ → ‘task’ Comment Out
  16. 16. Example 16 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 ) } } Method ‘setupThread’ → ‘configureTask’ Parameter ‘thread’ → ‘task’ 2 more refactorings Comment Out
  17. 17. Example 17 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 ) } } Comment Out Refactorings
  18. 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. 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. 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. 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. 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. 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. 24 Old Old version of source code New version of source codeApproach New Source code differences refactoring Old New Old Modified New
  25. 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. 26 Overview of the proposed technique New Ver. Input 2 ExtractingOld Ver. Refactorings Input 1 Ordered List of Refactorings Applying " Modified
 Refactorings Ver. Output 2 Output 1
  27. 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
  28. 28. Supporting tool •  Refactoring Extraction •  Automatical extraction •  External Input •  Refactoring Application •  Automatically apply by using Eclipse Refactoring Browser Extraction Application packages, files, classes, interfaces,Rename all elements enums, methods Move files, methods files, methods 28 Extract - methods
  29. 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. 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. 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. 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. 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. 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. 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

×