객체지향 프로그래밍의 단점

    상속의 남용

    • 코드 복잡도 증가
    • 깊은 상속 계층 구조 ➔ 유지보수 어려움
    • 부모 클래스 수정 시 모든 자식 클래스에 영향 ➔ 강한 결합(Tight Coupling) 발생

    객체 간 강한 의존성

    • 재사용성 저하
    • 하나의 클래스를 수정하면 여러 곳에 영향을 받을 수 있음
    • 객체 간 관계가 복잡해지면 확장성과 유연성이 떨어짐

    불필요한 메모리 낭비

    • 상속을 사용할 경우, 부모 클래스의 불필요한 필드/메서드도 함께 사용됨
    • 필요하지 않은 기능이 포함될 수 있음

     

    상속이 과도하게 사용된 경우

    class Animal {
        void eat() { System.out.println("먹는 중..."); }
    }
    
    class Bird extends Animal {
        void fly() { System.out.println("나는 중..."); }
    }
    
    class Penguin extends Bird {
        void swim() { System.out.println("헤엄치는 중..."); }
    }

     

    ➡︎ Penguin 은 Bird 를 상속받지만, 펭귄은 fly() 메서드 불필요

    ➡︎ 잘못된 상속 구조로 인해 불필요한 메서드가 포함됨

    ➡︎ 강한 결합도가 발생하여 유지보수가 어려워짐

     

    ‼️ 상속을 사용하기 보다 구성(Composition) 으로 변경


    구성

    구성(Composition) 이란?

    하나의 객체가 다른 객체를 멤버 변수로 포함하는 방식

    객체 간 결합도를 줄이고, 유연성을 높일 수 있음

     

    구성 적용 코드

    class Swimmer {
        void swim() { System.out.println("헤엄치는 중..."); }
    }
    
    class Penguin {
        private Swimmer swimmer; // 조합(Composition) 사용
    
        Penguin() {
            this.swimmer = new Swimmer();
        }
    
        void swim() {
            swimmer.swim();
        }
    }

     

    ➡︎ 필요한 기능만 포함하여 유연한 설계 가능


    상속과의 비교

    비교 항목 상속(Inheritance) 구성(Composition)
    코드 재사용성 높음 높음
    유지보수성 낮음 (부모 클래스 변경 시 영향) 녹음 (독립적인 기능 구성 가능)
    객체 간 결합도 높음 (Tight Coupling) 낮음 (Loose Coupling)
    유연성  낮음 (상속 관계 변경 어려움) 높음 (필요한 기능만 구성 가능)

     

    ⭐️ 유지보수성과 확장성을 고려할 때, 가능하면 구성(Composition) 을 우선적으로 고려하고, 

         부모-자식 관계가 명확한 경우에만 상속(Inheritance) 을 사용


    객체지향 대안

    SOLID 원칙 준수

    • SRP(단일 책임 원칙): 하나의 클래스가 너무 많은 역할을 하지 않도록 정리
    • DIP(의존성 역전 원칙): 직접적인 의존성을 줄이고, 인터페이스 활용

    함수형 프로그래밍 개념 활용

    • 불변성: 객체 변경이 아닌 새로운 객체 생성
    • 순수 함수: 부작용 최소화

    디자인 패턴 활용

    • 전략 패턴: 특정 동작을 외부에서 주입하여 유연성 확보
    • 데코레이터 패턴: 객체 기능을 동적으로 확장

    + Recent posts