728x90
반응형

단일 책임 원칙 (Single Responsibility Principle, SRP)

개념: 하나의 클래스는 하나의 책임만 가져야 한다.

쉬운 설명: 각 부품은 한 가지 일만 잘하면 된다.

일상 예시: 주방에서 칼은 자르는 일만, 냄비는 음식을 담아 조리하는 일만 합니다. 칼에 음식을 담아 끓이려 하거나, 냄비로 음식을 자르려 하지 않죠. 각자의 역할에 충실한 것이 단일 책임 원칙과 비슷합니다.

개방-폐쇄 원칙 (Open-Closed Principle, OCP)

개념: 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.

쉬운 설명: 기존 코드를 건드리지 않고도 새로운 기능을 추가할 수 있어야 한다.

일상 예시: 스마트폰을 생각해보세요. 새로운 앱을 설치할 때 휴대폰의 운영체제를 변경하지 않습니다. 휴대폰(기존 시스템)은 그대로 두고, 새로운 기능(앱)을 쉽게 추가할 수 있죠. 이것이 바로 개방-폐쇄 원칙의 예입니다.

 

리스코프 치환 원칙 (Liskov Substitution Principle, LSP)

개념: 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.

쉬운 설명: 부모 클래스가 들어갈 자리에 자식 클래스를 넣어도 잘 작동해야 한다.

일상 예시: 커피숍에서 일하는 바리스타를 생각해보세요. 숙련된 바리스타 대신 신입 바리스타가 와도 커피를 만들 수 있어야 합니다. 물론 맛의 차이는 있겠지만, 기본적인 커피 제조 과정은 동일하게 수행할 수 있어야 하죠. 이처럼 대체 가능성을 보장하는 것이 리스코프 치환 원칙입니다.

 

인터페이스 분리 원칙 (Interface Segregation Principle, ISP)

개념: 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.

쉬운 설명: 불필요한 인터페이스는 구현하지 말고, 꼭 필요한 인터페이스만 구현하라.

일상 예시: 스마트폰의 리모컨 앱을 생각해보세요. TV 리모컨 앱은 TV 제어 기능만 있고, 에어컨 리모컨 앱은 에어컨 제어 기능만 있습니다. 하나의 앱에 모든 가전제품을 제어하는 기능을 넣지 않죠. 이처럼 필요한 기능만 분리해서 제공하는 것이 인터페이스 분리 원칙과 유사합니다.

 

의존관계 역전 원칙 (Dependency Inversion Principle, DIP)

개념: 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 되며, 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.

쉬운 설명: 구체적인 것이 추상적인 것에 의존해야 하며, 변하기 쉬운 것보단 변하기 어려운 것에 의존해야 한다.

일상 예시: 전기 콘센트를 생각해보세요. 콘센트는 어떤 전자기기가 꽂힐지 모르는 추상적인 인터페이스입니다. 전자기기(구체적인 것)는 이 추상적인 콘센트 규격(추상화)에 맞춰 만들어집니다. 콘센트 디자인이 변경되면 모든 전자기기를 바꿔야 하는 상황은 피해야 하죠. 이처럼 구체적인 것이 추상적인 것에 의존하게 만드는 것이 의존관계 역전 원칙입니다.

 

이렇게 SOLID 원칙을 적용하면, 코드의 유지보수가 쉬워지고, 확장성이 높아지며, 재사용성이 증가합니다. 마치 잘 정돈된 주방에서 요리하는 것처럼, SOLID 원칙을 따르는 코드는 개발자가 더 효율적으로 일할 수 있는 환경을 제공합니다.

728x90
반응형
728x90
반응형

서론

객체지향 프로그래밍에서 '추상화 수준'은 코드의 가독성과 유지보수성을 크게 향상시킬 수 있는 중요한 개념입니다. 이 글에서는 추상화 수준이 무엇인지, 왜 중요한지, 그리고 어떻게 적용할 수 있는지 살펴보겠습니다.

 

객체지향 프로그래밍 

객체지향 프로그래밍(OOP)은 소프트웨어 개발의 주요 패러다임 중 하나로, 프로그램을 객체들의 모임으로 구조화하는 프로그래밍 방식입니다. 이 방식은 실제 세계를 모델링하여 소프트웨어를 설계하고 구현하는 데 효과적입니다.

 

객체지향의 핵심 개념

a) 객체(Object): 데이터와 그 데이터를 조작하는 메서드를 하나의 단위로 묶은 것.

b) 클래스(Class): 객체를 생성하기 위한 템플릿 또는 청사진.

c) 캡슐화(Encapsulation): 객체의 내부 구현을 숨기고 외부에서는 정의된 인터페이스로만 접근할 수 있게 하는 개념.

