Download presentation
Presentation is loading. Please wait.
Published byEthan Floyd Modified over 9 years ago
1
Chapter 7: Bad Code Smells Omar Meqdadi SE 3860 Lecture 7 Department of Computer Science and Software Engineering University of Wisconsin-Platteville
2
2 Topic Covered Bad Code Smells Smells Categorization Smells Refactoring
3
Bad Code Smells The most common design problems result from code because of bad code smells such as: Code duplication Unclear code Complicated Code
4
Bad Code Smells: Example Why is this implementation bad? How can you improve it? Provide a list of improvements. class Animal { int MAMMAL = 0, BIRD = 1, REPTILE = 2; int myKind; // set in constructor... string getSkin() { switch (myKind) { case MAMMAL: return "hair"; case BIRD: return "feathers"; case REPTILE: return "scales"; default: return "integument"; }
5
5 Bad Code Smells: Example Bad Implementation because of switch statements are very rare in properly designed object- oriented code A switch statement should not be used to distinguish between various kinds of object Code improvement solution Refactoring : the simplest is the creation of subclasses
6
Bad Code Smells: Example Improved code: class Animal { string getSkin() { return "integument"; } } class Mammal extends Animal { string getSkin() { return "hair"; } } class Bird extends Animal { string getSkin() { return "feathers"; } } class Reptile extends Animal { string getSkin() { return "scales"; } }
7
Bad Code Smells: Example How is this an improvement? Adding a new animal type, such as Insect, does not require revising and recompiling existing code Mammals, birds, and reptiles are likely to differ in other ways, and we’ve already separated them out (so we won’t need more switch statements) we’re now using Objects the way they were meant to be used
8
Bad Code Smells: Types Duplicate code Long method Conditional Complexity Data Class Solution Sprawl Switch statements Large class Lazy class Combinatorial Explosion Long Parameter List Data Clumps Comments
9
Bad Code Smells: Categorization Bloaters Something that has grown so large that it cannot be effectively handled Object-Orientation Abusers Cases where the solution does not fully exploit the possibilities of object-oriented design Change Preventers Smells that hinder changing or further developing the software. Dispensable Something unnecessary that should be removed from the source code Couplers: coupling-related smells
10
Bad Code Smells: Indications Frequent failures Overly complex structure Very large components Excessive resource requirements Deficient documentation High personnel turnover Different technologies in one system
11
Bad Code Smells: Solution Resolving the code smells is a Reengineering Process Steps: Program Comprehension (Understanding) Refactoring A set of transformations that are guaranteed to preserve the behavior while they can remove bad code smells Refining
12
Bad Code Smells Refactoring
13
Duplicate Code Duplicate Code (Code Clones): The same, or very similar code, appears in many places Problems: Bug introducing Makes code larger that it needs to be
14
Duplicate Code Case1: occurs within a single class Refactoring: Extract Method Turn the fragment into a method whose name explains the purpose of the method Any local variables that the method requires can be passed as parameters int sum1 = 0; int sum2 = 0; int average1 = 0; int average2 = 0; for (int i = 0; i < size1; i++){ sum1 += array1[i]; } average1 = sum1/size1; for (int i = 0; i < size2; i++){ sum2 += array2[i]; } average2 = sum2/size2; int calcAverage (int A[], int size){ int sum = 0; for (int i = 0; i < size; i++) { sum += A[i]; } return sum/size;}
15
Duplicate Code Case2: occurs in sibling classes Refactoring: Use Extract Method in each class Be sure the code is identical If necessary, adjust the method signatures to be identical Pull Up Method :Copy the extracted method to the common superclass Delete the method from subclasses
16
Duplicate Code Example: consider the ocean scenario: Fish move about randomly A big fish can move to where a little fish is (and eat it) A little fish will not move to where a big fish is General move method: public void move() { choose a random direction; // same for both find the location in that direction; // same for both check if it’s ok to move there; // different if it’s ok, make the move; // same for both } BigFish move() Fish > move() LittleFish move()
17
Duplicate Code Refactoring solution: Extract the check on whether it’s ok to move In the Fish class, put the actual move() method Create an abstract okToMove() method in the Fish class Implement okToMove() in each subclass BigFish okToMove(locn):boolean Fish move() >okToMove(locn):boolean BigFish okToMove(locn):boolean
18
Duplicate Code Case3: occurs in unrelated classes Refactoring Solution1: Use Extract Method in one class Then, invoke the method from the other class Refactoring Solution2: Use Extract Superclass if that is possible
19
Duplicate Code: Example class Car{ private: int mpg; double fuelInTank; public: Car() { mpg = 25; fuelInTank = 5.056;} void MoreGas(double g){ fuelInTank = fuelInTank + g;} void move(double miles){ double used = miles / mpg; fuelInTank = fuelInTank - used;}} class Van{ private: int mpg; double fuelInTank; public: Van() { mpg = 20; fuelInTank = 9.056;} void MoreGas(double g){ fuelInTank = fuelInTank + g;} void move(double miles){ double used = miles / mpg; fuelInTank = fuelInTank - used;}} class Vehicle{ private: int mpg; double fuelInTank; public: void MoreGas(double g){ fuelInTank = fuelInTank + g;} void move(double miles){ double used = miles / mpg; fuelInTank = fuelInTank - used;}} class Car: public Vehicle { public: Car() { mpg = 25; fuelInTank = 5.056;} } class Van: public Vehicle { public: Van() { mpg = 20; fuelInTank = 9.056;} }
20
Long Method Long method Over 20 LOC is usually bad. Under 10 lines is typically good. Problems: Difficult to Understand Change Reuse Refactoring Solution: Method Extraction Take portions of code from inside long method, and make a new method Then, Call new method inside the now-not-so-long method
21
Long Method Example: void methodA(){ Statement 1; Statement 2;.. Statement 30; } void methodA(){ Statement 1; Statement 2;.. Statement 30; } private void m1(){ Statement 1;.. Statement 9; } private void m2(){ Statement 10;.. Statement 19; } private void m3(){ Statement 20;.. Statement 30; } public void methodA(){ m1(); m2(); m3(); } private void m1(){ Statement 1;.. Statement 9; } private void m2(){ Statement 10;.. Statement 19; } private void m3(){ Statement 20;.. Statement 30; } public void methodA(){ m1(); m2(); m3(); }
22
Feature Envy A method in one class uses primarily data and methods from another class to perform its work Indicates the method was incorrectly placed in the wrong class Problems: High class coupling Difficult to change, understand, and reuse Refactoring Solution:Extract Method & Method Movement Move the method with feature envy to the class containing the most frequently used methods and data items
23
Feature Envy Example: Method updateItemPanel is defined in class OrderItemPanel, but the method interests in class ItemPanel class OrderItemPanel { private: itemPanel _itemPanel; void updateItemPanel( ) { Item item = getItem(); int quant = getQuantity( ); if (item == null) _itemPanel.clear( ); else{ _itemPanel.setItem(item); _itemPanel.setInstock(quant); }
24
Feature Envy Example: Refactoring solution: Extract method doUpdate in class OrderItemPanel Move method doUpdate to class ItemPanel class OrderItemPanel { private: itemPanel _itemPanel; void updateItemPanel( ) { Item item = getItem(); int quant = getQuantity( ); _itemPanel.doUpdate(item, quant); }} class ItemPanel { public: void doUpdate(Item item, int quantity){ if (item == null) clear( ); else{ setItem(item); setInstock(quantity); }} }
25
Large Classes Classes try to do too much (many methods and data members) Problems: Low class cohesion Difficult to change and understand Bug introducing Refactoring Solution: Class Extraction Take a subset of the instance variables and methods and create a new class with them Method Movement
26
PhoneNumber Customer name areaCode number String: getPhoneNumber() PhoneNumber: getPhoneNumber() Large Classes
27
Switch Statements The cases in a switch statement contain logic for different types of instances of the same class In object-oriented code, this indicates new subclasses should be created Problems: Introducing code clones The same switch/case structure appears in many places Refactoring Solution: Create new subclasses Extract method to move case block logic into methods on the new subclasses
28
Switch Statements Example: class Animal { int MAMMAL = 0, BIRD = 1, REPTILE = 2; int myKind; // set in constructor... string getSkin() { switch (myKind) { case MAMMAL: return "hair"; case BIRD: return "feathers"; case REPTILE: return "scales"; default: return “skin"; } } } class Animal { string getSkin() { return “skin"; } } class Mammal : public Animal { string getSkin() { return "hair"; } } class Bird: public Animal { string getSkin() { return "feathers"; } } class Reptile : public Animal { string getSkin() { return "scales"; } } After Refactoring
29
Data Classes A class that has only class variables, get/set methods Acting as a data holder only Problems: Other classes have methods with feature envy That is, there are usually other methods that primarily manipulate data in the data class Indicates these methods should really be on the data class Refactoring Solution: Method Movement Find methods that use data class attributes, and then move them to the data class
30
Data Classes Example:After Refactoring
31
Long Parameter List Many parameters passed into a method Problems: Hard to understand, change, and reuse Refactoring Solution: Replace Parameter with Method Introduce Parameter Object Preserve Whole Object
32
Long Parameter List Example: void paint (Graphics gr, double x, double y, double width, double height, bool shouldValidate) {.....} Caller side: public void someMethod(Graphics gr) { double x = 100; double y = 200; double width = 100; double height = width/2; paint(gr, x, y, width, height, true); } void paint (Graphics gr, Shape rec, bool shouldValidate) {.....} Caller side: void someMethod(Graphics gr){ double x = 100; double y = 200; double width = 100; double height = width/2; Shape rect = new Shape( x, y, width, height); paint(gr, rect, true); } After Refactoring
33
Shotgun Surgery Making one change requires changing code in multiple places Problems: Hard to change Refactoring Solution: Method Movement Data members(fields) movement Inline classes
34
Lazy Class A class just doesn’t do enough Refactoring Solution: If a class is very similar to its superclass, you can try to use Collapse Hierarchy to merge the two classes Use Inline class If a class just isn’t doing very much, move all its features into another class with Move Field and Move Method
35
Lazy Class Example: Salesman and Employee are not very different So, merge them
36
Data Clumps Sets of variables usually passed together in multiple places Refactoring Solution: Extract Classes Introduce Parameter Object
37
Data Clumps Example: bool SubmitCreditCardOrder (string creditCardNumber, int expirationMonth, int expirationYear, double saleAmount) { } bool Isvalid (string creditCardNumber, int expirationMonth, int expirationYear) { } bool Refund(string creditCardNumber, int expirationMonth, int expirationYear, double Amount) { } class CreditCard { private: string creditCardNumber;, int expirationMonth; int expirationYear; }; bool SubmitCreditCardOrder ( CreditCard card, double saleAmount) { } bool Isvalid (CreditCard card) { } bool Refund(CreditCard card, double Amount) { } After Refactoring
38
Middle Man Delegation : one class simply delegates many of its requests to another class Refactoring Solution: Replace Delegation with Inheritance Use Remove Middle Man and talk to the object that really knows what is going on Use Inline Method to absorb a few small methods into the caller
39
Middle Man Example: using Inline Method int getRating() { return (moreThanFiveLateDeliveries()) ? 2 : 1; } boolean moreThanFiveLateDeliveries() { return _numberOfLateDeliveries > 5; } int getRating() { return (moreThanFiveLateDeliveries()) ? 2 : 1; } boolean moreThanFiveLateDeliveries() { return _numberOfLateDeliveries > 5; } int getRating() { return (_numberOfLateDeliveries > 5) ? 2 : 1; } int getRating() { return (_numberOfLateDeliveries > 5) ? 2 : 1; }
40
Temporary Field We expect an object to use all its fields. However, it’s a problem when a field is used only in certain cases Or, a case in which a variable is in the class scope, when it should be in method scope Refactoring Solution: Use Extract Class to create a home for these variables
41
LaborItem JobItem getTotalPrice() getUnitPrice() getEmployee( ) Do all the JobItem objects need have getEmployee function? getUnitPrice() Temporary Field
42
Refused Bequest Refused bequest Subclasses may inherit unwanted methods from their superclasses Refactoring Solution: Extract Classes and Move Methods Create a new subclass and use method movement on the unused methods Replace inheritance with delegation
43
Replace inheritance with delegation A subclass uses only part of a superclasses interface or does not want to inherit data. Create a field for the superclass, adjust methods to delegate to the superclass, and remove the subclassing. Refused Bequest
44
Comments Often used as deodorant for other smells may indicate areas where the code is not as clear as it could be Refactoring Solution: Extract Method: if you need a comment to explain what a block of code does Rename Method: if you need a comment to explain what a method does Introduce Assertion: if you need to describe the required state of the system
45
Comments Example: void PrintBill ( Customer C, double Amount){ PrintBanner(); string name = c.getname(); // print details cout << “name: ” << name << endl; cout << ”amount: ” << Amount << endl; } void PrintBill ( Customer C, double Amount){ PrintBanner(); PrintDetails (c.getname(), Amount); } void PrintDetails(string name, double amount){ cout << “name: ” << name << endl; cout << ”amount: ” << Amount << endl; } Comment deleted, temp variable removed After Extract Method Refactoring
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.