Chapter 7: Bad Code Smells Omar Meqdadi SE 3860 Lecture 7 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.

Slides:



Advertisements
Similar presentations
12-Dec-14 Refactoring IV. Previously discussed bad smells Duplicated code — and other forms of redundancy Long method — use short methods that delegate.
Advertisements

Clean code. Motivation Total cost = the cost of developing + maintenance cost Maintenance cost = cost of understanding + cost of changes + cost of testing.
About Me – Frank Xu Education ▫ North Dakota State University  Ph.D. in Software Engineering ▫ Towson University  MS in Computer Science ▫ Southeast.
© 2010 Shawn A. Bohner Software Construction and Evolution - CSSE 375 Even more Bad Smells in Code Shawn & Steve Q1 Shawn & Steve Hint 
1 Software Maintenance and Evolution CSSE 575: Session 2, Part 2 Composing Methods Steve Chenoweth Office Phone: (812) Cell: (937)
Bad code smells Refactoring Example Game Design Experience Professor Jim Whitehead January 26, 2009 Creative Commons Attribution 3.0 creativecommons.org/licenses/by/3.0.
Refactoring Overview  What is refactoring?  What are four good reasons to refactor?  When should you refactor?  What is a bad smell (relative to refactoring.
Software Evolution and Refactoring July Introduction Any changes on software by developers or users These changes are costly How we can design.
Software Construction and Evolution - CSSE 375 Bad Smells in Code Shawn Bohner & Steve Chenoweth.
1 Software Maintenance and Evolution CSSE 575: Session 1, Part 4 Even more Bad Smells in Code Steve Chenoweth Office Phone: (812) Cell: (937)
Procedural vs Object Oriented Design Bad code smells Game Design Experience Professor Jim Whitehead January 23, 2009 Creative Commons Attribution 3.0 creativecommons.org/licenses/by/3.0.
Introduction to Refactoring Excerpted from ‘What is Refactoring?’ by William C. Wake and Refactoring: Improving the Design of Existing Code by Martin Fowler.
George Blank University Lecturer. REFACTORING Improving the Design of Existing Code Supplement to Ian Sommerville, Software Engineering, Chapter 20 Prepared.
25-Jun-15 Refactoring III. General philosophy A refactoring is just a way of rearranging code Refactorings are used to solve problems If there’s no problem,
REFACTORING Improving the Design of Existing Code Atakan Şimşek e
12-Jul-15 Refactoring. 2 Refactoring is: restructuring (rearranging) code......in a series of small, semantics-preserving transformations (i.e. the code.
13-Jul-15 Refactoring II. Books Design Patterns is the classic book by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides Basically a catalog.
Refactoring to Patterns Ravindra Chilaka Extreme Programming Seminar XP 2004 b.
Maintenance Refactoring and Code Smells. Where are we? Over the semester we have talked about Software Engineering. The overall goal of software engineering.
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Software Refactoring Part I: Introduction Bartosz Walter Advanced Object-Oriented Design Lecture 5.
LECTURE 38: REFACTORING CSC 395 – Software Engineering.
Refactoring. Mathematics: Factor ● fac·tor – One of two or more quantities that divides a given quantity without a remainder, e.g., 2 and 3 are factors.
Refactoring - A disciplined approach to rework for better design.
Software Engineering 1 Object-oriented Analysis and Design Chap 21 Test-Driven Development and Refactoring.
Refactoring Improving the structure of existing code Refactoring1.
17-Oct-15 Refactoring. 2 Refactoring is: restructuring (rearranging) code......in a series of small, semantics-preserving transformations (i.e. the code.
17-Oct-15 Design Patterns and Refactoring CSC 2053.
Refactoring (continued) Source: "Refactoring: Improving the Design of Existing Code", Martin Fowler.
Refactoring1 Improving the structure of existing code.
Refactoring Deciding what to make a superclass or interface is difficult. Some of these refactorings are helpful. Some research items include Inheritance.
Peyman Dodangeh Sharif University of Technology Fall 2014.
Software Engineering CS3003 Lecture 4 Code bad smells and refactoring.
Refactoring. Refactoring Overview  What is refactoring?  What are four good reasons to refactor?  When should you refactor?  What is a bad smell (relative.
Refactoring 2. Admin Blackboard Quiz Acknowledgements Material in this presentation was drawn from Martin Fowler, Refactoring: Improving the Design of.
REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies.
Module 3. Smells Between Classes Course: Refactoring.
Software Construction and Evolution - CSSE 375 Making Method Calls Simpler Shawn and Steve Below – “Be the character!” The late acting teacher Lee Strasberg.
1 Software Maintenance and Evolution CSSE 575: Session 3, Part 3 Dealing with Generalization Steve Chenoweth Office Phone: (812) Cell: (937)
Refactoring1 Improving the structure of existing code.
Pertemuan 12 Refactoring Mata kuliah: T0144 – Advanced Topics in Software Engineering Tahun: 2010.
CSSE 375 Organizing Data – Part 1 Shawn and Steve Q1.
Software Construction and Evolution - CSSE 375 Dealing with Generalization Steve and Shawn Left – In the 1990 movie “The Freshman,” Matthew Broderick,
Refactoring. DCS – SWC 2 Refactoring ”A change made to the internal structure of software to make it easier to understand and cheaper to modify without.
Module 9. Dealing with Generalization Course: Refactoring.
Chapter 9: Coupling & Cohesion Omar Meqdadi SE 273 Lecture 9 Department of Computer Science and Software Engineering University of Wisconsin-Platteville.
Chapter 9: Continuing Classes By Matt Hirsch. Table Of Contents 1.Static Fields and Methods 2.Inheritance I. Recycle Code with Inheritance II. Overriding.
10-Jun-16.  Refactoring is: ◦ restructuring (rearranging) code... ◦...in a series of small, semantics-preserving transformations (i.e. the code keeps.
Catalog of Refactoring (1) Composing Methods. Code Smells Long methods Dubious temporary variables Dubious methods.
Software Engineering 1 Object-oriented Analysis and Design Applying UML and Patterns An Introduction to Object-oriented Analysis and Design and Iterative.
ICONFINDER ICONFINDER Founded Django based web application -PostgreSQL -Elasticsearch -Amazon Elastic Compute.
A (Very) Simple Example Consolidate duplicate conditional fragments if (isSpecialDeal()) { total = price * 0.95; send (); } else { total = price * 0.98;
Principles and examples
Catalog of Refactoring
Module Road Map Refactoring Why Refactoring? Examples
Steve Chenoweth Office Phone: (812) Cell: (937)
Extract Subclass, Extract Superclass and Extract Hierarchy
Refactoring II 21-Sep-18.
Refactoring and Code Smells
Software Construction and Evolution - CSSE 375 Composing Methods
Refactoring III 27-Nov-18.
Code Smells 1.
Improving the structure of existing code
Refactoring and Code Smells
Refactoring III 25-Dec-18.
Refactoring II 5-Feb-19.
Refactoring and Code Smells
Refactoring.
Refactoring and Code Smells
Presentation transcript:

Chapter 7: Bad Code Smells Omar Meqdadi SE 3860 Lecture 7 Department of Computer Science and Software Engineering University of Wisconsin-Platteville

2 Topic Covered Bad Code Smells Smells Categorization Smells Refactoring

Bad Code Smells The most common design problems result from code because of bad code smells such as:  Code duplication  Unclear code  Complicated Code

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 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

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"; } }

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

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

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

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

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

Bad Code Smells Refactoring

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

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;}

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

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()

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

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

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;} }

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

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(); }

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

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); }

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); }} }

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

PhoneNumber Customer name areaCode number String: getPhoneNumber() PhoneNumber: getPhoneNumber() Large Classes

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

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

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

Data Classes Example:After Refactoring

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

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

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

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

Lazy Class Example:  Salesman and Employee are not very different  So, merge them

Data Clumps  Sets of variables usually passed together in multiple places  Refactoring Solution: Extract Classes Introduce Parameter Object

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

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

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; }

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

LaborItem JobItem getTotalPrice() getUnitPrice() getEmployee( ) Do all the JobItem objects need have getEmployee function? getUnitPrice() Temporary Field

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

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

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

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