: 소프트웨어의 핵심을 기능이 아닌 객체로 삼는것
객체를 도출하고 각각의 역할을 정의하는 것에 초점
책임과 권한을 가진 객체들이 서로 메시지를 주고받으며 협력해서 필요한 기능을 수행하도록 시스템을 개발하는 것
크고 복잡한 시스템을 효과적으로 분해하고 구성할 수 있고, 손쉽게 이해하고 효율적으로 다룰 수 있게 도와주는 방법
캡슐화, 다형성, 클래스 상속을 지원하는가? 기준을 만족할 경우 객체지향, 만족하지 않으면 절차지향
캡슐화 (Encapsulation):
개념적이나 물리적으로 객체 내부의 세부적인 사항을 감추는 것
목적: 정보은닉 ( 객체에 대한 중요한 정보를 외부로 노출시키지 않도록 하기 위한 기법 ), 변경하기 쉬운 객체 ( 객체와 객체 사이의 결합도를 낮출 수 있기 때문에 설계 변경 수월 )
Javascript, python 지원 x , c#/JAVA/Typescript 등 지원
Private: 접근 제한자(Access modifier)
-> 클래스 외부에서는 어떠한 방법으로도 직접 접근 불가/ 오로지 setter만 변수를 변경할 수 있고, getter만 변수를 조회 가능
상속 (Inheritance):
이미 정의된 상위 클래스의 특징을 하위 클래스에서 물려받아 코드의 중복을 제거하고 코드 재사용성을 증대
하나의 클래스가 가진 특징(함수, 변수 및 데이터)을 다른 클래스가 그대로 물려 받는 것
개별 클래스를 상속 관계로 묶음으로써 클래스 간의 체계화된 구조를 파악 용이
데이터와 메소드를 변경할 때 상위에 있는 것만 수정하여 전체적으로 일관성을 유지
class Child extends Mother{ // Mother 클래스를 상속받은 Child 자식 클래스
constructor(name, age, tech) { // 자식 클래스 생성자
super(name, age, tech); // 부모 클래스의 생성자를 호출
}
}
추상화 (Abstraction):
객체에서 공통된 부분을 모아 상위 개념으로 새롭게 선언하는 것
불필요한 부분을 생략하고 객체 속성 중 공통적이고 중요한 것에만 중점을 두어 모델화 하는 것
객체들의 공통적인 특성을 파악하여 필요 없는 특성을 제거하는 과정
시스템을 구축하기 전에 시스템 구조 및 구성을 가시적으로 볼 수 있고, 해당 시스템과 유사한 모델을 만들어 여러가지 테스트
복잡한 내부 구현에 신경쓰지 않고, 외부에 노출되어 있는 인터페이스만을 이용하여 코드를 작성
클래스를 설계할 때 공통적으로 묶일 수 있는 기능을 추상화 → 추상 클래스 → 인터페이스 { : 클래스를 정의할 때 메소드와 속성만 정의하여 인터페이스에 선언된 프로퍼티 또는 메소드의 구현을 강제하여 코드의 일관성을 유지하도록 하는 것 } 로 모델링해서 향후 다형성(Polymorphism)으로 확장할 수 있도록 설계
동일한 인터페이스를 상속받은 클래스는 해당 인터페이스 내부에 선언되어 있는 프로퍼티와 메소드가 구현되어 있다는것
다형성 (Polymorphism):
객체(클래스)가 연산을 수행하게 될 때 하나의 행위에 대해 각 객체가 가지고 있는 고유한 특성으로 다른 여러 형태로 재구성 되는 것
동일한 메소드의 이름을 사용하지만 메소드에 대해 클래스마다 다르게 구현
역할(인터페이스)과 구현을 분리해서 오버라이딩(Overriding)을 통해 서비스의 구현기능을 유연하게 변경, 확장이 가능
오버로딩(Overloading), 오버라이딩(Overriding)가 대표적인 다형성의 예시
의존성 (Dependency):
객체(모듈 및 클래스)들이 협력하는 과정 속에서 해당 객체들이 다른 객체를 의존하게 되는 정도
하나의 객체가 변경될 경우 의존하고 있는 다른 객체 또한 변경될수 있음
결합도 (Coupling):
의존성의 정도
응집도 (Cohesion):
모듈에 포함된 내부 요소들이 각각 연관되어 있는 관계의 정도
구조적 프로그래밍 (Structured Programming)
: 제어 흐름의 직접적인 전환에 대한 규칙을 제시
기능을 중심적으로 개발을 진행
프로그래밍이라는 기술이 시작되면서 가장 처음으로 적용된 패러다임
객체 지향 프로그래밍 (Object-Oriented Programming, OOP)
: 제어흐름의 간접적인 전환에 대한 규칙을 제시
프로그램의 처리단위가 객체
“현실 세계를 모델링”하는 대표적인 프로그래밍 패러다임
함수형 프로그래밍 (Functional Programming)
: 할당문에 대한 규칙을 제시
함수를 중심적으로 개발을 진행
3가지의 패러다임 중 가장 처음 만들어졌지만 최근들어 겨우 도입되기 시작하는 패러다임
: 데이터와 프로세스가 동일한 모듈 내부에 위치하도록 프로그래밍하는 방식
붕어빵틀: 클래스 / 밀가루반죽,팥: 자원 / 객체: 붕어빵
코드 추상화 -> 직관적 사고
현실세계의 객체를 유연하게 표현가능
객체: 어떠한 특성을 가지며 특정 기능 수행
장점
의존성을 효율적으로 통제 -> 요구사항 변경에 좀 더 수월하게 대응 가능
동작기준보다 데이터 중심 -> 코드의 덩치가 커져도 일관성 유지 용이
이해하기 쉽고, 객체 내부 변경이 주는 객체 외부에 영향 제어가능해 변경이 수월
데이터와 프로세세스를 하나의 단위로 통합해 놓은 방식
데이터와 프로세스가 동일한 객체 안에 있다면 객체지향프로그래밍 방식일 확률 多
객체 지향 설계
요구하는 기능을 온전히 수행하면서 추후의 변경을 매끄럽게 수용할 수 있음
변경가능한 코드 == 이해하기 쉬운 코드
변경하기 쉬운 설계 == 하나의 클래스만 변경할 수 있는 설계
핵심: 캡슐화 -> 의존성 관리 -> 결합도 낮춤
: 프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 사용
단일 책임의 원칙 (Single Responsibility Principle, SRP)
: 하나의 객체는 단 하나의 책임을 가져야 한다
즉 클래스나 모듈을 변경할 이유가 단 하나 뿐이어야 한다
SRP : 책임 -> 적절한 클래스의 크기
개방-폐쇄 원칙 (Open-Closed Principle, OCP)
: 소프트웨어 엔티티 또는 개체(클래스, 모듈, 함수 등)는 확장에는 열림, 변경에는 닫힘
즉 소프트웨어 개체의 행위는 확장 가능, 개체 변경 불가
기존코드에 영향을 주지 않고 새로운 기능이나 구성요소 추가 가능해야
요구사항 확장에 수정사항이 많으면 개발코스트 증가 (안좋음)
리스코프 치환 원칙 (Liskov substitution principle, LSP)
: 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다
부모 클래스와 자식 클래스가 있는 경우 서로를 바꾸더라도 해당 프로그램에서 잘못된 결과를 도출하지 않는 것
인터페이스 분리 원칙 (Interface segregation principle, ISP)
: 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다
사용자가 필요하지 않은 기능을 가진 인터페이스에 의존 x, 최대한 인터페이스를 작게 유지
불필요한 짐을 실은 인터페이스에 의존하게 된다면 예상치도 못한 문제에 빠질 수 있다
의존성 역전 원칙 (Dependency Inversion Principle, DIP)
: 프로그래머는 추상화에 의존 o, 구체화에 의존 x
고수준 계층의 모듈(도메인)은 저수준 계층의 모듈(하부구조)에 의존해서는 안된다. 둘 다 추상화에 의존해야
추상화는 세부 사항에 의존해서는 안 된다. 세부 사항은 추상화에 의존해야