Refactoring 022 - Extract Common Ancestor

Make your class hierarchy clear and flexible TL;DR: Extract a common abstract class to mimic real-world structure. Problems Addressed Duplicate Code Inappropriate Inheritance Shotgun Surgery Big Class Feature Envy High Coupling Concrete classes subclassified Parent class not abstract Related Code Smells Code Smell 66 - Shotgun Surgery Maxi Contieri ・ Apr 5 '21 #codenewbie #tutorial #oop #webdev Code Smell 255 - Parallel Hierarchies Maxi Contieri ・ Jun 21 '24 #webdev #beginners #programming #tutorial Code Smell 63 - Feature Envy Maxi Contieri ・ Mar 23 '21 #codenewbie #programming #oop #webdev Code Smell 43 - Concrete Classes Subclassified Maxi Contieri ・ Dec 5 '20 #oop #codenewbie #tutorial #webdev Code Smell 161 - Abstract/Final/Undefined Classes Maxi Contieri ・ Sep 2 '22 #webdev #beginners #programming #java Steps Identify common behaviors in both classes Create an abstract class with shared behavior and no implementation Move common logic to the abstract class Update subclasses to inherit from the abstract class Sample Code Before class Car { void drive() { System.out.println("Driving a car"); } } class Truck extends Car { void load() { System.out.println("Loading cargo"); } void unload() { System.out.println("Unloading cargo"); } } // Truck reuses driving method // Overriding it would be another code smell // Violating Liskov Substitution rule After abstract class Vehicle { // 2. Create an abstract class // with shared behavior and no implementation abstract void drive(); // 1. Identify common behaviors in both classes // 3. Move common logic to the abstract class } class Car extends Vehicle { // 4. Update subclasses to inherit from the abstract class void drive() { System.out.println("Driving a car"); } } class Truck extends Vehicle { // 4. Update subclasses to inherit from the abstract class void drive() { System.out.println("Driving a truck"); // Implementation is different than the car's } void load() { System.out.println("Loading cargo"); } void unload() { System.out.println("Unloading cargo"); } } Type [X] Semi-Automatic Safety This refactoring is safe if you identify all common behaviors correctly and move one method at a time running the tests. Why is the Code Better? It reduces duplication, simplifies maintenance, and makes it easier to extend functionality by adding new concrete realizations. How Does it Improve the Bijection? By introducing an abstract class, the code better reflects the real-world hierarchy, creating a clear relationship between the generic and specific types. Refactor with AI Without Proper Instructions With Specific Instructions ChatGPT ChatGPT Claude Claude Perplexity Perplexity Copilot Copilot Gemini Gemini Meta AI Meta AI Tags Inheritance Related Refactorings Refactoring 013 - Remove Repeated Code Maxi Contieri ・ Jun 16 '24 #webdev #beginners #programming #tutorial See also Refactoring Guru - Extract Superclass Credits Image by Pexels on Pixabay This article is part of the Refactoring Series. How to Improve your Code With easy Refactorings Maxi Contieri ・ Oct 24 '22 #webdev #beginners #programming #tutorial

Jan 23, 2025 - 03:34
 0
Refactoring 022 - Extract Common Ancestor

Make your class hierarchy clear and flexible

TL;DR: Extract a common abstract class to mimic real-world structure.

Problems Addressed

Related Code Smells

Steps

  1. Identify common behaviors in both classes
  2. Create an abstract class with shared behavior and no implementation
  3. Move common logic to the abstract class
  4. Update subclasses to inherit from the abstract class

Sample Code

Before

class Car {
    void drive() {
        System.out.println("Driving a car");
    }
}

class Truck extends Car {
    void load() {
        System.out.println("Loading cargo");
    }

    void unload() {
        System.out.println("Unloading cargo");
    }
}

// Truck reuses driving method
// Overriding it would be another code smell
// Violating Liskov Substitution rule

After

abstract class Vehicle {
    // 2. Create an abstract class
    // with shared behavior and no implementation
    abstract void drive();
    // 1. Identify common behaviors in both classes
    // 3. Move common logic to the abstract class
}

class Car extends Vehicle {
    // 4. Update subclasses to inherit from the abstract class
    void drive() {
        System.out.println("Driving a car");
    }
}

class Truck extends Vehicle {
    // 4. Update subclasses to inherit from the abstract class
    void drive() {
        System.out.println("Driving a truck");
        // Implementation is different than the car's
    }

    void load() {
        System.out.println("Loading cargo");
    }

    void unload() {
        System.out.println("Unloading cargo");
    }
}

Type

[X] Semi-Automatic

Safety

This refactoring is safe if you identify all common behaviors correctly and move one method at a time running the tests.

Why is the Code Better?

It reduces duplication, simplifies maintenance, and makes it easier to extend functionality by adding new concrete realizations.

How Does it Improve the Bijection?

By introducing an abstract class, the code better reflects the real-world hierarchy, creating a clear relationship between the generic and specific types.

Refactor with AI

Without Proper Instructions With Specific Instructions
ChatGPT ChatGPT
Claude Claude
Perplexity Perplexity
Copilot Copilot
Gemini Gemini
Meta AI Meta AI

Tags

  • Inheritance

Related Refactorings

See also

Refactoring Guru - Extract Superclass

Credits

Image by Pexels on Pixabay

This article is part of the Refactoring Series.

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow