انت هنا الان : شبكة جامعة بابل > موقع الكلية > نظام التعليم الالكتروني > مشاهدة المحاضرة

Code Refactoring

Share |
الكلية كلية تكنولوجيا المعلومات     القسم قسم البرامجيات     المرحلة 3
أستاذ المادة احمد خلفة عبيد العجيلي       30/06/2018 10:27:01
Definition
I Refactoring is changing a software system by improving its
internal structure without changing its external behaviour,
i.e. it is a technique to restructure the code in a disciplined
way
I It makes the software easier to understand and cheaper to
modify.
I Refactoring can help a team recover code that was previously
written off as an unmaintainable mess - spaghetti
code
I Code that is easier to understand is easier to maintain, and
code that is harder to understand is harder to maintain
I Refactoring can also help a programmer find bugs more
quickly
3 / 17
The code example
In this example, a programming team in an investment bank is
reviewing a block of code for a feature that calculates fees and
bonuses for brokers who sell a certain kind of investment account
to their corporate clients. The programmer who wrote the
code uses refactoring to clarify problems that were identified during
the code review.
The inspection team performed a code review on this block of
Java code, which included the class Account and a function
calculateFee from a different class:
4 / 17
Continued...
1 class Account {
2 f loa t p r i n c i p a l ;
3 f loa t rate ;
4 int daysAct ive ;
5 int accountType ;
6 public s t a t i c f i n a l int STANDARD = 0;
7 public s t a t i c f i n a l int BUDGET = 1;
8 public s t a t i c f i n a l int PREMIUM = 2;
9 public s t a t i c f i n a l int PREMIUM_PLUS = 3;
10 }
11 f loa t calculateFee ( Account accounts [ ] ) {
12 f loa t totalFee = 0;
13 Account account ;
14 for ( int i = 0; i < accounts . length ; i ++) {
15 account = accounts [ i ] ;
16 i f ( account . accountType == Account .PREMIUM | |
account . accountType == Account .PREMIUM_PLUS) {
17 totalFee += .0125 * ( account . p r i n c i p a l
* Math . exp ( account . rate * ( account . daysAct ive /
365.25) ) ?? account . p r i n c i p a l ) ;
18 }
19 }
20 return totalFee ;
21 }
5 / 17
The Extract Method refactoring
When refactor?
I You have a code fragment that can be grouped together
I Turn the fragment into a method whose name explains the
purpose of the method
Motivation
I Extract Method is one of the most common refactorings
done
I Looking at a method that is too long or look at code that
needs a comment to understand its purpose
I Then turn that fragment of code into its own method
6 / 17
Continued...
Mechanics
I Create a new method, and name it after the intention of the
method (name it by what it does, not by how it does it).
I Copy the extracted code from the source method into the
new target method.
I See whether any temporary variables are used only within
this extracted code. If so, declare them in the target method
as temporary variables.
I Pass into the target method as parameters local-scope variables
that are read from the extracted code.
I Compile when you have dealt with all the locally-scoped
variables.
I Replace the extracted code in the source method with a call
to the target method.
I Compile and test.
7 / 17
The refactored code
1 class Account {
2 f loa t p r i n c i p a l ;
3 f loa t rate ;
4 int daysAct ive ;
5 int accountType ;
6 public s t a t i c f i n a l int STANDARD = 0;
7 public s t a t i c f i n a l int BUDGET = 1;
8 public s t a t i c f i n a l int PREMIUM = 2;
9 public s t a t i c f i n a l int PREMIUM_PLUS = 3;
10 f loa t interes tEarned ( ) {
11 return ( p r i n c i p a l * ( f loa t ) Math . exp ( rate *
( daysAct ive / 365.25) ) ) ?? p r i n c i p a l ;
12 }
13 }
14 f loa t calculateFee ( Account accounts [ ] ) {
15 f loa t totalFee = 0;
16 Account account ;
17 for ( int i = 0; i < accounts . length ; i ++) {
18 account = accounts [ i ] ;
19 i f ( account . accountType == Account .PREMIUM | |
account . accountType == Account .PREMIUM_PLUS)
20 totalFee += .0125 * account . interes tEarned ( ) ;
21 }
22 return totalFee ;
23 }
8 / 17
Replace Magic Number with Symbolic Constant
When refactor?
I You have a literal number with a particular meaning
I Create a constant, name it after the meaning, and replace
the number with it
Motivation
I Magic numbers are one of oldest ills in computing
I They are numbers with special values that usually are not
obvious
I Magic numbers are really nasty when you need to reference
the same logical number in more than one place
I If the numbers might ever change, making the change is a
nightmare
9 / 17
Continued...
Mechanics
I Declare a constant and set it to the value of the magic
number
I Find all occurrences of the magic number
I See whether the magic number matches the usage of the
constant; if it does, change the magic number to use the
constant
I When all magic numbers are changed, compile and test. At
this point all should work as if nothing has been changed
10 / 17
The refactored code
1 class Account {
2 f loa t p r i n c i p a l ;
3 f loa t rate ;
4 int daysAct ive ;
5 int accountType ;
67
public s t a t i c f i n a l int STANDARD = 0;
8 public s t a t i c f i n a l int BUDGET = 1;
9 public s t a t i c f i n a l int PREMIUM = 2;
10 public s t a t i c f i n a l int PREMIUM_PLUS = 3;
11
12 f loa t interes tEarned ( ) {
13 return ( p r i n c i p a l * ( f loa t ) Math . exp ( rate *
( daysAct ive / 365.25) ) ) ?? p r i n c i p a l ;
14 }
15 }
16 f loa t calculateFee ( Account accounts [ ] ) {
17 f loa t totalFee = 0;
18 Account account ;
19 for ( int i = 0; i < accounts . length ; i ++) {
20 account = accounts [ i ] ;
21 i f ( account . accountType == Account .PREMIUM | |
22 account . accountType == Account .PREMIUM_PLUS)
23 totalFee += BROKER_FEE_PERCENT *
account . interes tEarned ( ) ;
24 }
25 return totalFee ;
26 }
27 s t a t i c f i n a l double BROKER_FEE_PERCENT = 0.0125;
11 / 17
The Decompose Conditional refactoring
When refactor?
I You have a complicated conditional (if-then-else) statement
I Extract methods from the condition, then part, and else part
Motivation
I One of the most common areas of complexity in a program
lies in complex conditional logic
Mechanics
I Extract the condition into its own method
I Extract the then part and the else part into their own methods
12 / 17
The refactored code
1 class Account {
2 f loa t p r i n c i p a l ;
3 f loa t rate ;
4 int daysAct ive ;
5 int accountType ;
7 public s t a t i c f i n a l int STANDARD = 0;
8 public s t a t i c f i n a l int BUDGET = 1;
9 public s t a t i c f i n a l int PREMIUM = 2;
10 public s t a t i c f i n a l int PREMIUM_PLUS = 3;
11 f loa t interes tEarned ( ) {
12 return ( p r i n c i p a l * ( f loa t ) Math . exp ( rate *
( daysAct ive / 365.25) ) ) ?? p r i n c i p a l ;
13 }
14 public boolean isPremium ( ) {
15 i f ( accountType == Account .PREMIUM | |
accountType == Account .PREMIUM_PLUS)
16 return true ;
17 else
18 return false ;
19 }
20 }
21 f loa t calculateFee ( Account accounts [ ] ) {
22 f loa t totalFee = 0;
23 Account account ;
24 for ( int i = 0; i < accounts . length ; i ++) {
25 account = accounts [ i ] ;
26 i f ( account . isPremium ( ) )
27 totalFee += BROKER_FEE_PERCENT *
account . interes tEarned ( ) ;
28 }
29 return totalFee ;
30 }
31 s t a t i c f i n a l double BROKER_FEE_PERCENT = 0.0125;
13 / 17
The Introduce Explaining Variable refactoring
When refactor?
I You have a complicated expression
I Put the result of the expression, or parts of the expression,
in a temporary variable with a name that explains the purpose
Motivation
I Expressions can become very complex and hard to read
I In such situations temporary variables can be helpful to
break down the expression into something more manageable
14 / 17
Continued...
Mechanics
I Declare a final temporary variable, and set it to the result of
part of the complex expression
I Replace the result part of the expression with the value of
the temp.
I Compile and test
I Repeat for other parts of the expression
15 / 17
The refactored code
1 class Account {
2 f loa t p r i n c i p a l ;
3 f loa t rate ;
4 int daysAct ive ;
5 int accountType ;
7 public s t a t i c f i n a l int STANDARD = 0;
8 public s t a t i c f i n a l int BUDGET = 1;
9 public s t a t i c f i n a l int PREMIUM = 2;
10 public s t a t i c f i n a l int PREMIUM_PLUS = 3;
12 f loa t interes tEarned ( ) {
13 f loa t years = daysAct ive / ( f loa t ) 365.25;
14 f loa t compoundInterest = p r i n c i p a l * ( f loa t )
Math . exp ( rate * years ) ;
15 return ( compoundInterest ?? p r i n c i p a l ) ;
16 }
17 public boolean isPremium ( ) {
18 i f ( accountType == Account .PREMIUM | |
accountType == Account .PREMIUM_PLUS)
19 return true ;
20 else
21 return false ;
22 }
23 }
16 / 17
Continued...
24 f loa t calculateFee ( Account accounts [ ] ) {
25 f loa t totalFee = 0;
26 Account account ;
27 for ( int i = 0; i < accounts . length ; i ++) {
28 account = accounts [ i ] ;
29 i f ( account . isPremium ( ) )
30 totalFee += BROKER_FEE_PERCENT *
account . interes tEarned ( ) ;
31 }
32 return totalFee ;
33 }
34 s t a t i c f i n a l double BROKER_FEE_PERCENT = 0.0125;
17 / 17

المادة المعروضة اعلاه هي مدخل الى المحاضرة المرفوعة بواسطة استاذ(ة) المادة . وقد تبدو لك غير متكاملة . حيث يضع استاذ المادة في بعض الاحيان فقط الجزء الاول من المحاضرة من اجل الاطلاع على ما ستقوم بتحميله لاحقا . في نظام التعليم الالكتروني نوفر هذه الخدمة لكي نبقيك على اطلاع حول محتوى الملف الذي ستقوم بتحميله .
الرجوع الى لوحة التحكم