d) 상속(Inheritance): 기존 클래스의 특성을 새로운 클래스가 물려받아 재사용성을 높이는 메커니즘.

e) 다형성(Polymorphism): 같은 인터페이스나 메서드가 다양한 형태로 동작할 수 있게 하는 개념.

 

객체지향의 장점

  • 코드 재사용성 증가
  • 유지보수의 용이성
  • 대규모 프로젝트에 적합한 구조
  • 실제 세계를 모델링하기 쉬움

객체지향과 추상화

객체지향 프로그래밍에서 추상화는 복잡한 시스템을 단순화하고 필수적인 특징만을 강조하는 과정입니다. 이는 불필요한 세부사항을 제거하고 문제의 본질에 집중할 수 있게 해줍니다.

추상화는 인터페이스와 추상 클래스를 통해 구현될 수 있으며, 이를 통해 코드의 유연성과 확장성을 높일 수 있습니다.

추상화 수준과 객체지향

추상화 수준은 객체지향 설계의 품질을 결정짓는 중요한 요소입니다. 적절한 추상화 수준을 유지함으로써, 우리는 객체들 간의 관계를 더 명확히 정의하고, 각 객체의 책임을 적절히 분배할 수 있습니다.

 

추상화와 추상화 수준이란?

추상화는 복잡한 시스템에서 핵심적인 부분만을 골라내는 과정입니다. 객체지향 언어에서는 객체의 공통된 특성을 뽑아 일반화하는 것을 의미합니다.

추상화 수준은 객체나 메서드가 얼마나 일반적이거나 구체적인지를 나타내는 정도입니다. 높은 추상화 수준은 더 일반적이고, 낮은 추상화 수준은 더 구체적입니다.

 

추상화 수준의 중요성

  • 코드 가독성 향상: 같은 추상화 수준의 코드는 읽기 쉽습니다.
  • 유지보수성 개선: 각 객체나 메서드가 한 가지 일만 담당하게 되어 수정이 용이합니다.
  • 테스트 용이성: 작은 단위로 나누어져 있어 단위 테스트가 쉬워집니다.
  • 재사용성 증가: 잘 나누어진 기능은 다른 곳에서도 쉽게 재사용할 수 있습니다.

실제 예시 : 쇼핑시나리오

낮은 수준의 추상화 코드

public void goShopping() {
    walkToStore();
    grabShoppingCart();
    findMilk();
    findEggs();
    goToCheckout();
    payForItems();
    walkHome();
}

이 코드는 너무 구체적이고 한 메서드가 여러 가지 일을 하고 있습니다.

 

높은 수준의 추상화 코드

public void goShopping() {
    Store store = new Store();
    ShoppingCart cart = store.getShoppingCart();
    List<Item> items = store.getItems(Arrays.asList("milk", "eggs"));
    cart.addItems(items);
    store.checkout(cart);
}

이 코드는 각 객체가 자신의 책임만 수행하도록 되어 있어 더 읽기 쉽고 유지보수하기 좋습니다.

 

실제 예시 : 자동차 경주

낮은 수준의 추상화 코드

class Car {
    private int position = 0;
    private IntSupplier powerGenerator;

    public void moveOnGeneratedPowerExceedsThreshold() {
        if (powerGenerator.getAsInt() > 4) {
            position++;
        }
    }
}

 

높은 수준의 추상화 코드

class Car {
    private Position position;
    private PowerGenerator powerGenerator;

    public void move() {
        if (powerGenerator.generatePower() > PowerThreshold.MOVE_THRESHOLD) {
            position.increase();
        }
    }
}

class Position {
    private int value = 0;
    public void increase() {
        value++;
    }
}

interface PowerGenerator {
    int generatePower();
}

 

추상화 수준 개선하기

a) 메서드 추출 : 긴 메서드를 여러 개의 작은 메서드로 나눕니다.

b) 새로운 클래스 도출 : 관련된 책임을 가진 메서드들을 새로운 클래스로 묶습니다.

c) 인터페이스 사용 : 구체적인 구현 대신 인터페이스를 사용하여 추상화 수준을 높입니다.

 

결론

추상화 수준을 일관되게 유지하는 것은 객체지향 프로그래밍의 핵심 원칙 중 하나입니다. 이를 통해 우리는 더 깔끔하고, 이해하기 쉬우며, 유지보수가 용이한 코드를 작성할 수 있습니다. 항상 "이 객체나 메서드가 한 가지 일만 하고 있는가?"를 질문하며 코드를 작성하고 리팩토링하는 습관을 들이면, 자연스럽게 좋은 추상화 수준을 유지할 수 있을 것입니다.

 

출처 : https://www.youtube.com/watch?v=1VwRtsLDiyM&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=4

 

 

 

728x90
반응형

+ Recent posts