요약
OOP(객체 지향 프로그래밍) : 문제를 여러 객체로 분할하여 작업하는 프로그래밍 패러다임을 의미합니다. 객체는 데이터와 기능을 하나로 묶은 그룹이며, 객체들은 상호작용하여 문제를 해결합니다. OOP의 특징으로는 캡슐화, 추상화, 상속, 다형성 등이 있습니다.
다형성 : 다형성은 같은 이름의 메소드가 클래스나 객체에 따라 다르게 동작하는 개념을 나타냅니다
- 오버로드 : 같은 이름의 메소드가 다양한 매개변수로 다르게 작동
- 오버라이드 : 자식 클래스에서 부모 클래스의 메소드를 다시 정의
SOLID 원칙 : 소프트웨어를 설계함에 있어 이해하기 쉽고, 유연하고, 유지보수가 편하도록 도와주는 5가지의 원칙을 의미한다.
- Single Responsibility Principle (단일 책임 원칙): 소프트웨어의 설계 부품(클래스/함수 등)는 단 하나의 책임만 가져야 합니다. 이를 통해 코드의 응집도를 높이고 결합도를 낮춥니다.
- Open-Closed Principle (개방-패쇄 원칙): 기존 코드를 수정하지 않고 새로운 기능을 추가하거나 변경할 수 있도록 설계해야 합니다. 즉, 확장에는 열려 있고 변경에는 닫혀 있어야 합니다.
- Liskov Substitution Principle (리스코프 치환 원칙): 자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야 합니다. 즉, 하위 객체를 상위 객체로 대체해도 일관성 있는 동작을 해야 합니다.
- Dependency Inversion Principle (의존 역전 원칙): 추상화에 의존하도록 하여 상위 모듈과 하위 모듈 간의 의존 관계를 최소화하고 유연한 설계를 만들어야 합니다.
- Interface Segregation Principle (인터페이스 분리 원칙): 한 클래스는 사용하지 않는 인터페이스를 구현하지 않아야 하며, 다수의 구체적인 인터페이스보다 하나의 일반적인 인터페이스가 낫습니다.
OOP(Object Oriented Programming, 객체 지향 프로그래밍)
OOP란 문제를 여러 개의 객체로 나눠 작업하는 방식으로, 객체들이 서로 유기적으로 상호작용하는 프로그래밍 이론이다(대표적으로 Java와 C#)
- 객체 : 프로그래밍에서의 객체는 데이터의 분산을 막기 위해 데이터와 기능을 하나로 묶은 그룹
- 절차 지향 프로그래밍 vs 객체 지향 프로그래밍
ㅤ | 절차 지향 프로그래밍 | 객체 지향 프로그래밍 |
방식 | 문제를 여러 개의 함수로 나누어 순차적으로 호출하여 처리하는 방식 | 문제를 여러 개의 객체로 나누어 처리하는 방식 |
장점 | 컴퓨터의 처리구조와 유사해 실행속도가 빠르다 | 코드의 재활용성이 높다.
간편하고 디버깅이 쉽다 |
단점 | 유지보수가 어렵다.
코드의 순서가 바뀌면 동일한 결과를 보장하기 어렵다. | 처리속도가 절차지향보다 느리다
설계에 많은 시간소요가 들어갑니다. |
예 | C | Java, C# |
OOP 특징
- 캡슐화(Encapsulation)
- 데이터와 데이터를 처리하는 메서드를 하나의 캡슐 형태로 만드는 방법이다,
- 데이터를 외부에서 직접 접근하지 않고 메서드를 통해서만 접근한다 (변수를 private로 선언하여 데이터를 보호하고, 보호된 변수는 getter나 setter 등의 메서드를 통해서만 간접적으로 접근을 허용한다)
- 캡슐화를 하면 데이터와 코드의 형태를 외부에서 알 수 없게하여 정보를 감출 수 있기 때문에, 정보은닉을 할 수 있다는 특징이 있다.
- 추상화(Abstraction)
- 객체의 공통적인 속성과 기능을 추출하여 정의하는 것을 의미합니다.
- 클래스는 객체들이 어떤 특징들이 있어야 한다고 정의하는 추상화된 개념이다.
- 상속(Inheritance)
- 자식 클래스가 부모 클래스의 특성과 기능을 물려받는 것을 의미합니다.
- 자식 클래스가 부모 클래스의 코드를 재사용 및 확장하는 것입니다.
- • 상속은 캡슐화를 유지, 클래스의 재사용이 용이하도록 해 준다.
- 다형성(Polymorphism)
- 같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 구현된다.
- 오버로드(overload)와 오버라이드(override)이 다향성의 대표적인 예
- 오버로딩 : 하나의 클래스 안에서 같은 이름의 메서드를 사용하지만 각 메서드마다 다른 용도로 사용되며 그 결과물도 다르게 구현할 수 있게 만드는 개념인데 오버로딩이 가능하려면 메서드끼리 이름은 같지만 매개변수의 갯수나 데이터타입이 다르면 오버로딩이 적용되어 메서드 이름이 같아도 문법 에러가 나지 않습니다.
- 오버라이딩 : 부모클래스에서 상속받은 서브클래스 즉 자식클래스에서 부모클래스, 즉 상위클래스에서 만들어진 메서드를 자신의 입맛대로 다시 재창조해서 사용하는 것을 말합니다.
OOP 장점
동일하게 반복하여 사용하는 코드를 줄여서 유지보수에 용이함
- 코드의 재사용성 증가
- 상속을 통해 코드의 재사용성을 높일 수 있다
- 생산성 향상
- 잘 설계된 클래스를 만들어서 독립적인 객체를 사용함으로써 개발의 생산성을 향상시킬 수 있다
- 자연적인 모델링
- 생각하는 것을 그대로 자연스럽게 구현할 수 있다
- 유지보수의 우수성
- 프로그램을 변경할 때 수정, 추가를 하더라도 캡슐화를 통해 주변 코드에 영향이 적기 때문에 유지보수가 용이합니다.
OOP 단점
- 개발속도가 느림(설계에 많은 시간 소요)
- 개체가 처리하려는 것에 대한 정확한 이해가 필요하기에 설계단계부터 많은 시간이 소요된다.
- 실행속도가 느림
- 객체지향언어(C++, JAVA 등)는 상대적으로 실행 속도가 느립니다.
- 프로그램 용량이 큼
- 객체 단위로 프로그램을 많이 만들다보면, 불필요한 정보들이 같이 삽입될 수 있고, 이는 프로그램의 용량 증가로 이어질 수 있습니다.
SOLID
SOLID 원칙
SOLID 원칙은 소프트웨어를 설계함에 있어 이해하기 쉽고, 유연하고, 유지보수가 편하도록 도와주는 5가지의 원칙을 의미한다.
1. Single Responsiblity Principle (단일 책임 원칙)
소프트웨어의 설계 부품(클래스, 함수 등)은 단 하나의 책임(기능)만을 가져야 한다.
설계를 잘한 프로그램은 기본적으로 새로운 요구사항와 프로그램 변경에 영향을 받는 부분이 적다.응집도는 높고 결합도는 낮은 프로그램을 뜻한다. 만약 한 클래스가 수행할 수 있는 기능, 즉 책임이 많아지면 클래스 내부의 함수끼리 강한 결합을 발생할 가능성이 높아진다. 이는 유지보수에 비용이 증가하게 되므로 책임을 분리시킬 필요가 있다.
2. Open-Closed Principle (개방-패쇄 원칙)
기존의 코드를 변경하지 않고(Closed) 기능을 수정하거나 추가할 수 있도록(Open) 설계해야 한다.
소프트웨어의 구성요소(컴포넌트, 클래스, 모듈, 함수)가 확장에 대해서는 유연하여야 하지만 수정에 대해서는 폐쇄적이어야 함을 의미한다. 다시 말해 새 기능이 필요할 때 기존에 작성하고 테스트했던 코드를 수정하지 않고 추가할 수 있어야 한다는 것이다.
3. Liskov Substitution Principle (리스코프 치환 원칙)
자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다.
상위 타입은 항상 하위 타입으로 대체할 수 있어야 함을 의미한다. 다시 말해 어떤 하위 객체에 접근할 때 그 상위 객체의 인터페이스로 접근하더라도 아무런 문제가 없이 일관성 있는 행동을 해야 한다. 메소드의 사전 조건과 사후 측면에서 보면 사전 조건은 축소되지 않아야 하며, 사후 조건은 확대되지 않아야 한다.2 이를 준수하지 않으면 하위 객체를 상위 클래스 타입으로 활용할 때, 당장은 괜찮을 수 있어도 나중에 문제가 발견될 수 있다.
4. Dependency Inversion Principle (의존 역전 원칙)
의존 관계를 맺을 때, 변화하기 쉬운것 보단 변화하기 어려운 것에 의존해야 한다는 원칙이다.
상위 모듈이 하위 모듈에 종속성을 가져서는 안 되며, 양쪽 모두 추상화에 의존해야 함을 의미한다. 풀어 설명하자면 하위 레벨 모듈의 변경이 상위 레벨 모듈의 변경을 요구하는 구조적 문제에서 발생하는 위계관계를 끊는 것이다. 실제 사용 관계는 바뀌지 않으며, 추상을 매개로 메시지를 주고 받음으로써 관계를 최대한 느슨하게 만드는 원칙이다.
5. Interface Segregation Principle (인터페이스 분리 원칙)
한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다.
필요하지 않는 요소를 구현하도록 강요하거나 사용하지 않는 요소에 의존하도록 만들면 안 된다는 것을 의미한다. 다시 말해 어떤 클래스가 다른 클래스에 종속될 때에는 가능한 최소한의 인터페이스만을 사용해야 한다. 인터페이스의 단일 책임을 강조한다고도 볼 수 있다.