ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] 0216 객체 지향 프로그래밍 (OOP), SOLID
    카테고리 없음 2024. 2. 16. 20:57

     

    객체 (Object)

    : 현실 세계의 물체 혹은 개념을 소프트웨어 적으로 옮긴 것으로, 정보 + 행동(method) 으로 구성된다.

     

    객체 지향 (Object-Oriented)

    : 객체 도출, 각각의 역할 명확히 정의하는 것에 초점을 맞추는 방법론

    : 크고 복잡한 시스템도 효과적으로 분해와 구성이 가능하여, 효율적으로 관리할 수 있다.

     

    객체 지향적 소프트웨어 

     1) 캡슐화, 다형성, 상속을 지원

     2) 데이터 접근 제한 (Access modifier) 가능

    <-> 절차 지향 소프트웨어

     

    프로그래밍 패러다임 ( Programming Paradigm )

    : 프로그래밍의 방식이나 관점을 바탕으로 효율적이고 명확한 코드를 작성하는 방법

     

    1) 구조적 프로그래밍 : 가장 처음 적용된 패러다임

    2) 함수형 프로그래밍 : 함수 중심적으로 개발 진행

     

    3) 객체 지향 프로그래밍 

    : 데이터와 메서드가 같은 모듈 내부에 배치되는 프로그래밍 방식

    : 객체는 고유의 특성 + 특정 기능 을 가진다.

    : 데이터와 기능이 밀접하게 연결되어 있어 코드의 구조와 동작을 직관적으로 파악이 가능하다.

    객체 지향 프로그래밍 (OOP)

     

    객체 지향 프로그래밍의 원칙

     

    1) 캡슐화 (Encapsulation)

    : 객체 내부의 중요한 정보를 외부로 노출되지 않도록 만드는 것

    : JS 는 완벽한 캡슐화를 지원하지 않아 개발자들은 변수 앞에 _ 를 붙여 내부 변수를 숨긴 것 처럼 나타낸다.


    class User {
      private name: string; // name 변수의 외부접근 차단
      private age: number; // age 변수의 외부접근 차단

      setName(name: string) { // Private 속성을 가진 name 변수의 값을 변경
        this.name = name;
      }


      getName() { // Private 속성을 가진 name 변수의 값을 조회합니다.
        return this.name;
      }
      setAge(age: number) { // Private 속성을 가진 age 변수의 값을 변경합니다.
        this.age = age;
      }
      getAge() { // Private 속성을 가진 age 변수의 값을 조회합니다.
        return this.age;
      }
    }

    : 변수의 값을 가져오는 getter (getName, getAge) 만 변수를 조회할 수 있고,

    변수의 값을 설정하는 setter (setName, setAge) 만 변수를 변경할 수 있다.

     

    2) 상속 (Inheritance)

    : 하나의 클래스가 가진 특징을 다른 클래스가 그대로 물려 받는 것

    : 코드의 중복을 제거하고 코드 재사용성을 증대시킴

     

    class Mother { // Mother 부모 클래스
      constructor(name, age, tech) { // 부모 클래스 생성자
        this.name = name;
        this.age = age;
        this.tech = tech;
      }
      getTech(){ return this.tech; } // 부모 클래스 getTech 메서드
    }

    class Child extends Mother{ // Mother 클래스를 상속받은 Child 자식 클래스
      constructor(name, age, tech) { // 자식 클래스 생성자
        super(name, age, tech); // 부모 클래스의 생성자를 호출
      }
    }

    3) 추상화 (Abstraction)

    : 객체에서 공통된 부분을 모아 상위 개념으로 새롭게 정의하는 것

    : 불필요한 세부사항을 생략하여 코드를 간결하고 명확하게 만든다.

     

    interface Human {
      name: string;
      setName(name);
      getName();
    }

    // 인터페이스에서 상속받은 프로퍼티와 메소드는 구현하지 않을 경우 에러가 발생
    class Employee implements Human {
      constructor(public name: string) {  }
      
      // Human 인터페이스에서 상속받은 메소드
      setName(name) { this.name = name; }
      
      // Human 인터페이스에서 상속받은 메소드
      getName() { return this.name; }
    }

    const employee = new Employee("");
    employee.setName("홍길동");
    console.log(employee.getName()); // 홍길동

     

    4) 다형성 (Polymorphism)

    : 하나의 객체(클래스) 가 다양한 형태로 동작하는 것

    : 같은 기능이 다르게 재구성 되어 사용됨을 의미

    : 동일 메서드나 함수 명이여도 클래스마다 다르게 동작

     

    class Person {
      constructor(name) { this.name = name; }

      buy() {}
    }

    class Employee extends Person {
      buy() { console.log(`${this.constructor.name} 클래스의 ${this.name}님이 물건을 구매하였습니다.`); }
    }

    class User extends Person {
      buy() { console.log(`${this.constructor.name} 클래스의 ${this.name}님이 물건을 구매하였습니다.`); }
    }

    const user1 = new User("이태강");
    const user2 = new User("김민수");

    const personsArray = [user1, user2];
    personsArray.forEach((person) => person.buy());

    // User 클래스의 이태강님이 물건을 구매하였습니다.
    // User 클래스의 김민수님이 물건을 구매하였습니다.

     

     

    객체 지향 프로그래밍 및 설계의 다섯가지 기본원칙 : SOLID

     

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

     : 하나의 객체는 하나의 책임을 가져야 한다는 개념을 가지며, 적절한 클래스의 크기를 제시한다.

     

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

    : 소프트웨어 엔티티 또는 개체(클래스, 모듈, 함수 등) 의 행위는 확장될 수 있어야 하지만, 개체를 변경해서는 안된다.

    : 기존 코드에 영향없이 소프트웨어에 새로운 기능이나 구성 요소를 추가할 수 있어야 한다.

    OCP 예시

     

    3) 리스코프 치환 원칙 (Liskov substitution principle, LSP)

    : 부모 클래스와 자식 클래스를 가지고 있다면, 서로 바꾸더라도 해당 프로그램에서 잘못된 결과를 도출하지 않아야 한다는 원칙

    : 원칙에 위배되면, 새로운 부모 클래스를 형성하여 자식 클래스로 넣어 통합시키는 방법 이 있다.

     

    4) 인터페이스 분리 원칙 (Interface segregation principle, ISP)

    : 필요없는 것들에 의존하지 않도록 인터페이스는 작고 구체적으로 유지해야 한다는 원칙

    : 범용 인터페이스 하나보다 특정 클라이언트를 위한 인터페이스 여러 개가 낫다.

     

    5) 의존성 역전 원칙 (Dependency Inversion Principle, DIP)

    : 높은 계층의 모듈(도메인)이 저수준의 모듈(하부구조)에 직접 의존해서는 안된다.

    DIP 전 후

Designed by Tistory. KYW